int
ZZErrorEstimator :: estimateError(EE_ErrorMode mode, TimeStep *tStep)
{
    int nelems = this->domain->giveNumberOfElements();
    ZZErrorEstimatorInterface *interface;
    double sNorm;
    InternalStateType type = IStype;

    if ( mode == temporaryEM ) {
        type = IST_StressTensorTemp;                  // OOFEM_ERROR("temporaryEM mode not supported");
    }

    if ( this->stateCounter == tStep->giveSolutionStateCounter() ) {
        return 1;
    }

    NodalRecoveryModel *oldSmoother, *rm = NULL;
    if ( this->nodalRecoveryType == ZZRecovery ) {
        rm = new ZZNodalRecoveryModel(this->domain);
    } else if ( this->nodalRecoveryType == SPRRecovery ) {
        rm = new SPRNodalRecoveryModel(this->domain);
    } else {
        OOFEM_ERROR("unknown nodal recovery type");
    }

    // first set the domain Smoother to suitable one, keep old one to be recovered
    oldSmoother = this->domain->giveSmoother();
    this->domain->setSmoother(rm, 0); // do not delete old one

    // create a new set containing all elements
    Set elemSet(0, this->domain);
    elemSet.addAllElements();
    // recover nodal values on entire elemSet (domain)
    rm->recoverValues(elemSet, type, tStep);

#ifdef ZZErrorEstimator_ElementResultCashed
    this->eNorms.resize(nelems);
 #ifdef EXPERIMENT
    sNorms.resize(nelems);
 #endif
#else
    double eNorm;
#endif

    this->globalENorm = this->globalSNorm = 0.0;
    // loop over domain's elements
    for ( int ielem = 1; ielem <= nelems; ielem++ ) {
        if ( this->skipRegion( this->domain->giveElement(ielem)->giveRegionNumber() ) ) {
            continue;
        }

        interface = static_cast< ZZErrorEstimatorInterface * >( this->domain->giveElement(ielem)->giveInterface(ZZErrorEstimatorInterfaceType) );
        if ( interface == NULL ) {
            OOFEM_ERROR("Element has no ZZ error estimator interface defined");
        }

#ifdef ZZErrorEstimator_ElementResultCashed
        interface->ZZErrorEstimatorI_computeElementContributions(eNorms.at(ielem), sNorm, this->normType, type, tStep);
        this->globalENorm += eNorms.at(ielem) * eNorms.at(ielem);
 #ifdef EXPERIMENT
        sNorms.at(ielem) = sNorm;
 #endif
#else
        interface->ZZErrorEstimatorI_computeElementContributions(eNorm, sNorm, this->normType, type, tStep);
        this->globalENorm += eNorm * eNorm;
#endif
        this->globalSNorm += sNorm * sNorm;
    }

    FloatArray gnorms;
    ParallelContext *parallel_context = this->domain->giveEngngModel()->giveParallelContext(this->domain->giveNumber());
    parallel_context->accumulate({this->globalENorm, this->globalSNorm}, gnorms);
    this->globalENorm = gnorms [ 0 ];
    this->globalSNorm = gnorms [ 1 ];
    

    // recover the stored smoother
    this->domain->setSmoother(oldSmoother); //delete old one (the rm)

    // report the error estimate
    double pe = sqrt( this->globalENorm / ( this->globalENorm + this->globalSNorm ) );
    OOFEM_LOG_RELEVANT("Relative stress error estimate: %5.2f%%\n", pe * 100.0);

    this->globalENorm = sqrt(this->globalENorm);
    this->globalSNorm = sqrt(this->globalSNorm);
    this->globalErrorEstimate = pe;


    this->stateCounter = tStep->giveSolutionStateCounter();
    return 1;
}
Exemple #2
0
int
Structural3DElement :: computeLoadLSToLRotationMatrix(FloatMatrix &answer, int, GaussPoint *)
{
    OOFEM_ERROR("surface local coordinate system not supported");
    return 1;
}
Exemple #3
0
void
SUPGElement2 :: computeSurfaceLoadVector_MC(FloatArray &answer, Load *load, int id, TimeStep *tStep)
{
    OOFEM_ERROR("not implemented");
}
Exemple #4
0
void
XFEMStatic :: terminate(TimeStep *tStep)
{
    this->doStepOutput(tStep);
    this->printReactionForces(tStep, 1);
    // update load vectors before storing context
    fflush( this->giveOutputStream() );
    this->updateLoadVectors(tStep);
    this->saveStepContext(tStep);

    // Propagate fronts
    for ( auto &domain: domainList ) {
        XfemManager *xMan = domain->giveXfemManager();
        xMan->propagateFronts();
    }


    // Update element subdivisions if necessary
    // (e.g. if a crack has moved and cut a new element)
    for ( int domInd = 1; domInd <= this->giveNumberOfDomains(); domInd++ ) {
        Domain *domain = this->giveDomain(domInd);

        // create a new set containing all elements
        Set elemSet(0, domain);
        elemSet.addAllElements();

        if ( domain->giveXfemManager()->hasPropagatingFronts() || mForceRemap ) {
            // If domain cloning is performed, there is no need to
            // set values from the dof map.
            mSetValsFromDofMap = false;

            // Take copy of the domain to allow mapping of state variables
            // to the new Gauss points.
            Domain *dNew = domain->Clone();

            bool deallocateOld = false;
            setDomain(1, dNew, deallocateOld);
            forceEquationNumbering();

            // Map primary variables
            LSPrimaryVariableMapper primMapper;
            FloatArray u;
            primMapper.mapPrimaryVariables(u, * domain, * dNew, VM_Total, * tStep);


            if ( totalDisplacement.giveSize() == u.giveSize() ) {
                FloatArray diff;
                diff.beDifferenceOf(totalDisplacement, u);

                printf( "diff norm: %e\n", diff.computeNorm() );
            }

            totalDisplacement = u;


            primMapper.mapPrimaryVariables(incrementOfDisplacement, * domain, * dNew, VM_Incremental, * tStep);


            int numEl = dNew->giveNumberOfElements();

            for ( int i = 1; i <= numEl; i++ ) {
                ////////////////////////////////////////////////////////
                // Map state variables for regular Gauss points
                StructuralElement *el = dynamic_cast< StructuralElement * >( dNew->giveElement(i) );
                el->createMaterialStatus();
                el->mapStateVariables(* domain, * tStep);


                ////////////////////////////////////////////////////////
                // Map state variables for cohesive zone if applicable
                XfemStructuralElementInterface *xFemEl = dynamic_cast< XfemStructuralElementInterface * >(el);
                if ( xFemEl != NULL ) {
                    if ( xFemEl->mpCZMat != NULL ) {
                        size_t numCzRules = xFemEl->mpCZIntegrationRules.size();

                        for ( size_t czIndex = 0; czIndex < numCzRules; czIndex++ ) {
                            if ( xFemEl->mpCZIntegrationRules [ czIndex ] != NULL ) {
                                for ( GaussPoint *gp: *xFemEl->mpCZIntegrationRules [ czIndex ] ) {

                                    MaterialStatus *ms = xFemEl->mpCZMat->giveStatus(gp);
                                    if ( ms == NULL ) {
                                        OOFEM_ERROR("Failed to fetch material status.");
                                    }

                                    MaterialStatusMapperInterface *interface = dynamic_cast< MaterialStatusMapperInterface * >
                                                                               ( xFemEl->mpCZMat->giveStatus(gp) );

                                    if ( interface == NULL ) {
                                        OOFEM_ERROR("Failed to fetch MaterialStatusMapperInterface.");
                                    }


                                    MaterialStatus *matStat = dynamic_cast< MaterialStatus * >( xFemEl->mpCZMat->giveStatus(gp) );
                                    StructuralInterfaceMaterialStatus *siMatStat = dynamic_cast< StructuralInterfaceMaterialStatus * >(matStat);
                                    if ( siMatStat == NULL ) {
                                        OOFEM_ERROR("Failed to cast to StructuralInterfaceMaterialStatus.");
                                    }
                                    interface->MSMI_map_cz(* gp, * domain, elemSet, * tStep, * siMatStat);
                                }
                            }
                        }
                    }
                }
            }


            delete domain;
            domain = this->giveDomain(1);

            // Set domain pointer to various components ...
            this->nMethod->setDomain(domain);

            int numExpModules = this->exportModuleManager->giveNumberOfModules();
            for ( int i = 1; i <= numExpModules; i++ ) {
                //  ... by diving deep into the hierarchies ... :-/
                VTKXMLExportModule *vtkxmlMod = dynamic_cast< VTKXMLExportModule * >( this->exportModuleManager->giveModule(i) );
                if ( vtkxmlMod != NULL ) {
                    vtkxmlMod->giveSmoother()->setDomain(domain);
                    vtkxmlMod->givePrimVarSmoother()->setDomain(domain);
                }
            }


            this->setUpdateStructureFlag(true);
        } // if( domain->giveXfemManager()->hasPropagatingFronts() )

        //#endif
    }

    // Fracture/failure mechanics evaluation
    for ( auto &domain: domainList ) {
        if ( domain->hasFractureManager() ) { // Will most likely fail if numDom > 1
            FractureManager *fracMan = domain->giveFractureManager();
            fracMan->evaluateYourself(tStep);
            fracMan->updateXFEM(tStep); // Update XFEM structure based on the fracture manager

            this->setUpdateStructureFlag( fracMan->giveUpdateFlag() ); // if the internal structure need to be updated
        }
    }
}
Exemple #5
0
void
IDGMaterial :: giveRealStressVectorGrad(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalCumulatedStrain, TimeStep *tStep)
//
// returns real stress vector in 3d stress space of receiver according to
// previous level of stress and current
// strain increment, the only way, how to correctly update gp records
//
{
    IDGMaterialStatus *status = static_cast< IDGMaterialStatus * >( this->giveStatus(gp) );
    LinearElasticMaterial *lmat = this->giveLinearElasticMaterial();
    FloatArray reducedTotalStrainVector, strain;

    FloatMatrix de;
    double f, equivStrain, tempKappa = 0.0, omega = 0.0;

    //this->initGpForNewStep(gp);
    this->initTempStatus(gp);
    
    // subtract stress independent part
    // note: eigenStrains (temperature) is not contained in mechanical strain stored in gp
    // therefore it is necessary to subtract always the total eigen strain value
    this->giveStressDependentPartOfStrainVector(reducedTotalStrainVector, gp, totalStrain, tStep, VM_Total);


    // compute equivalent strain
    this->computeEquivalentStrain(equivStrain, reducedTotalStrainVector, gp, tStep);

    if ( llcriteria == idm_strainLevelCR ) {
        // compute value of loading function if strainLevel crit apply
        f = nonlocalCumulatedStrain - status->giveKappa();

        if ( f <= 0.0 ) {
            // damage does not grow
            tempKappa = status->giveKappa();
            omega     = status->giveDamage();
        } else {
            // damage grow
            this->initDamaged(tempKappa, reducedTotalStrainVector, gp);
            // evaluate damage parameter
            this->computeDamageParam(omega, nonlocalCumulatedStrain, reducedTotalStrainVector, gp);
        }
    } else if ( llcriteria == idm_damageLevelCR ) {
        // evaluate damage parameter first
        tempKappa = nonlocalCumulatedStrain;
        this->initDamaged(tempKappa, strain, gp);
        this->computeDamageParam(omega, tempKappa, reducedTotalStrainVector, gp);
        if ( omega < status->giveDamage() ) {
            // unloading takes place
            omega = status->giveDamage();
            //printf (".");
        }
    } else {
        OOFEM_ERROR("unsupported loading/uloading criteria");
    }


    lmat->giveStiffnessMatrix(de, SecantStiffness, gp, tStep);
    de.times(1.0 - omega);
    answer1.beProductOf(de, strain);
    answer2 = equivStrain;

    // update gp

    status->letTempStrainVectorBe(totalStrain);
    status->letTempStressVectorBe(answer1);
    status->setNonlocalCumulatedStrain(nonlocalCumulatedStrain);
    status->setTempKappa(tempKappa);
    status->setTempDamage(omega);
}
void
NonlocalMaterialExtensionInterface :: buildNonlocalPointTable(GaussPoint *gp)
{
    double weight, elemVolume, integrationVolume = 0.;

    NonlocalMaterialStatusExtensionInterface *statusExt =
        static_cast< NonlocalMaterialStatusExtensionInterface * >( gp->giveMaterialStatus()->
                                                                  giveInterface(NonlocalMaterialStatusExtensionInterfaceType) );
    std :: list< localIntegrationRecord > *iList;

    Element *ielem;
    IntegrationRule *iRule;

    if ( !statusExt ) {
        OOFEM_ERROR("local material status encountered");
    }

    if ( !statusExt->giveIntegrationDomainList()->empty() ) {
        return;                                                  // already done
    }

    iList = statusExt->giveIntegrationDomainList();

    FloatArray gpCoords, jGpCoords, shiftedGpCoords;
    SpatialLocalizer :: elementContainerType elemSet;
    if ( gp->giveElement()->computeGlobalCoordinates( gpCoords, gp->giveNaturalCoordinates() ) == 0 ) {
        OOFEM_ERROR("computeGlobalCoordinates of target failed");
    }

    // If nonlocal variation is set to the distance-based approach, a new nonlocal radius
    // is calculated as a function of the distance from the Gauss point to the nonlocal boundaries
    if ( nlvar == NLVT_DistanceBasedLinear || nlvar == NLVT_DistanceBasedExponential ) {
        //      cl=cl0;
        cl = giveDistanceBasedInteractionRadius(gpCoords);
        suprad = evaluateSupportRadius();
    }

    // If the mesh represents a periodic cell, nonlocal interaction is considered not only for the real neighbors
    // but also for their periodic images, shifted by +px or -px in the x-direction. In the implementation,
    // instead of shifting the potential neighbors, we shift the receiver point gp. In the non-periodic case (typical),
    // px=0 and the following loop is executed only once.  

    int ix, nx = 0; // typical case
    if ( px > 0. ) nx = 1; // periodicity taken into account

    for (ix=-nx; ix<=nx; ix++) { // loop over periodic images shifted in x-direction

      shiftedGpCoords = gpCoords;
      shiftedGpCoords.at(1) += ix*px;

    // ask domain spatial localizer for list of elements with IP within this zone
#ifdef NMEI_USE_ALL_ELEMENTS_IN_SUPPORT
    this->giveDomain()->giveSpatialLocalizer()->giveAllElementsWithNodesWithinBox(elemSet, shiftedGpCoords, suprad);
    // insert element containing given gp
    elemSet.insert( gp->giveElement()->giveNumber() );
#else
    this->giveDomain()->giveSpatialLocalizer()->giveAllElementsWithIpWithinBox_EvenIfEmpty(elemSet, shiftedGpCoords, suprad);
#endif
    // initialize iList

    for ( auto elindx: elemSet ) {
        ielem = this->giveDomain()->giveElement(elindx);
        if ( regionMap.at( ielem->giveRegionNumber() ) == 0 ) {
            iRule = ielem->giveDefaultIntegrationRulePtr();
            for ( GaussPoint *jGp: *iRule ) {
                if ( ielem->computeGlobalCoordinates( jGpCoords, jGp->giveNaturalCoordinates() ) ) {
                    weight = this->computeWeightFunction(shiftedGpCoords, jGpCoords);

                    //manipulate weights for a special averaging of strain (OFF by default)
                    this->manipulateWeight(weight, gp, jGp);

                    this->applyBarrierConstraints(shiftedGpCoords, jGpCoords, weight);
#ifdef NMEI_USE_ALL_ELEMENTS_IN_SUPPORT
                    if ( 1 ) {
#else
                    if ( weight > 0. ) {
#endif
                        localIntegrationRecord ir;
                        ir.nearGp = jGp;  // store gp
                        elemVolume = weight * jGp->giveElement()->computeVolumeAround(jGp);
                        ir.weight = elemVolume; // store gp weight
                        iList->push_back(ir); // store own copy in list
                        integrationVolume += elemVolume;
                    }
                } else {
                    OOFEM_ERROR("computeGlobalCoordinates of target failed");
                }
            }
        }
    } // loop over elements
    }

    statusExt->setIntegrationScale(integrationVolume); // store scaling factor

    /*
     * // Old implementation without spatial localizer
     *
     * FloatArray jGpCoords;
     * for (i=1; i<=nelem; i++) {
     * ielem = this->giveDomain()->giveElement(i);
     * if (regionMap.at(ielem->giveRegionNumber()) == 0) {
     * iRule = ielem->giveDefaultIntegrationRulePtr ();
     * for (GaussPoint *jGp: *iRule ) {
     * if (ielem->computeGlobalCoordinates (jGpCoords, *(jGp->giveCoordinates()))) {
     *   weight = this->computeWeightFunction (gpCoords, jGpCoords);
     *   if (weight > NonlocalMaterialZeroWeight) {
     *    localIntegrationRecord ir;
     *    ir.nearGp = jGp;                   // store gp
     *    elemVolume = weight * jGp->giveElement()->computeVolumeAround (jGp);
     *    ir.weight = elemVolume;            // store gp weight
     *    iList->append(ir); // store own copy in list
     *    integrationVolume += elemVolume;
     *   }
     * } else OOFEM_ERROR("computeGlobalCoordinates failed");
     * }
     * }
     * } // loop over elements
     * statusExt->setIntegrationScale (integrationVolume); // remember scaling factor
     */
}

void
NonlocalMaterialExtensionInterface :: rebuildNonlocalPointTable(GaussPoint *gp, IntArray *contributingElems)
{
    double weight, elemVolume, integrationVolume = 0.;

    NonlocalMaterialStatusExtensionInterface *statusExt =
        static_cast< NonlocalMaterialStatusExtensionInterface * >( gp->giveMaterialStatus()->
                                                                  giveInterface(NonlocalMaterialStatusExtensionInterfaceType) );
    std :: list< localIntegrationRecord > *iList;

    Element *ielem;
    IntegrationRule *iRule;

    if ( !statusExt ) {
        OOFEM_ERROR("local material status encountered");
    }

    iList = statusExt->giveIntegrationDomainList();
    iList->clear();

    if ( contributingElems == NULL ) {
        // no element table provided, use standard method
        this->buildNonlocalPointTable(gp);
    } else {
        FloatArray gpCoords, jGpCoords;
        int _size = contributingElems->giveSize();
        if ( gp->giveElement()->computeGlobalCoordinates( gpCoords, gp->giveNaturalCoordinates() ) == 0 ) {
            OOFEM_ERROR("computeGlobalCoordinates of target failed");
        }

        //If nonlocal variation is set to the distance-based approach calculates  new nonlocal radius
        // based on the distance from the nonlocal boundaries
        if ( nlvar == NLVT_DistanceBasedLinear || nlvar == NLVT_DistanceBasedExponential ) {
            cl = cl0;
            cl = giveDistanceBasedInteractionRadius(gpCoords);
            suprad = evaluateSupportRadius();
        }

        // initialize iList
        for ( int _e = 1; _e <= _size; _e++ ) {
            ielem = this->giveDomain()->giveElement( contributingElems->at(_e) );
            if ( regionMap.at( ielem->giveRegionNumber() ) == 0 ) {
                iRule = ielem->giveDefaultIntegrationRulePtr();
                for ( GaussPoint *jGp: *iRule ) {
                    if ( ielem->computeGlobalCoordinates( jGpCoords, jGp->giveNaturalCoordinates() ) ) {
                        weight = this->computeWeightFunction(gpCoords, jGpCoords);

                        //manipulate weights for a special averaging of strain (OFF by default)
                        this->manipulateWeight(weight, gp, jGp);

                        this->applyBarrierConstraints(gpCoords, jGpCoords, weight);
#ifdef NMEI_USE_ALL_ELEMENTS_IN_SUPPORT
                        if ( 1 ) {
#else
                        if ( weight > 0. ) {
#endif
                            localIntegrationRecord ir;
                            ir.nearGp = jGp;     // store gp
                            elemVolume = weight * jGp->giveElement()->computeVolumeAround(jGp);
                            ir.weight = elemVolume; // store gp weight
                            iList->push_back(ir); // store own copy in list
                            integrationVolume += elemVolume;
                        }
                    } else {
                        OOFEM_ERROR("computeGlobalCoordinates of target failed");
                    }
                }
            }
        } // loop over elements

        statusExt->setIntegrationScale(integrationVolume); // remember scaling factor
#ifdef __PARALLEL_MODE
 #ifdef __VERBOSE_PARALLEL
        fprintf( stderr, "%d(%d):", gp->giveElement()->giveGlobalNumber(), gp->giveNumber() );
        for ( auto &lir: iList ) {
            fprintf(stderr, "%d,%d(%e)", lir.nearGp->giveElement()->giveGlobalNumber(), lir.nearGp->giveNumber(), lir.weight);
        }

        fprintf(stderr, "\n");
 #endif
#endif
    }
}


std :: list< localIntegrationRecord > *
NonlocalMaterialExtensionInterface :: giveIPIntegrationList(GaussPoint *gp)
{
    NonlocalMaterialStatusExtensionInterface *statusExt =
        static_cast< NonlocalMaterialStatusExtensionInterface * >( gp->giveMaterialStatus()->
                                                                  giveInterface(NonlocalMaterialStatusExtensionInterfaceType) );

    if ( !statusExt ) {
        OOFEM_ERROR("local material status encountered");
    }

    if ( statusExt->giveIntegrationDomainList()->empty() ) {
        this->buildNonlocalPointTable(gp);
    }

    return statusExt->giveIntegrationDomainList();
}
Exemple #7
0
void
Beam3d :: computeEdgeLoadVectorAt(FloatArray &answer, Load *load, int iedge, TimeStep *tStep, ValueModeType mode)
{
    FloatArray coords, components, endComponents;
    FloatMatrix T;
    double l = this->computeLength();
    double kappay = this->giveKappayCoeff(tStep);
    double kappaz = this->giveKappazCoeff(tStep);
    double fx, fy, fz, fmx, fmy, fmz, dfx, dfy, dfz, dfmx, dfmy, dfmz;

    // evaluates the receivers edge load vector
    // for clamped beam
    //
    BoundaryLoad *edgeLoad = dynamic_cast< BoundaryLoad * >( load );
    if ( edgeLoad ) {

        answer.resize(12);
        answer.zero();

        switch ( edgeLoad->giveApproxOrder() ) {
        case 0:

            if ( edgeLoad->giveFormulationType() == Load :: FT_Entity ) {
                coords.resize(1);
                coords.at(1) = 0.0;
            } else {
                coords = * ( this->giveNode(1)->giveCoordinates() );
            }

            edgeLoad->computeValues(components, tStep, coords, {D_u, D_v, D_w, R_u, R_v, R_w}, mode);

            // prepare transformation coeffs
            if ( edgeLoad->giveCoordSystMode() == Load :: CST_Global ) {
                if ( this->computeLoadGToLRotationMtrx(T) ) {
                    components.rotatedWith(T, 'n');
                }
            }

            fx = components.at(1);
            fy = components.at(2);
            fz = components.at(3);
            fmx = components.at(4);
            fmy = components.at(5);
            fmz = components.at(6);


            answer.at(1) = fx * l / 2.;
            answer.at(2) = fy * l / 2. + fmz / ( 1. + 2. * kappaz );
            answer.at(3) = fz * l / 2. + fmy / ( 1. + 2. * kappay );
            answer.at(4) = fmx * l / 2.;
            answer.at(5) = ( -1. ) * fz * l * l / 12. + fmy * l * kappay / ( 1. + 2. * kappay );
            answer.at(6) = ( 1. ) * fy * l * l / 12. + fmz * l * kappaz / ( 1. + 2. * kappaz );

            answer.at(7) = fx * l / 2.;
            answer.at(8) = fy * l / 2. - fmz / ( 1. + 2. * kappaz );
            answer.at(9) = fz * l / 2. - fmy / ( 1. + 2. * kappay );
            answer.at(10) = fmx * l / 2.;
            answer.at(11) = ( 1. ) * fz * l * l / 12. + fmy * l * kappay / ( 1. + 2. * kappay );
            answer.at(12) = ( -1. ) * fy * l * l / 12. + fmz * l * kappaz / ( 1. + 2. * kappaz );
            break;

        case 1:
            if ( edgeLoad->giveFormulationType() == Load :: FT_Entity ) {
                coords.resize(1);
                coords.at(1) = -1.0;
            } else {
                coords = * ( this->giveNode(1)->giveCoordinates() );
            }

            edgeLoad->computeValues(components, tStep, coords, {D_u, D_v, D_w, R_u, R_v, R_w}, mode);


            // prepare transformation coeffs
            if ( edgeLoad->giveCoordSystMode() == Load :: CST_Global ) {
                if ( this->computeLoadGToLRotationMtrx(T) ) {
                    components.rotatedWith(T, 'n');
                }
            }

            fx = components.at(1);
            fy = components.at(2);
            fz = components.at(3);
            fmx = components.at(4);
            fmy = components.at(5);
            fmz = components.at(6);

            if ( edgeLoad->giveFormulationType() == Load :: FT_Entity ) {
                coords.resize(1);
                coords.at(1) = 1.0;
            } else {
                coords = * ( this->giveNode(2)->giveCoordinates() );
            }

            edgeLoad->computeValues(endComponents, tStep, coords, {D_u, D_v, D_w, R_u, R_v, R_w}, mode);

            // prepare transformation coeffs
            if ( edgeLoad->giveCoordSystMode() == Load :: CST_Global ) {
                if ( T.isNotEmpty() ) {
                    endComponents.rotatedWith(T, 'n');
                }
            }

            // compute differences
            endComponents.subtract(components);

            dfx = endComponents.at(1);
            dfy = endComponents.at(2);
            dfz = endComponents.at(3);
            dfmx = endComponents.at(4);
            dfmy = endComponents.at(5);
            dfmz = endComponents.at(6);


            answer.at(1) = fx * l / 2. + dfx * l / 6.;
            answer.at(2) = fy * l / 2. + dfy * l * ( 20. * kappaz + 9 ) / ( 60. * ( 1. + 2. * kappaz ) ) +
                           fmz / ( 1. + 2. * kappaz ) + dfmz * ( 1. / 2. ) / ( 1. + 2. * kappaz );
            answer.at(3) = fz * l / 2. + dfz * l * ( 20. * kappay + 9 ) / ( 60. * ( 1. + 2. * kappay ) ) +
                           fmy / ( 1. + 2. * kappay ) + dfmy * ( 1. / 2. ) / ( 1. + 2. * kappay );
            answer.at(4) = fmx * l / 2. + dfmx * l / 6.;
            answer.at(5) = ( -1. ) * fz * l * l / 12. - dfz * l * l * ( 5. * kappay + 2. ) / ( 60. * ( 1. + 2. * kappay ) ) +
                           fmy * l * kappay / ( 1. + 2. * kappay ) + dfmy * l * ( 4. * kappay - 1. ) / ( 12. * ( 1. + 2. * kappay ) );
            answer.at(6) = ( 1. ) * fy * l * l / 12. + dfy * l * l * ( 5. * kappaz + 2. ) / ( 60. * ( 1. + 2. * kappaz ) ) +
                           fmz * l * kappaz / ( 1. + 2. * kappaz ) + dfmz * l * ( 4. * kappaz - 1. ) / ( 12. * ( 1. + 2. * kappaz ) );

            answer.at(7) = fx * l / 2. + dfx * l / 3.;
            answer.at(8) = fy * l / 2. + dfy * l * ( 40. * kappaz + 21 ) / ( 60. * ( 1. + 2. * kappaz ) ) -
                           fmz / ( 1. + 2. * kappaz ) - dfmz * ( 1. / 2. ) / ( ( 1. + 2. * kappaz ) );
            answer.at(9) = fz * l / 2. + dfz * l * ( 40. * kappay + 21 ) / ( 60. * ( 1. + 2. * kappay ) ) -
                           fmy / ( 1. + 2. * kappay ) - dfmy * ( 1. / 2. ) / ( ( 1. + 2. * kappay ) );
            answer.at(10) = fmx * l / 2. + dfmx * l / 3.;
            answer.at(11) = ( 1. ) * fz * l * l / 12. + dfz * l * l * ( 5. * kappay + 3. ) / ( 60. * ( 1. + 2. * kappay ) ) +
                            fmy * l * kappay / ( 1. + 2. * kappay ) + dfmy * l * ( 8. * kappay + 1. ) / ( 12. * ( 1. + 2. * kappay ) );
            answer.at(12) = ( -1. ) * fy * l * l / 12. - dfy * l * l * ( 5. * kappaz + 3. ) / ( 60. * ( 1. + 2. * kappaz ) ) +
                            fmz * l * kappaz / ( 1. + 2. * kappaz ) + dfmz * l * ( 8. * kappaz + 1. ) / ( 12. * ( 1. + 2. * kappaz ) );
            break;

        default:
            OOFEM_ERROR("unsupported load type");
        }
    }
}
Exemple #8
0
BasicGeometry *CreateUsrDefGeometry(classType type)
{
    OOFEM_ERROR("CreateUsrDefGeometry: Unknown type\n");
    return NULL;
}
void StaticStructural :: solveYourselfAt(TimeStep *tStep)
{
    int neq;
    int di = 1;

    this->field->advanceSolution(tStep);
    this->field->applyBoundaryCondition(tStep); ///@todo Temporary hack, advanceSolution should apply the boundary conditions directly.

    neq = this->giveNumberOfDomainEquations( di, EModelDefaultEquationNumbering() );
    if (tStep->giveNumber()==1) {
        this->field->initialize(VM_Total, tStep, this->solution, EModelDefaultEquationNumbering() );
    } else {
        this->field->initialize(VM_Total, tStep->givePreviousStep(), this->solution, EModelDefaultEquationNumbering() );
        this->field->update(VM_Total, tStep, this->solution, EModelDefaultEquationNumbering() );
    }

    FloatArray incrementOfSolution(neq), externalForces(neq);

    // Create "stiffness matrix"
    if ( !this->stiffnessMatrix ) {
        this->stiffnessMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) );
        if ( !this->stiffnessMatrix ) {
            OOFEM_ERROR("Couldn't create requested sparse matrix of type %d", sparseMtrxType);
        }

        this->stiffnessMatrix->buildInternalStructure( this, di, EModelDefaultEquationNumbering() );
    }
    this->internalForces.resize(neq);

    this->giveNumericalMethod( this->giveCurrentMetaStep() );
    this->initMetaStepAttributes( this->giveCurrentMetaStep() );

    if ( this->initialGuessType == IG_Tangent ) {
        OOFEM_LOG_RELEVANT("Computing initial guess\n");
        FloatArray extrapolatedForces(neq);
        this->assembleExtrapolatedForces( extrapolatedForces, tStep, TangentStiffnessMatrix, this->giveDomain(di) );
        extrapolatedForces.negated();
        ///@todo Need to find a general way to support this before enabling it by default.
        //this->assembleVector(extrapolatedForces, tStep, LinearizedDilationForceAssembler(), VM_Incremental, EModelDefaultEquationNumbering(), this->giveDomain(di) );
#if 0
        // Some debug stuff:
        extrapolatedForces.printYourself("extrapolatedForces");
        this->internalForces.zero();
        this->assembleVectorFromElements(this->internalForces, tStep, InternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(di));
        this->internalForces.printYourself("internal forces");
#endif
        OOFEM_LOG_RELEVANT("Computing old tangent\n");
        this->updateComponent( tStep, NonLinearLhs, this->giveDomain(di) );
        SparseLinearSystemNM *linSolver = nMethod->giveLinearSolver();
        OOFEM_LOG_RELEVANT("Solving for increment\n");
        linSolver->solve(*stiffnessMatrix, extrapolatedForces, incrementOfSolution);
        OOFEM_LOG_RELEVANT("Initial guess found\n");
        this->solution.add(incrementOfSolution);
        
        this->field->update(VM_Total, tStep, this->solution, EModelDefaultEquationNumbering());
        this->field->applyBoundaryCondition(tStep); ///@todo Temporary hack to override the incorrect values that is set by "update" above. Remove this when that is fixed.
    } else if ( this->initialGuessType != IG_None ) {
        OOFEM_ERROR("Initial guess type: %d not supported", initialGuessType);
    } else {
        incrementOfSolution.zero();
    }

    // Build initial/external load
    externalForces.zero();
    this->assembleVector( externalForces, tStep, ExternalForceAssembler(), VM_Total,
                         EModelDefaultEquationNumbering(), this->giveDomain(1) );
    this->updateSharedDofManagers(externalForces, EModelDefaultEquationNumbering(), LoadExchangeTag);

    if ( this->giveProblemScale() == macroScale ) {
        OOFEM_LOG_INFO("\nStaticStructural :: solveYourselfAt - Solving step %d, metastep %d, (neq = %d)\n", tStep->giveNumber(), tStep->giveMetaStepNumber(), neq);
    }

    double loadLevel;
    int currentIterations;
    NM_Status status = this->nMethod->solve(*this->stiffnessMatrix,
                                            externalForces,
                                            NULL,
                                            this->solution,
                                            incrementOfSolution,
                                            this->internalForces,
                                            this->eNorm,
                                            loadLevel, // Only relevant for incrementalBCLoadVector?
                                            SparseNonLinearSystemNM :: rlm_total,
                                            currentIterations,
                                            tStep);
    if ( !( status & NM_Success ) ) {
        OOFEM_ERROR("No success in solving problem");
    }
}
Exemple #10
0
EnrichmentItem *CreateUsrDefEnrichmentItem(classType type, int number, XfemManager *xm, Domain *domain)
{
    OOFEM_ERROR("CreateUsrDefEnrichmentItem: Unknown type\n");
    return NULL;
}
Exemple #11
0
EnrichmentFunction *CreateUsrDefEnrichmentFunction(classType type, int number, Domain *domain)
{
    OOFEM_ERROR("CreateUsrDefEnrichmentFunction: Unknown type\n");
    return NULL;
}
Exemple #12
0
void UniformGridField::setValues(const FloatArray& vv){
    int s=1;
    for(int i=0; i<div.giveSize(); i++) s*=div[i]+1;
    if(vv.giveSize()!=s) OOFEM_ERROR((std::string("Array size must be exactly prod(div[i]+1)=")+std::to_string(s)).c_str());
    values=vv;
}
Exemple #13
0
NM_Status
SubspaceIteration :: solve(SparseMtrx &a, SparseMtrx &b, FloatArray &_eigv, FloatMatrix &_r, double rtol, int nroot)
//
// this function solve the generalized eigenproblem using the Generalized
// jacobi iteration
//
//
{
    FILE *outStream;
    FloatArray temp, w, d, tt, rtolv, eigv;
    FloatMatrix r;
    int nn, nc1, i, j, k, ij = 0, nite, is;
    double rt, art, brt, eigvt, dif;
    FloatMatrix ar, br, vec;

    GJacobi mtd(domain, engngModel);
    outStream = domain->giveEngngModel()->giveOutputStream();
    nc = min(2 * nroot, nroot + 8);
    //
    // check matrix size
    //
    if ( a.giveNumberOfColumns() != b.giveNumberOfColumns() ) {
        OOFEM_ERROR("matrices size mismatch");
    }

    // check matrix for factorization support
    if ( !a.canBeFactorized() ) {
        OOFEM_ERROR("a matrix not support factorization");
    }

    //
    // check for wery small problem
    //
    nn = a.giveNumberOfColumns();
    if ( nc > nn ) {
        nc = nn;
    }

    ar.resize(nc, nc);
    ar.zero();
    br.resize(nc, nc);
    br.zero();

    //
    // creation of initial iteration vectors
    //
    nc1 = nc - 1;

    w.resize(nn);
    w.zero();
    d.resize(nc);
    d.zero();
    tt.resize(nn);
    tt.zero();
    rtolv.resize(nc);
    rtolv.zero();
    vec.resize(nc, nc);
    vec.zero();                   // eigen vectors of reduced problem

    _r.resize(nn, nroot);
    _eigv.resize(nroot);

    //
    // create work arrays
    //
    r.resize(nn, nc);
    r.zero();
    eigv.resize(nc);
    eigv.zero();

    FloatArray h(nn);
    for ( i = 1; i <= nn; i++ ) {
        h.at(i) = 1.0;
        w.at(i) = b.at(i, i) / a.at(i, i);
    }

    b.times(h, tt);
    for ( i = 1; i <= nn; i++ ) {
        r.at(i, 1) = tt.at(i);
    }

    for ( j = 2; j <= nc; j++ ) {
        rt = 0.0;
        for ( i = 1; i <= nn; i++ ) {
            if ( fabs( w.at(i) ) >= rt ) {
                rt = fabs( w.at(i) );
                ij = i;
            }
        }

        tt.at(j) = ij;
        w.at(ij) = 0.;
        for ( i = 1; i <= nn; i++ ) {
            if ( i == ij ) {
                h.at(i) = 1.0;
            } else {
                h.at(i) = 0.0;
            }
        }

        b.times(h, tt);
        for ( i = 1; i <= nn; i++ ) {
            r.at(i, j) = tt.at(i);
        }
    } // (r = z)

# ifdef DETAILED_REPORT
    printf("SubspaceIteration :: solveYourselfAt: Degrees of freedom invoked by initial vectors :\n");
    tt.printYourself();
    printf("SubspaceIteration :: solveYourselfAt: initial vectors for iteration:\n");
    r.printYourself();
# endif

    //ish = 0;
    a.factorized();
    //
    // start of iteration loop
    //
    for ( nite = 0; ; ++nite ) {               // label 100
# ifdef DETAILED_REPORT
        printf("SubspaceIteration :: solveYourselfAt: Iteration loop no. %d\n", nite);
# endif
        //
        // compute projection ar and br of matrices a , b
        //
        for ( j = 1; j <= nc; j++ ) {
            for ( k = 1; k <= nn; k++ ) {
                tt.at(k) = r.at(k, j);
            }

            //a. forwardReductionWith(&tt) -> diagonalScalingWith (&tt)
            //  -> backSubstitutionWithtt) ;
            a.backSubstitutionWith(tt);

            for ( i = j; i <= nc; i++ ) {
                art = 0.;
                for ( k = 1; k <= nn; k++ ) {
                    art += r.at(k, i) * tt.at(k);
                }

                ar.at(j, i) = art;
            }

            for ( k = 1; k <= nn; k++ ) {
                r.at(k, j) = tt.at(k);                 // (r = xbar)
            }
        }

        ar.symmetrized();        // label 110
#ifdef DETAILED_REPORT
        printf("SubspaceIteration :: solveYourselfAt: Printing projection matrix ar\n");
        ar.printYourself();
#endif
        //
        for ( j = 1; j <= nc; j++ ) {
            for ( k = 1; k <= nn; k++ ) {
                tt.at(k) = r.at(k, j);
            }

            b.times(tt, temp);
            for ( i = j; i <= nc; i++ ) {
                brt = 0.;
                for ( k = 1; k <= nn; k++ ) {
                    brt += r.at(k, i) * temp.at(k);
                }

                br.at(j, i) = brt;
            }                   // label 180

            for ( k = 1; k <= nn; k++ ) {
                r.at(k, j) = temp.at(k);             // (r=zbar)
            }
        }                       // label 160

        br.symmetrized();
#ifdef DETAILED_REPORT
        printf("SubspaceIteration :: solveYourselfAt: Printing projection matrix br\n");
        br.printYourself();
#endif

        //
        // solution of reduced eigenvalue problem
        //
        mtd.solve(ar, br, eigv, vec);

        /// START EXPERIMENTAL
        // solve the reduced problem by Inverse iteration
        /*
         * {
         * FloatMatrix x(nc,nc), z(nc,nc), zz(nc,nc), arinv;
         * FloatArray  w(nc), ww(nc), tt(nc), t(nc);
         * double c;
         * int ii, i,j,k,ac;
         *
         *
         * //  initial setting
         * for (i=1;i<=nc;i++){
         * ww.at(i)=1.0;
         * }
         *
         * for (i=1;i<=nc;i++)
         * for (j=1; j<=nc;j++)
         *   z.at(i,j)=1.0;
         *
         * arinv.beInverseOf (ar);
         *
         * for (i=0;i<nitem;i++) {
         *
         * //  copy zz=z
         * zz = z;
         *
         * // solve matrix equation K.X = M.X
         * x.beProductOf (arinv, z);
         * //  evaluation of Rayleigh quotients
         * for (j=1;j<=nc;j++){
         *   w.at(j) = 0.0;
         *   for (k = 1; k<= nc; k++) w.at(j) += zz.at(k,j)*x.at(k,j);
         * }
         *
         * z.beProductOf (br, x);
         *
         * for (j=1;j<=nc;j++){
         *   c = 0;
         *   for (k = 1; k<= nc; k++) c+= z.at(k,j)*x.at(k,j);
         *   w.at(j) /= c;
         * }
         *
         * //  check convergence
         * ac=0;
         * for (j=1;j<=nc;j++){
         *   if (fabs((ww.at(j)-w.at(j))/w.at(j))< rtol)  ac++;
         *   ww.at(j)=w.at(j);
         * }
         *
         * printf ("\n iterace cislo  %d   %d",i,ac);
         * w.printYourself();
         *
         * //  Gramm-Schmidt ortogonalization
         * for (j=1;j<=nc;j++) {
         *   for (k = 1; k<= nc; k++) tt.at(k) = x.at(k,j) ;
         *   t.beProductOf(br,tt) ;
         *   for (ii=1;ii<j;ii++) {
         *     c = 0.0;
         *     for (k = 1; k<= nc; k++) c += x.at(k,ii)*t.at(k);
         *     for (k = 1; k<= nc; k++) x.at(k,j) -= x.at(k,ii)*c;
         *   }
         *   for (k = 1; k<= nc; k++) tt.at(k) = x.at(k,j) ;
         *   t.beProductOf (br,tt) ;
         *   c = 0.0;
         *   for (k = 1; k<= nc; k++) c += x.at(k,j)*t.at(k);
         *   for (k = 1; k<= nc; k++) x.at(k,j) /= sqrt(c);
         * }
         *
         * if (ac>nroot){
         *   break;
         * }
         *
         * //  compute new approximation of Z
         * z.beProductOf (br,x);
         * }
         *
         * eigv = w;
         * vec = x;
         * }
         * /// END EXPERIMANTAL
         */


        //
        // sorting eigenvalues according to their values
        //
        do {
            is = 0; // label 350
            for ( i = 1; i <= nc1; i++ ) {
                if ( fabs( eigv.at(i + 1) ) < fabs( eigv.at(i) ) ) {
                    is++;
                    eigvt = eigv.at(i + 1);
                    eigv.at(i + 1) = eigv.at(i);
                    eigv.at(i)   = eigvt;
                    for ( k = 1; k <= nc; k++ ) {
                        rt = vec.at(k, i + 1);
                        vec.at(k, i + 1) = vec.at(k, i);
                        vec.at(k, i)   = rt;
                    }
                }
            }                   // label 360
        } while ( is != 0 );

# ifdef DETAILED_REPORT
        printf("SubspaceIteration :: solveYourselfAt: current eigen values of reduced problem \n");
        eigv.printYourself();
        printf("SubspaceIteration :: solveYourselfAt: current eigen vectors of reduced problem \n");
        vec.printYourself();
# endif
        //
        // compute eigenvectors
        //
        for ( i = 1; i <= nn; i++ ) { // label 375
            for ( j = 1; j <= nc; j++ ) {
                tt.at(j) = r.at(i, j);
            }

            for ( k = 1; k <= nc; k++ ) {
                rt = 0.;
                for ( j = 1; j <= nc; j++ ) {
                    rt += tt.at(j) * vec.at(j, k);
                }

                r.at(i, k) = rt;
            }
        }                       // label 420   (r = z)

        //
        // convergency check
        //
        for ( i = 1; i <= nc; i++ ) {
            dif = ( eigv.at(i) - d.at(i) );
            rtolv.at(i) = fabs( dif / eigv.at(i) );
        }

# ifdef DETAILED_REPORT
        printf("SubspaceIteration :: solveYourselfAt: Reached precision of eigenvalues:\n");
        rtolv.printYourself();
# endif
        for ( i = 1; i <= nroot; i++ ) {
            if ( rtolv.at(i) > rtol ) {
                goto label400;
            }
        }

        fprintf(outStream,
                "SubspaceIteration :: solveYourselfAt: Convergence reached for RTOL=%20.15f",
                rtol);
        break;
label400:
        if ( nite >= nitem ) {
            fprintf(outStream, " SubspaceIteration :: solveYourselfAt: Convergence not reached in %d iteration - using current values", nitem);
            break;
        }

        for ( i = 1; i <= nc; i++ ) {
            d.at(i) = eigv.at(i);                     // label 410 and 440
        }

        continue;
    }


    // compute eigenvectors
    for ( j = 1; j <= nc; j++ ) {
        for ( k = 1; k <= nn; k++ ) {
            tt.at(k) = r.at(k, j);
        }

        a.backSubstitutionWith(tt);
        for ( k = 1; k <= nn; k++ ) {
            r.at(k, j) = tt.at(k);                   // (r = xbar)
        }
    }

    // one cad add a normalization of eigen-vectors here

    for ( i = 1; i <= nroot; i++ ) {
        _eigv.at(i) = eigv.at(i);
        for ( j = 1; j <= nn; j++ ) {
            _r.at(j, i) = r.at(j, i);
        }
    }

    solved = 1;
    return NM_Success;
}
/////////////////////////////////////////////////
// Help functions
void GnuplotExportModule::outputReactionForces(TimeStep *tStep)
{
    // Add sum of reaction forces to arrays
    // Compute sum of reaction forces for each BC number
    Domain *domain = emodel->giveDomain(1);
    StructuralEngngModel *seMod = dynamic_cast<StructuralEngngModel* >(emodel);
    if(seMod == NULL) {
        OOFEM_ERROR("failed to cast to StructuralEngngModel.");
    }

    FloatArray reactions;
    IntArray dofManMap, dofidMap, eqnMap;

    // test if solution step output is active
    if ( !testTimeStepOutput(tStep) ) {
        return;
    }

    // map contains corresponding dofmanager and dofs numbers corresponding to prescribed equations
    // sorted according to dofmanger number and as a minor crit. according to dof number
    // this is necessary for extractor, since the sorted output is expected
    seMod->buildReactionTable(dofManMap, dofidMap, eqnMap, tStep, 1);

    // compute reaction forces
    seMod->computeReaction(reactions, tStep, 1);

    // Find highest index of prescribed dofs
    int maxIndPresDof = 0;
    for ( int i = 1; i <= dofManMap.giveSize(); i++ ) {
        maxIndPresDof = std::max(maxIndPresDof, dofidMap.at(i));
    }

    int numBC = domain->giveNumberOfBoundaryConditions();

    while ( mReactionForceHistory.size() < size_t(numBC) ) {
        std::vector<FloatArray> emptyArray;
        mReactionForceHistory.push_back( emptyArray );
    }

    maxIndPresDof = domain->giveNumberOfSpatialDimensions();

    while ( mDispHist.size() < size_t(numBC) ) {
        std::vector<double> emptyArray;
        mDispHist.push_back( emptyArray );
    }

    for(int bcInd = 0; bcInd < numBC; bcInd++) {
        FloatArray fR(maxIndPresDof), disp(numBC);
        fR.zero();


        for ( int i = 1; i <= dofManMap.giveSize(); i++ ) {
            DofManager *dMan = domain->giveDofManager( dofManMap.at(i) );
            Dof *dof = dMan->giveDofWithID( dofidMap.at(i) );

            if ( dof->giveBcId() == bcInd+1 ) {
                fR.at( dofidMap.at(i) ) += reactions.at( eqnMap.at(i) );

                // Slightly dirty
                BoundaryCondition *bc = dynamic_cast<BoundaryCondition*> (domain->giveBc(bcInd+1));
                if ( bc != NULL ) {
                    disp.at(bcInd+1) = bc->give(dof, VM_Total, tStep->giveTargetTime());
                }
                ///@todo This function should be using the primaryfield instead of asking BCs directly. / Mikael
            }
        }

        mDispHist[bcInd].push_back(disp.at(bcInd+1));
        mReactionForceHistory[bcInd].push_back(fR);



        // X
        FILE * pFileX;
        char fileNameX[100];
        sprintf(fileNameX, "ReactionForceGnuplotBC%dX.dat", bcInd+1);
        pFileX = fopen ( fileNameX , "wb" );

        fprintf(pFileX, "#u Fx\n");
        for ( size_t j = 0; j < mDispHist[bcInd].size(); j++ ) {
            fprintf(pFileX, "%e %e\n", mDispHist[bcInd][j], mReactionForceHistory[bcInd][j].at(1) );
        }

        fclose(pFileX);

        // Y
        FILE * pFileY;
        char fileNameY[100];
        sprintf(fileNameY, "ReactionForceGnuplotBC%dY.dat", bcInd+1);
        pFileY = fopen ( fileNameY , "wb" );

        fprintf(pFileY, "#u Fx\n");
        for ( size_t j = 0; j < mDispHist[bcInd].size(); j++ ) {
            if( mReactionForceHistory[bcInd][j].giveSize() >= 2 ) {
                fprintf(pFileY, "%e %e\n", mDispHist[bcInd][j], mReactionForceHistory[bcInd][j].at(2) );
            }
        }

        fclose(pFileY);

    }
}
Exemple #15
0
void
FEI3dHexaQuad :: computeLocalEdgeMapping(IntArray &edgeNodes, int iedge)
{ OOFEM_ERROR("FEI3dHexaQuad :: computeLocalEdgeMapping not implemented"); }
Exemple #16
0
/*
 * should be called after basic local migration is finalized,
 * when all local elements are already available
 */
void
NonlocalMaterialWTP :: migrate()
{
    Domain *domain = this->lb->giveDomain();
    EngngModel *emodel = domain->giveEngngModel();
    int nproc = emodel->giveNumberOfProcesses();
    int myrank = emodel->giveRank();
    CommunicatorBuff cb(nproc, CBT_dynamic);
    Communicator com(emodel, &cb, myrank, nproc, CommMode_Dynamic);
    StaticCommunicationBuffer commBuff(MPI_COMM_WORLD);

    /*
     * build domain nonlocal element dependency list. Then exclude local elements - what remains are unsatisfied
     * remote dependencies that have to be broadcasted and received from partitions owning relevant elements
     */
    int _locsize, i, _i, ie, _size, _globnum, result, nelems = domain->giveNumberOfElements();
    int _globsize, _val;
    Element *elem;
    std :: set< int >domainElementDepSet;
    // loop over each element dep list to assemble domain list
    for ( ie = 1; ie <= nelems; ie++ ) {
        elem = domain->giveElement(ie);
        if ( ( elem->giveParallelMode() == Element_local ) ) {
            _globnum = elem->giveGlobalNumber();
            IntArray &iedep = nonlocElementDependencyMap [ _globnum ];
            _size = iedep.giveSize();
            for ( _i = 1; _i <= _size; _i++ ) {
                domainElementDepSet.insert( iedep.at(_i) );
            }

#if NonlocalMaterialWTP_DEBUG_PRINT
            fprintf(stderr, "[%d] element %d dependency:", myrank, _globnum);
            for ( _i = 1; _i <= _size; _i++ ) {
                fprintf( stderr, "%d ", iedep.at(_i) );
            }

            fprintf(stderr, "\n");
#endif
        }
    }

#if NonlocalMaterialWTP_DEBUG_PRINT
    fprintf(stderr, "[%d] nonlocal domain dependency:", myrank);
    for ( int eldep: domainElementDepSet ) {
        fprintf(stderr, "%d ", eldep);
    }

    fprintf(stderr, "\n");
#endif

    // now exclude local elements (local dependency is always satisfied)
    for ( _i = 1; _i <= nelems; _i++ ) {
        elem = domain->giveElement(_i);
        if ( elem->giveParallelMode() == Element_local ) {
            domainElementDepSet.erase( elem->giveGlobalNumber() );
        }
    }

#if NonlocalMaterialWTP_DEBUG_PRINT
    fprintf(stderr, "[%d] remote elem wish list:", myrank);
    for ( int eldep: domainElementDepSet ) {
        fprintf(stderr, "%d ", eldep);
    }

    fprintf(stderr, "\n");
#endif

    // broadcast remaining elements (unsatisfied domain nonlocal dependency) to remaining partitions
    _locsize = domainElementDepSet.size() + 1;
    result = MPI_Allreduce(& _locsize, & _globsize, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
    if ( result != MPI_SUCCESS ) {
        OOFEM_ERROR("MPI_Allreduce to determine  broadcast buffer size failed");
    }

    commBuff.resize( commBuff.givePackSize(MPI_INT, _globsize) );
    // remote domain wish list
    std :: set< int >remoteWishSet;

    toSendList.resize(nproc);
    for ( i = 0; i < nproc; i++ ) { // loop over partitions
        commBuff.init();
        toSendList [ i ].clear();
        if ( i == myrank ) {
            // current domain has to send its receive wish list to all domains
            commBuff.packInt(_locsize);
            for ( int eldep: domainElementDepSet ) {
                commBuff.packInt(eldep);
            }

            result = commBuff.bcast(i);
        } else {
            // unpack remote domain wish list
            remoteWishSet.clear();
            result = commBuff.bcast(i);
            // unpack size
            commBuff.unpackInt(_size);
            for ( _i = 1; _i < _size; _i++ ) {
                commBuff.unpackInt(_val);
                remoteWishSet.insert(_val);
            }

            // determine which local elements are to be sent to remotepartition
            for ( _i = 1; _i <= nelems; _i++ ) {
                elem = domain->giveElement(_i);
                if ( elem->giveParallelMode() == Element_local ) {
                    if ( remoteWishSet.find( elem->giveGlobalNumber() ) != remoteWishSet.end() ) {
                        // store local element number
                        toSendList [ i ].push_back(_i);
                    }
                }
            }
        }
    } // end loop over partitions broadcast

#if NonlocalMaterialWTP_DEBUG_PRINT
    for ( i = 0; i < nproc; i++ ) { // loop over partitions
        // print some info
        fprintf(stderr, "[%d] elements scheduled for mirroring at [%d]:",
                myrank, i);
        for ( int elnum: toSendList [ i ] ) {
            fprintf( stderr, "%d[%d] ", elnum, domain->giveElement(elnum)->giveGlobalNumber() );
        }

        fprintf(stderr, "\n");
    }

#endif





    com.packAllData(this, domain, & NonlocalMaterialWTP :: packRemoteElements);
    com.initExchange(MIGRATE_REMOTE_ELEMENTS_TAG);
    com.unpackAllData(this, domain, & NonlocalMaterialWTP :: unpackRemoteElements);
    com.finishExchange();

    domain->commitTransactions( domain->giveTransactionManager() );

#ifdef __VERBOSE_PARALLEL
    VERBOSEPARALLEL_PRINT("NonlocalMaterialWTP::migrate", "Finished migrating remote elements", myrank);
#endif
}
Exemple #17
0
int
PiecewiseLinFunctionBlock :: giveInputRecordString(std :: string &str, bool keyword)
{
 OOFEM_ERROR("Not implemented");
  return 1;
}
Exemple #18
0
void
Tria1PlateSubSoil :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep)
// Returns the lumped mass matrix of the receiver.
{
  OOFEM_ERROR("Mass matrix not provided");
}
IRResultType
NonlocalMaterialExtensionInterface :: initializeFrom(InputRecord *ir)
{
    IRResultType result;              // Required by IR_GIVE_FIELD macro

    if ( ir->hasField(_IFT_NonlocalMaterialExtensionInterface_regionmap) ) {
        IR_GIVE_FIELD(ir, regionMap, _IFT_NonlocalMaterialExtensionInterface_regionmap);
        if ( regionMap.giveSize() != this->giveDomain()->giveNumberOfRegions() ) {
            OOFEM_ERROR("regionMap size mismatch");
        }
    } else {
        regionMap.zero();
    }

    if ( this->hasBoundedSupport() ) {
        permanentNonlocTableFlag = true;
    } else {
        permanentNonlocTableFlag = false;
    }
    IR_GIVE_OPTIONAL_FIELD(ir, this->permanentNonlocTableFlag, _IFT_NonlocalMaterialExtensionInterface_permanentNonlocTableFlag);

    // read the characteristic length
    IR_GIVE_FIELD(ir, cl, _IFT_NonlocalMaterialExtensionInterface_r);
    if ( cl < 0.0 ) {
        cl = 0.0;
    }

    // read the type of weight function
    int val = WFT_Bell;
    IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_NonlocalMaterialExtensionInterface_wft);
    this->weightFun = ( WeightFunctionType ) val;

    // this is introduced for compatibility of input format with previous versions
    // ("averagingtype 1" in the input means that the weight function
    //   should be uniform over an element,
    //   which can now be described as "wft 5")
    int avt = 0;
    IR_GIVE_OPTIONAL_FIELD(ir, avt, _IFT_NonlocalMaterialExtensionInterface_averagingtype);
    if ( avt == 1 ) {
        weightFun = WFT_UniformOverElement;
    }

    // evaluate the support radius based on type of weight function and characteristic length
    suprad = evaluateSupportRadius();

    // read the optional parameter for overnonlocal formulation
    mm = 1.;
    IR_GIVE_OPTIONAL_FIELD(ir, mm, _IFT_NonlocalMaterialExtensionInterface_m);

    // read the type of scaling
    val = ST_Standard;
    IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_NonlocalMaterialExtensionInterface_scalingtype);
    this->scaling = ( ScalingType ) val;

    // read the type of averaged variable
    val = AVT_EqStrain;
    IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_NonlocalMaterialExtensionInterface_averagedquantity);
    this->averagedVar = ( AveragedVarType ) val;

    // read the nonlocal variation type (default is zero)
    cl0 = cl;
    int nlvariation = 0;
    IR_GIVE_OPTIONAL_FIELD(ir, nlvariation, _IFT_NonlocalMaterialExtensionInterface_nonlocalvariation);
    if ( nlvariation == 1 ) {
        nlvar = NLVT_DistanceBasedLinear;
        IR_GIVE_FIELD(ir, beta, _IFT_NonlocalMaterialExtensionInterface_beta);
        IR_GIVE_FIELD(ir, zeta, _IFT_NonlocalMaterialExtensionInterface_zeta);
    } else if ( nlvariation == 2 ) {
        nlvar = NLVT_StressBased;
        IR_GIVE_FIELD(ir, beta, _IFT_NonlocalMaterialExtensionInterface_beta);
    } else if ( nlvariation == 3 ) {
        nlvar = NLVT_DistanceBasedExponential;
        IR_GIVE_FIELD(ir, beta, _IFT_NonlocalMaterialExtensionInterface_beta);
        IR_GIVE_FIELD(ir, zeta, _IFT_NonlocalMaterialExtensionInterface_zeta);
    }

    // read the periodic shift (default is zero)
    px = 0.;
    IR_GIVE_OPTIONAL_FIELD(ir, px, _IFT_NonlocalMaterialExtensionInterface_px);

    return IRRT_OK;
}
Exemple #20
0
void
Tria1PlateSubSoil :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode)
{
  OOFEM_ERROR("Body load not supported, use surface load instead");
}
Exemple #21
0
void LSPrimaryVariableMapper :: mapPrimaryVariables(FloatArray &oU, Domain &iOldDom, Domain &iNewDom, ValueModeType iMode, TimeStep &iTStep)
{
    EngngModel *engngMod = iNewDom.giveEngngModel();
    EModelDefaultEquationNumbering num;


    const int dim = iNewDom.giveNumberOfSpatialDimensions();

    int numElNew = iNewDom.giveNumberOfElements();

    // Count dofs
    int numDofsNew = engngMod->giveNumberOfDomainEquations( 1, num );


    oU.resize(numDofsNew);
    oU.zero();

    FloatArray du(numDofsNew);
    du.zero();

    FloatArray res(numDofsNew);

#ifdef __PETSC_MODULE
    PetscSparseMtrx *K = dynamic_cast<PetscSparseMtrx*>( classFactory.createSparseMtrx(SMT_PetscMtrx) );
    SparseLinearSystemNM *solver = classFactory.createSparseLinSolver(ST_Petsc, & iOldDom, engngMod);
#else
    SparseMtrx *K = classFactory.createSparseMtrx(SMT_Skyline);
    SparseLinearSystemNM *solver = classFactory.createSparseLinSolver(ST_Direct, & iOldDom, engngMod);
#endif


    K->buildInternalStructure( engngMod, 1, num );

    int maxIter = 1;

    for ( int iter = 0; iter < maxIter; iter++ ) {
        K->zero();
        res.zero();


        // Contribution from elements
        for ( int elIndex = 1; elIndex <= numElNew; elIndex++ ) {
            StructuralElement *elNew = dynamic_cast< StructuralElement * >( iNewDom.giveElement(elIndex) );
            if ( elNew == NULL ) {
                OOFEM_ERROR("Failed to cast Element new to StructuralElement.");
            }

            ///////////////////////////////////
            // Compute residual

            // Count element dofs
            int numElNodes = elNew->giveNumberOfDofManagers();
            int numElDofs = 0;
            for ( int i = 1; i <= numElNodes; i++ ) {
                numElDofs += elNew->giveDofManager(i)->giveNumberOfDofs();
            }

            FloatArray elRes(numElDofs);
            elRes.zero();

            IntArray elDofsGlob;
            elNew->giveLocationArray( elDofsGlob, num );


            // Loop over Gauss points
            for ( int intRuleInd = 0; intRuleInd < elNew->giveNumberOfIntegrationRules(); intRuleInd++ ) {
                IntegrationRule *iRule = elNew->giveIntegrationRule(intRuleInd);

                for ( GaussPoint *gp: *iRule ) {

                    // New N-matrix
                    FloatMatrix NNew;
                    elNew->computeNmatrixAt(* ( gp->giveNaturalCoordinates() ), NNew);


                    //////////////
                    // Global coordinates of GP
                    const int nDofMan = elNew->giveNumberOfDofManagers();

                    FloatArray Nc;
                    FEInterpolation *interp = elNew->giveInterpolation();
                    const FloatArray &localCoord = * ( gp->giveNaturalCoordinates() );
                    interp->evalN( Nc, localCoord, FEIElementGeometryWrapper(elNew) );

                    const IntArray &elNodes = elNew->giveDofManArray();

                    FloatArray globalCoord(dim);
                    globalCoord.zero();

                    for ( int i = 1; i <= nDofMan; i++ ) {
                        DofManager *dMan = elNew->giveDofManager(i);

                        for ( int j = 1; j <= dim; j++ ) {
                            globalCoord.at(j) += Nc.at(i) * dMan->giveCoordinate(j);
                        }
                    }
                    //////////////


                    // Localize element and point in the old domain
                    FloatArray localCoordOld(dim), pointCoordOld(dim);
                    StructuralElement *elOld = dynamic_cast< StructuralElement * >( iOldDom.giveSpatialLocalizer()->giveElementClosestToPoint(localCoordOld, pointCoordOld, globalCoord, 0) );
                    if ( elOld == NULL ) {
                        OOFEM_ERROR("Failed to cast Element old to StructuralElement.");
                    }


                    // Compute N-Matrix for the old element
                    FloatMatrix NOld;
                    elOld->computeNmatrixAt(localCoordOld, NOld);

                    // Fetch nodal displacements for the new element
                    FloatArray nodeDispNew( elDofsGlob.giveSize() );


                    int dofsPassed = 1;
                    for ( int i = 1; i <= elNodes.giveSize(); i++ ) {
                        DofManager *dMan = elNew->giveDofManager(i);

                        for ( Dof *dof: *dMan ) {
                            if ( elDofsGlob.at(dofsPassed) != 0 ) {
                                nodeDispNew.at(dofsPassed) = oU.at( elDofsGlob.at(dofsPassed) );
                            } else {
                                if ( dof->hasBc(& iTStep) ) {
                                    nodeDispNew.at(dofsPassed) = dof->giveBcValue(iMode, & iTStep);
                                }
                            }

                            dofsPassed++;
                        }
                    }


                    FloatArray newDisp;
                    newDisp.beProductOf(NNew, nodeDispNew);


                    // Fetch nodal displacements for the old element
                    FloatArray nodeDispOld;
                    dofsPassed = 1;
                    IntArray elDofsGlobOld;
                    elOld->giveLocationArray( elDofsGlobOld, num );

//                    elOld->computeVectorOf(iMode, &(iTStep), nodeDisp);
                    int numElNodesOld = elOld->giveNumberOfDofManagers();
                    for(int nodeIndOld = 1; nodeIndOld <= numElNodesOld; nodeIndOld++) {
                        DofManager *dManOld = elOld->giveDofManager(nodeIndOld);

                        for ( Dof *dof: *dManOld ) {
                            if ( elDofsGlobOld.at(dofsPassed) != 0 ) {
                                FloatArray dofUnknowns;
                                dof->giveUnknowns(dofUnknowns, iMode, &iTStep);

#ifdef DEBUG
                                if(!dofUnknowns.isFinite()) {
                                    OOFEM_ERROR("!dofUnknowns.isFinite()")
                                }

                                if(dofUnknowns.giveSize() < 1) {
                                    OOFEM_ERROR("dofUnknowns.giveSize() < 1")
                                }
#endif
                                nodeDispOld.push_back(dofUnknowns.at(1));
                            } else {
                                if ( dof->hasBc(& iTStep) ) {
//                                    printf("hasBC.\n");
#ifdef DEBUG
                                    if(!std::isfinite(dof->giveBcValue(iMode, & iTStep))) {
                                        OOFEM_ERROR("!std::isfinite(dof->giveBcValue(iMode, & iTStep))")
                                    }
#endif
                                    nodeDispOld.push_back( dof->giveBcValue(iMode, & iTStep) );
                                }
                                else {
//                                    printf("Unhandled case in LSPrimaryVariableMapper :: mapPrimaryVariables().\n");
                                    nodeDispOld.push_back( 0.0 );
                                }
                            }

                            dofsPassed++;
                        }

                    }


                    FloatArray oldDisp;
                    oldDisp.beProductOf(NOld, nodeDispOld);

                    FloatArray temp, du;

#ifdef DEBUG
                    if(!oldDisp.isFinite()) {
                        OOFEM_ERROR("!oldDisp.isFinite()")
                    }

                    if(!newDisp.isFinite()) {
                        OOFEM_ERROR("!newDisp.isFinite()")
                    }
#endif

                    du.beDifferenceOf(oldDisp, newDisp);
                    temp.beTProductOf(NNew, du);
                    double dV = elNew->computeVolumeAround(gp);
                    elRes.add(dV, temp);
                }
            }
Exemple #22
0
void FEI3dHexaQuad :: edgeEvalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo)
{ OOFEM_ERROR("FEI3dHexaQuad :: edgeEvalN not implemented"); }
Exemple #23
0
void
IDGMaterial :: giveInternalLength(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep)
{
    if ( averType == 0 ) {
        answer.resize(1, 1);
        answer.at(1, 1) = cl;
    } else if ( averType == 1 ) {
        answer.resize(1, 1);
        FloatArray gpCoords;
        if ( gp->giveElement()->computeGlobalCoordinates( gpCoords, gp->giveNaturalCoordinates() ) == 0 ) {
            OOFEM_ERROR("computeGlobalCoordinates of GP failed");
        }

        this->giveDistanceBasedCharacteristicLength(gpCoords);
        answer.at(1, 1) = cl;
    } else if ( averType == 2 ) {
        MaterialMode mMode = gp->giveMaterialMode();
        if ( mMode == _PlaneStress ) {
            answer.resize(2, 2);
            answer.zero();
            IDGMaterialStatus *status = static_cast< IDGMaterialStatus * >( this->giveStatus(gp) );
            FloatArray stress = status->giveTempStressVector();
            StressVector fullStress(stress, _PlaneStress);
            FloatArray sigPrinc;
            FloatMatrix nPrinc;
            // get principal stresses (ordered) and principal stress directions
            fullStress.computePrincipalValDir(sigPrinc, nPrinc);
            if ( nPrinc.giveNumberOfRows() == 0 ) {
                nPrinc.resize(2, 2);
                nPrinc.at(1, 1) = 1;
                nPrinc.at(2, 2) = 1;
            }

            // principal internal lengths
            double l1 = cl0;
            double l2 = cl0;
            double gamma;
            if ( sigPrinc.at(1) > 0 ) {
                if ( sigPrinc.at(2) > 0 ) {
                    gamma = beta + ( 1 - beta ) * sigPrinc.at(2) * sigPrinc.at(2) / ( sigPrinc.at(1) * sigPrinc.at(1) );
                } else {
                    gamma = beta;
                }
            } else {
                gamma = 1;
            }

            l2 = l2 * gamma;

            // compose the internal Length matrix in global coordinates
            //   the first subscript refers to coordinate
            //   the second subscript refers to eigenvalue
            double n11 = nPrinc.at(1, 1);
            double n12 = nPrinc.at(1, 2);
            double n21 = nPrinc.at(2, 1);
            double n22 = nPrinc.at(2, 2);

            answer.at(1, 1) = l1 * l1 * n11 * n11 + l2 * l2 * n12 * n12;
            answer.at(1, 2) = l1 * l1 * n11 * n21 + l2 * l2 * n12 * n22;
            answer.at(2, 1) = l1 * l1 * n11 * n21 + l2 * l2 * n12 * n22;
            answer.at(2, 2) = l1 * l1 * n21 * n21 + l2 * l2 * n22 * n22;
        } else {
            OOFEM_ERROR("Unknown material mode.");
        }
    }
}
Exemple #24
0
void FEI3dHexaQuad :: edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo)
{ OOFEM_ERROR("FEI3dHexaQuad :: edgeEvaldNdx not implemented"); }
Exemple #25
0
void
TR_SHELL02 :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode)
{
        OOFEM_ERROR("This function is not implemented yet.");
}
Exemple #26
0
void FEI3dHexaQuad :: edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo)
{ OOFEM_ERROR("FEI3dHexaQuad :: edgeLocal2global not implemented"); }
Exemple #27
0
void
SUPGElement2 :: giveCharacteristicVector(FloatArray &answer, CharType mtrx, ValueModeType mode,
                                         TimeStep *tStep)
//
// returns characteristics vector of receiver according to requested type
//
{
    if ( mtrx == ExternalForcesVector ) {
        // stokes flow
        IntArray vloc, ploc;
        FloatArray h;
        int size = this->computeNumberOfDofs();
        this->giveLocalVelocityDofMap(vloc);
        this->giveLocalPressureDofMap(ploc);
        answer.resize(size);
        answer.zero();
        this->computeBCRhsTerm_MB(h, tStep);
        answer.assemble(h, vloc);
        this->computeBCRhsTerm_MC(h, tStep);
        answer.assemble(h, ploc);
    } else
#if 0
    if ( mtrx == InternalForcesVector ) {
        // stokes flow
        IntArray vloc, ploc;
        FloatArray h;
        int size = this->computeNumberOfDofs();
        this->giveLocalVelocityDofMap(vloc);
        this->giveLocalPressureDofMap(ploc);
        answer.resize(size);
        answer.zero();
        this->computeAdvectionTerm_MB(h, tStep);
        answer.assemble(h, vloc);
        this->computeAdvectionTerm_MC(h, tStep);
        answer.assemble(h, ploc);
        this->computeDiffusionTerm_MB(h, tStep);
        answer.assemble(h, vloc);
        this->computeDiffusionTerm_MC(h, tStep);
        answer.assemble(h, ploc);

        FloatMatrix m1;
        FloatArray v, p;
        // add lsic stabilization term
        this->giveCharacteristicMatrix(m1, LSICStabilizationTerm_MB, tStep);
        //m1.times( lscale / ( dscale * uscale * uscale ) );
        this->computeVectorOfVelocities(VM_Total, tStep, v);
        h.beProductOf(m1, v);
        answer.assemble(h, vloc);
        this->giveCharacteristicMatrix(m1, LinearAdvectionTerm_MC, tStep);
        //m1.times( 1. / ( dscale * uscale ) );
        h.beProductOf(m1, v);
        answer.assemble(h, ploc);


        // add pressure term
        this->giveCharacteristicMatrix(m1, PressureTerm_MB, tStep);
        this->computeVectorOfPressures(VM_Total, tStep, v);
        h.beProductOf(m1, v);
        answer.assemble(h, vloc);

        // pressure term
        this->giveCharacteristicMatrix(m1, PressureTerm_MC, tStep);
        this->computeVectorOfPressures(VM_Total, tStep, v);
        h.beProductOf(m1, v);
        answer.assemble(h, ploc);
    } else
#endif
    {
        OOFEM_ERROR("Unknown Type of characteristic mtrx.");
    }
}
Exemple #28
0
double FEI3dHexaQuad :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo)
{
    OOFEM_ERROR("FEI3dHexaQuad :: edgeGiveTransformationJacobian not implemented");
    return 0.0;
}
double LocalGaussianRandomGenerator :: normal01CdfInverse(double p)
{
    double a [ 8 ] = {
        3.3871328727963666080,     1.3314166789178437745e+2,
        1.9715909503065514427e+3,  1.3731693765509461125e+4,
        4.5921953931549871457e+4,  6.7265770927008700853e+4,
        3.3430575583588128105e+4,  2.5090809287301226727e+3
    };
    double b [ 8 ] = {
        1.0,                       4.2313330701600911252e+1,
        6.8718700749205790830e+2,  5.3941960214247511077e+3,
        2.1213794301586595867e+4,  3.9307895800092710610e+4,
        2.8729085735721942674e+4,  5.2264952788528545610e+3
    };
    double c [ 8 ] = {
        1.42343711074968357734,     4.63033784615654529590,
        5.76949722146069140550,     3.64784832476320460504,
        1.27045825245236838258,     2.41780725177450611770e-1,
        2.27238449892691845833e-2,  7.74545014278341407640e-4
    };
    double const1 = 0.180625;
    double const2 = 1.6;
    double d [ 8 ] = {
        1.0,                        2.05319162663775882187,
        1.67638483018380384940,     6.89767334985100004550e-1,
        1.48103976427480074590e-1,  1.51986665636164571966e-2,
        5.47593808499534494600e-4,  1.05075007164441684324e-9
    };
    double e [ 8 ] = {
        6.65790464350110377720,     5.46378491116411436990,
        1.78482653991729133580,     2.96560571828504891230e-1,
        2.65321895265761230930e-2,  1.24266094738807843860e-3,
        2.71155556874348757815e-5,  2.01033439929228813265e-7
    };
    double f [ 8 ] = {
        1.0,                        5.99832206555887937690e-1,
        1.36929880922735805310e-1,  1.48753612908506148525e-2,
        7.86869131145613259100e-4,  1.84631831751005468180e-5,
        1.42151175831644588870e-7,  2.04426310338993978564e-15
    };
    double q;
    double r;
    double split1 = 0.425;
    double split2 = 5.0;
    double value;

    if ( p <= 0.0 ) {
        value = -HUGE_VAL;
        return value;
    }

    if ( 1.0 <= p ) {
        value = HUGE_VAL;
        return value;
    }

    q = p - 0.5;

    if ( fabs(q) <= split1 ) {
        r = const1 - q * q;
        value = q * dpolyValue(8, a, r) / dpolyValue(8, b, r);
    } else {
        if ( q < 0.0 ) {
            r = p;
        } else {
            r = 1.0 - p;
        }

        if ( r <= 0.0 ) {
            OOFEM_ERROR("r < 0.0!");
            return -1.0;
        }

        r = sqrt( -log(r) );
        if ( r <= split2 ) {
            r = r - const2;
            value = dpolyValue(8, c, r) / dpolyValue(8, d, r);
        } else {
            r = r - split2;
            value = dpolyValue(8, e, r) / dpolyValue(8, f, r);
        }

        if ( q < 0.0 ) {
            value = -value;
        }
    }

    return value;
}
int
ZZRemeshingCriteria :: estimateMeshDensities(TimeStep *tStep)
{
    int nelem, nnode, elemPolyOrder, ielemNodes;
    double globValNorm = 0.0, globValErrorNorm = 0.0, elemErrLimit, eerror, iratio, currDensity, elemSize;
    EE_ErrorType errorType = indicatorET;
    double pe, coeff = 2.0;

    if ( stateCounter == tStep->giveSolutionStateCounter() ) {
        return 1;
    }

    nelem = this->domain->giveNumberOfElements();
    nnode = this->domain->giveNumberOfDofManagers();

    //std::vector<char> nodalDensities(nnode);
    this->nodalDensities.resize(nnode);
    std :: vector< char > dofManInitFlag(nnode);
    for ( int i = 0; i < nnode; i++ ) {
        dofManInitFlag [ i ] = 0;
    }

    // compute element error limit based on equally distribution error principle
    if ( mode == stressBased ) {
        globValNorm      = this->ee->giveValue(globalNormEEV, tStep);
        globValErrorNorm = this->ee->giveValue(globalErrorEEV, tStep);
        errorType = internalStressET;
    } else {
        OOFEM_ERROR("unknown mode");
    }


    // test if solution is allowable
    pe = sqrt( globValErrorNorm * globValErrorNorm / ( globValErrorNorm * globValErrorNorm + globValNorm * globValNorm ) );
    if ( pe <= this->requiredError ) {
        this->remeshingStrategy = NoRemeshing_RS;
        // added by bp
        /*
         * for (i=1; i<=nnode; i++) nodalDensities.at(i) = this->giveDofManDensity (i);
         * stateCounter = tStep->giveSolutionStateCounter();
         * return 1;  // remove to force computing densities
         */
    } else {
        this->remeshingStrategy = RemeshingFromPreviousState_RS;
    }

    elemErrLimit = sqrt( ( globValNorm * globValNorm + globValErrorNorm * globValErrorNorm ) / nelem ) *
    this->requiredError * coeff;

    for ( auto &elem : domain->giveElements() ) {

        if ( this->ee->skipRegion( elem->giveRegionNumber() ) ) {
            continue;
        }

        eerror = this->ee->giveElementError(errorType, elem.get(), tStep);
        iratio = eerror / elemErrLimit;
        if ( fabs(iratio) < 1.e-3 ) {
            continue;
        }

        if ( iratio > 1.0 ) {
            this->remeshingStrategy = RemeshingFromPreviousState_RS;
        }

        if ( iratio < 0.5 ) {
            iratio = 0.5;
        }

        //  if (iratio > 5.0)iratio = 5.0;

        currDensity = elem->computeMeanSize();
        elemPolyOrder = elem->giveInterpolation()->giveInterpolationOrder();
        elemSize = currDensity / pow(iratio, 1.0 / elemPolyOrder);

        ielemNodes = elem->giveNumberOfDofManagers();
        for ( int j = 1; j <= ielemNodes; j++ ) {
            int jnode = elem->giveDofManager(j)->giveNumber();
            if ( dofManInitFlag [ jnode - 1 ] ) {
                this->nodalDensities.at(jnode) = min(this->nodalDensities.at(jnode), elemSize);
            } else {
                this->nodalDensities.at(jnode) = elemSize;
                dofManInitFlag [ jnode - 1 ] = 1;
            }
        }
    }

    // init non-initialized nodes -> those in skip regions
    for ( int i = 0; i < nnode; i++ ) {
        if ( dofManInitFlag [ i ] == 0 ) {
            this->nodalDensities.at(i + 1) = this->giveDofManDensity(i + 1);
        }
    }

    // remember time stamp
    stateCounter = tStep->giveSolutionStateCounter();
    return 1;
}