void SimpleVitrificationMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp,
                                                            const FloatArray &reducedStrain, TimeStep *tStep)
{
    FloatArray strainVector;
    FloatMatrix d;
    FloatArray deltaStrain;

    StructuralMaterialStatus *status = dynamic_cast< StructuralMaterialStatus * >( this->giveStatus(gp) );

    this->giveStressDependentPartOfStrainVector(strainVector, gp, reducedStrain, tStep, VM_Total);

    deltaStrain.beDifferenceOf( strainVector, status->giveStrainVector() );

    this->give3dMaterialStiffnessMatrix(d, TangentStiffness, gp, tStep);

    FloatArray deltaStress;
    deltaStress.beProductOf(d, deltaStrain);

    answer = status->giveStressVector();
    answer.add(deltaStress);

    // update gp
    status->letTempStrainVectorBe(reducedStrain);
    status->letTempStressVectorBe(answer);
}
示例#2
0
void
TutorialMaterial :: computeSphDevPartOf(const FloatArray &sigV, FloatArray &sigSph, FloatArray &sigDev)
{
    double volumetricPart = ( sigV.at(1) + sigV.at(2) + sigV.at(3) ) / 3.0;
    sigSph = {volumetricPart, volumetricPart, volumetricPart, 0.0, 0.0, 0.0};
    sigDev.beDifferenceOf(sigV, sigSph);
}
void FE2FluidMaterial :: giveDeviatoricPressureStiffness(FloatArray &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep)
{
    FE2FluidMaterialStatus *ms = static_cast<FE2FluidMaterialStatus*> (this->giveStatus(gp));
    ms->computeTangents(tStep);
    if ( mode == TangentStiffness ) {
        answer = ms->giveDeviatoricPressureTangent();
#ifdef DEBUG_TANGENT
        // Numerical ATS for debugging
        FloatArray strain(3); strain.zero();
        FloatArray sig, sigh;
        double epspvol, pressure = 0.0;
        double h = 1.00; // Linear problem, size of this doesn't matter.
        computeDeviatoricStressVector (sig, epspvol, gp, strain, pressure, tStep);
        computeDeviatoricStressVector (sigh, epspvol, gp, strain, pressure+h, tStep);

        FloatArray dsigh; dsigh.beDifferenceOf(sigh,sig); dsigh.times(1/h);

        printf("Analytical deviatoric pressure tangent = "); answer.printYourself();
        printf("Numerical deviatoric pressure tangent = "); dsigh.printYourself();
        dsigh.subtract(answer);
        double norm = dsigh.computeNorm();
        if (norm > answer.computeNorm()*DEBUG_ERR && norm > 0.0) {
            OOFEM_ERROR("Error in deviatoric pressure tangent");
        }
#endif
    } else {
        OOFEM_ERROR("Mode not implemented");
    }
}
示例#4
0
double Line :: computeTangentialDistanceToEnd(FloatArray *point)
{
    FloatArray projection;
    this->computeProjection(projection);
    FloatArray tmp;
    tmp.beDifferenceOf(* point, mVertices [ 1 ]);
    return tmp.dotProduct(projection) / projection.computeNorm();
}
示例#5
0
void PrescribedGradientBCWeak :: giveTractionElNormal(size_t iElInd, FloatArray &oNormal, FloatArray &oTangent) const
{
	FloatArray xS, xE;
	giveTractionElCoord(iElInd, xS, xE);

    oTangent.beDifferenceOf(xE, xS);
    oTangent.normalize();

    oNormal = {
        oTangent [ 1 ], -oTangent [ 0 ]
    };
}
示例#6
0
void Line :: transformIntoPolar(FloatArray *point, FloatArray &answer)
{
    FloatArray xp;
    FloatMatrix Qt;
    FloatArray help;
    this->computeTransformationMatrix(Qt);
    help.beDifferenceOf(* point, mVertices [ 1 ]);
    xp.beProductOf(Qt, help);
    answer.resize(2);
    answer.at(1) = xp.computeNorm();
    answer.at(2) = atan2( xp.at(2), xp.at(1) );
}
示例#7
0
文件: intelpoint.C 项目: erisve/oofem
void
IntElPoint :: computeLocalSlipDir(FloatArray &normal)
{
    normal.resizeWithValues(3);
    if ( this->referenceNode ) {
        // normal
        normal.beDifferenceOf(*domain->giveNode(this->referenceNode)->giveCoordinates(), *this->giveNode(1)->giveCoordinates());
    } else {
        if ( normal.at(1) == 0 && normal.at(2) == 0 && normal.at(3) == 0 ) {
            OOFEM_ERROR("Normal is not defined (referenceNode=0,normal=(0,0,0))");
        }
    }

    normal.normalize();
}
void TransportGradientPeriodic :: computeDofTransformation(ActiveDof *dof, FloatArray &masterContribs)
{
    DofManager *master = this->domain->giveDofManager(this->slavemap[dof->giveDofManager()->giveNumber()]);
    FloatArray *coords = dof->giveDofManager()->giveCoordinates();
    FloatArray *masterCoords = master->giveCoordinates();

    FloatArray dx;
    dx.beDifferenceOf(* coords, * masterCoords );

    masterContribs.resize(dx.giveSize() + 1);

    masterContribs.at(1) = 1.; // Master dof is always weight 1.0
    for ( int i = 1; i <= dx.giveSize(); ++i ) {
        masterContribs.at(i+1) = dx.at(i);
    }
}
void PrescribedGradientBCPeriodic :: findSlaveToMasterMap()
{
    FloatArray coord;
    SpatialLocalizer *sl = this->domain->giveSpatialLocalizer();
    //Set *masterSet = this->domain->giveSet(2);
    const IntArray &nodes = this->domain->giveSet(this->set)->giveNodeList(); // Split into slave set and master set?
    int nsd = jump.giveSize();
    std :: vector< FloatArray > jumps;
    // Construct all the possible jumps;
    jumps.reserve((2 << (nsd-1)) - 1);
    if ( nsd != 3 ) {
        OOFEM_ERROR("Only 3d implemented yet!");
    }
    jumps.emplace_back(jump);
    jumps.emplace_back(FloatArray{jump.at(1), jump.at(2), 0.});
    jumps.emplace_back(FloatArray{jump.at(1), 0., jump.at(3)});
    jumps.emplace_back(FloatArray{0., jump.at(2), jump.at(3)});
    jumps.emplace_back(FloatArray{jump.at(1), 0., 0.});
    jumps.emplace_back(FloatArray{0., jump.at(2), 0.});
    jumps.emplace_back(FloatArray{0., 0., jump.at(3)});

    this->slavemap.clear();
    for ( int inode : nodes ) {
        Node *masterNode = NULL;
        Node *node = this->domain->giveNode(inode);
        const FloatArray &masterCoord = *node->giveCoordinates();
        //printf("node %d\n", node->giveLabel()); masterCoord.printYourself();
        // The difficult part, what offset to subtract to find the master side;
        for ( FloatArray &testJump : jumps ) {
            coord.beDifferenceOf(masterCoord, testJump);
            masterNode = sl->giveNodeClosestToPoint(coord, fabs(jump.at(1))*1e-5);
            if ( masterNode != NULL ) {
                //printf("Found master (%d) to node %d (distance = %e)\n",  masterNode->giveNumber(), node->giveNumber(),
                //       masterNode->giveCoordinates()->distance(coord));
                break;
            }
        }
        if ( masterNode != NULL ) {
            this->slavemap.insert({node->giveNumber(), masterNode->giveNumber()});
        } else {
            OOFEM_ERROR("Couldn't find master node!");
        }
    }
}
示例#10
0
double
FEI3dLineLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo)
{
    ///@todo Not clear what this function should return. Just dNds would make sense if the caller defines a local coordinate system.
    FloatArray vec;
    vec.beDifferenceOf(*cellgeo.giveVertexCoordinates(2), *cellgeo.giveVertexCoordinates(1));

    double detJ = vec.computeSquaredNorm() * 0.5;
    double l2_inv = 0.5 / detJ;
    answer.resize(2, 3);

    answer.at(1, 1) = -vec.at(1)*l2_inv;
    answer.at(2, 1) =  vec.at(1)*l2_inv;
    answer.at(1, 2) = -vec.at(2)*l2_inv;
    answer.at(2, 2) =  vec.at(2)*l2_inv;
    answer.at(1, 3) = -vec.at(3)*l2_inv;
    answer.at(2, 3) =  vec.at(3)*l2_inv;

    return detJ;
}
示例#11
0
void
StructuralFE2Material :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep)
{
    if ( useNumTangent ) {
        // Numerical tangent
        StructuralFE2MaterialStatus *status = static_cast<StructuralFE2MaterialStatus*>( this->giveStatus( gp ) );
        double h = 1.0e-9;

        const FloatArray &epsRed = status->giveTempStrainVector();
        FloatArray eps;
        StructuralMaterial::giveFullSymVectorForm(eps, epsRed, gp->giveMaterialMode() );


        int dim = eps.giveSize();
        answer.resize(dim, dim);
        answer.zero();

        FloatArray sig, sigPert, epsPert;

        for(int i = 1; i <= dim; i++) {
            // Add a small perturbation to the strain
            epsPert = eps;
            epsPert.at(i) += h;

            giveRealStressVector_3d(sigPert, gp, epsPert, tStep);
            answer.setColumn(sigPert, i);
        }

        giveRealStressVector_3d(sig, gp, eps, tStep);

        for(int i = 1; i <= dim; i++) {
            for(int j = 1; j <= dim; j++) {
                answer.at(j,i) -= sig.at(j);
                answer.at(j,i) /= h;
            }
        }

    } else {

        StructuralFE2MaterialStatus *ms = static_cast< StructuralFE2MaterialStatus * >( this->giveStatus(gp) );
        ms->computeTangent(tStep);
        const FloatMatrix &ans9 = ms->giveTangent();

        StructuralMaterial::giveReducedSymMatrixForm(answer, ans9, _3dMat);

//        const FloatMatrix &ans9 = ms->giveTangent();
//        printf("ans9: "); ans9.printYourself();
//
//        // Compute the (minor) symmetrized tangent:
//        answer.resize(6, 6);
//        for ( int i = 0; i < 6; ++i ) {
//            for ( int j = 0; j < 6; ++j ) {
//                answer(i, j) = ans9(i, j);
//            }
//        }
//        for ( int i = 0; i < 6; ++i ) {
//            for ( int j = 6; j < 9; ++j ) {
//                answer(i, j-3) += ans9(i, j);
//                answer(j-3, i) += ans9(j, i);
//            }
//        }
//        for ( int i = 6; i < 9; ++i ) {
//            for ( int j = 6; j < 9; ++j ) {
//                answer(j-3, i-3) += ans9(j, i);
//            }
//        }
//        for ( int i = 0; i < 6; ++i ) {
//            for ( int j = 3; j < 6; ++j ) {
//                answer(j, i) *= 0.5;
//                answer(i, j) *= 0.5;
//            }
//        }



#if 0
        // Numerical ATS for debugging
        FloatMatrix numericalATS(6, 6);
        FloatArray dsig;
        // Note! We need a copy of the temp strain, since the pertubations might change it.
        FloatArray tempStrain = ms->giveTempStrainVector();

        FloatArray sig, strain, sigPert;
        giveRealStressVector_3d(sig, gp, tempStrain, tStep);
        double hh = 1e-6;
        for ( int k = 1; k <= 6; ++k ) {
            strain = tempStrain;
            strain.at(k) += hh;
            giveRealStressVector_3d(sigPert, gp, strain, tStep);
            dsig.beDifferenceOf(sigPert, sig);
            numericalATS.setColumn(dsig, k);
        }
        numericalATS.times(1. / hh);
        giveRealStressVector_3d(sig, gp, tempStrain, tStep); // Reset

        //answer.printYourself("Analytical deviatoric tangent");
        //numericalATS.printYourself("Numerical deviatoric tangent");

        numericalATS.subtract(answer);
        double norm = numericalATS.computeFrobeniusNorm();
        if ( norm > answer.computeFrobeniusNorm() * 1e-3 && norm > 0.0 ) {
            OOFEM_ERROR("Error in deviatoric tangent");
        }
#endif
    }
}
示例#12
0
void
MisesMat :: giveFirstPKStressVector_3d(FloatArray &answer,
                                       GaussPoint *gp,
                                       const FloatArray &totalDefGradOOFEM,
                                       TimeStep *tStep)
{
    MisesMatStatus *status = static_cast< MisesMatStatus * >( this->giveStatus(gp) );

    double kappa, dKappa, yieldValue, mi;
    FloatMatrix F, oldF, invOldF;
    FloatArray s;
    F.beMatrixForm(totalDefGradOOFEM); //(method assumes full 3D)

    kappa = status->giveCumulativePlasticStrain();
    oldF.beMatrixForm( status->giveFVector() );
    invOldF.beInverseOf(oldF);
    //relative deformation radient
    FloatMatrix f;
    f.beProductOf(F, invOldF);
    //compute elastic predictor
    FloatMatrix trialLeftCauchyGreen, help;

    f.times( 1./cbrt(f.giveDeterminant()) );

    help.beProductOf(f, status->giveTempLeftCauchyGreen());
    trialLeftCauchyGreen.beProductTOf(help, f);
    FloatMatrix E;
    E.beTProductOf(F, F);
    E.at(1, 1) -= 1.0;
    E.at(2, 2) -= 1.0;
    E.at(3, 3) -= 1.0;
    E.times(0.5);

    FloatArray e;
    e.beSymVectorFormOfStrain(E);

    FloatArray leftCauchyGreen;
    FloatArray leftCauchyGreenDev;
    double leftCauchyGreenVol;

    leftCauchyGreen.beSymVectorFormOfStrain(trialLeftCauchyGreen);

    leftCauchyGreenVol = computeDeviatoricVolumetricSplit(leftCauchyGreenDev, leftCauchyGreen);
    FloatArray trialStressDev;
    applyDeviatoricElasticStiffness(trialStressDev, leftCauchyGreenDev, G / 2.);
    s = trialStressDev;

    //check for plastic loading
    double trialS = computeStressNorm(trialStressDev);
    double sigmaY = sig0 + H * kappa;
    //yieldValue = sqrt(3./2.)*trialS-sigmaY;
    yieldValue = trialS - sqrt(2. / 3.) * sigmaY;


    //store deviatoric trial stress(reused by algorithmic stiffness)
    status->letTrialStressDevBe(trialStressDev);
    //the return-mapping algorithm
    double J = F.giveDeterminant();
    mi = leftCauchyGreenVol * G;
    if ( yieldValue > 0 ) {
        //dKappa =sqrt(3./2.)* yieldValue/(H + 3.*mi);
        //kappa = kappa + dKappa;
        //trialStressDev.times(1-sqrt(6.)*mi*dKappa/trialS);
        dKappa = ( yieldValue / ( 2 * mi ) ) / ( 1 + H / ( 3 * mi ) );
        FloatArray n = trialStressDev;
        n.times(2 * mi * dKappa / trialS);
        ////return map
        s.beDifferenceOf(trialStressDev, n);
        kappa += sqrt(2. / 3.) * dKappa;


        //update of intermediate configuration
        trialLeftCauchyGreen.beMatrixForm(s);
        trialLeftCauchyGreen.times(1.0 / G);
        trialLeftCauchyGreen.at(1, 1) += leftCauchyGreenVol;
        trialLeftCauchyGreen.at(2, 2) += leftCauchyGreenVol;
        trialLeftCauchyGreen.at(2, 2) += leftCauchyGreenVol;
        trialLeftCauchyGreen.times(J * J);
    }

    //addition of the elastic mean stress
    FloatMatrix kirchhoffStress;
    kirchhoffStress.beMatrixForm(s);
    kirchhoffStress.at(1, 1) += 1. / 2. *  K * ( J * J - 1 );
    kirchhoffStress.at(2, 2) += 1. / 2. *  K * ( J * J - 1 );
    kirchhoffStress.at(3, 3) += 1. / 2. *  K * ( J * J - 1 );


    FloatMatrix iF, Ep(3, 3), S;
    FloatArray vF, vS, ep;

    //transform Kirchhoff stress into Second Piola - Kirchhoff stress
    iF.beInverseOf(F);
    help.beProductOf(iF, kirchhoffStress);
    S.beProductTOf(help, iF);

    this->computeGLPlasticStrain(F, Ep, trialLeftCauchyGreen, J);

    ep.beSymVectorFormOfStrain(Ep);
    vS.beSymVectorForm(S);
    vF.beVectorForm(F);
    answer.beVectorForm(kirchhoffStress);

    status->setTrialStressVol(mi);
    status->letTempLeftCauchyGreenBe(trialLeftCauchyGreen);
    status->setTempCumulativePlasticStrain(kappa);
    status->letTempStressVectorBe(answer);
    status->letTempStrainVectorBe(e);
    status->letTempPlasticStrainBe(ep);
    status->letTempPVectorBe(answer);
    status->letTempFVectorBe(vF);
}
示例#13
0
void PLHoopStressCirc :: propagateInterfaces(Domain &iDomain, EnrichmentDomain &ioEnrDom)
{
    // Fetch crack tip data
    TipInfo tipInfoStart, tipInfoEnd;
    ioEnrDom.giveTipInfos(tipInfoStart, tipInfoEnd);
    std :: vector< TipInfo >tipInfo = {tipInfoStart, tipInfoEnd};

    SpatialLocalizer *localizer = iDomain.giveSpatialLocalizer();

    for ( size_t tipIndex = 0; tipIndex < tipInfo.size(); tipIndex++ ) {
        // Construct circle points on an arc from -90 to 90 degrees
        double angle = -90.0 + mAngleInc;
        std :: vector< double >angles;
        while ( angle <= ( 90.0 - mAngleInc ) ) {
            angles.push_back(angle * M_PI / 180.0);
            angle += mAngleInc;
        }

        const FloatArray &xT    = tipInfo [ tipIndex ].mGlobalCoord;
        const FloatArray &t             = tipInfo [ tipIndex ].mTangDir;
        const FloatArray &n             = tipInfo [ tipIndex ].mNormalDir;

        // It is meaningless to propagate a tip that is not inside any element
        Element *el = localizer->giveElementContainingPoint(tipInfo [ tipIndex ].mGlobalCoord);
        if ( el != NULL ) {
            std :: vector< FloatArray >circPoints;

            for ( size_t i = 0; i < angles.size(); i++ ) {
                FloatArray tangent(2);
                tangent.zero();
                tangent.add(cos(angles [ i ]), t);
                tangent.add(sin(angles [ i ]), n);
                tangent.normalize();

                FloatArray x(xT);
                x.add(mRadius, tangent);
                circPoints.push_back(x);
            }



            std :: vector< double >sigTTArray, sigRTArray;

            // Loop over circle points
            for ( size_t pointIndex = 0; pointIndex < circPoints.size(); pointIndex++ ) {
                FloatArray stressVec;

                if ( mUseRadialBasisFunc ) {
                    // Interpolate stress with radial basis functions

                    // Choose a cut-off length l:
                    // take the distance between two nodes in the element containing the
                    // crack tip multiplied by a constant factor.
                    // ( This choice implies that we hope that the element has reasonable
                    // aspect ratio.)
                    const FloatArray &x1 = * ( el->giveDofManager(1)->giveCoordinates() );
                    const FloatArray &x2 = * ( el->giveDofManager(2)->giveCoordinates() );
                    const double l = 1.0 * x1.distance(x2);

                    // Use the octree to get all elements that have
                    // at least one Gauss point in a certain region around the tip.
                    const double searchRadius = 3.0 * l;
                    std :: set< int >elIndices;
                    localizer->giveAllElementsWithIpWithinBox(elIndices, circPoints [ pointIndex ], searchRadius);


                    // Loop over the elements and Gauss points obtained.
                    // Evaluate the interpolation.
                    FloatArray sumQiWiVi;
                    double sumWiVi = 0.0;
                    for ( int elIndex: elIndices ) {
                        Element *gpEl = iDomain.giveElement(elIndex);
                        IntegrationRule *iRule = gpEl->giveDefaultIntegrationRulePtr();

                        for ( GaussPoint *gp_i: *iRule ) {

                            ////////////////////////////////////////
                            // Compute global gp coordinates
                            FloatArray N;
                            FEInterpolation *interp = gpEl->giveInterpolation();
                            interp->evalN( N, * ( gp_i->giveCoordinates() ), FEIElementGeometryWrapper(gpEl) );


                            // Compute global coordinates of Gauss point
                            FloatArray globalCoord(2);
                            globalCoord.zero();

                            for ( int i = 1; i <= gpEl->giveNumberOfDofManagers(); i++ ) {
                                DofManager *dMan = gpEl->giveDofManager(i);
                                globalCoord.at(1) += N.at(i) * dMan->giveCoordinate(1);
                                globalCoord.at(2) += N.at(i) * dMan->giveCoordinate(2);
                            }


                            ////////////////////////////////////////
                            // Compute weight of kernel function

                            FloatArray tipToGP;
                            tipToGP.beDifferenceOf(globalCoord, xT);
                            bool inFrontOfCrack = true;
                            if ( tipToGP.dotProduct(t) < 0.0 ) {
                                inFrontOfCrack = false;
                            }

                            double r = circPoints [ pointIndex ].distance(globalCoord);

                            if ( r < l && inFrontOfCrack ) {
                                double w = ( ( l - r ) / ( pow(2.0 * M_PI, 1.5) * pow(l, 3) ) ) * exp( -0.5 * pow(r, 2) / pow(l, 2) );

                                // Compute gp volume
                                double V = gpEl->computeVolumeAround(gp_i);

                                // Get stress
                                StructuralMaterialStatus *ms = dynamic_cast< StructuralMaterialStatus * >( gp_i->giveMaterialStatus() );
                                if ( ms == NULL ) {
                                    OOFEM_ERROR("failed to fetch MaterialStatus.");
                                }

                                FloatArray stressVecGP = ms->giveStressVector();

                                if ( sumQiWiVi.giveSize() != stressVecGP.giveSize() ) {
                                    sumQiWiVi.resize( stressVecGP.giveSize() );
                                    sumQiWiVi.zero();
                                }

                                // Add to numerator
                                sumQiWiVi.add(w * V, stressVecGP);

                                // Add to denominator
                                sumWiVi += w * V;
                            }
                        }
                    }


                    if ( fabs(sumWiVi) > 1.0e-12 ) {
                        stressVec.beScaled(1.0 / sumWiVi, sumQiWiVi);
                    } else {
                        // Take stress from closest Gauss point
                        int region = 1;
                        bool useCZGP = false;
                        GaussPoint &gp = * ( localizer->giveClosestIP(circPoints [ pointIndex ], region, useCZGP) );


                        // Compute stresses
                        StructuralMaterialStatus *ms = dynamic_cast< StructuralMaterialStatus * >( gp.giveMaterialStatus() );
                        if ( ms == NULL ) {
                            OOFEM_ERROR("failed to fetch MaterialStatus.");
                        }

                        stressVec = ms->giveStressVector();
                    }
                } else {
                    // Take stress from closest Gauss point
                    int region = 1;
                    bool useCZGP = false;
                    GaussPoint &gp = * ( localizer->giveClosestIP(circPoints [ pointIndex ], region, useCZGP) );


                    // Compute stresses
                    StructuralMaterialStatus *ms = dynamic_cast< StructuralMaterialStatus * >( gp.giveMaterialStatus() );
                    if ( ms == NULL ) {
                        OOFEM_ERROR("failed to fetch MaterialStatus.");
                    }

                    stressVec = ms->giveStressVector();
                }

                FloatMatrix stress(2, 2);

                int shearPos = stressVec.giveSize();

                stress.at(1, 1) = stressVec.at(1);
                stress.at(1, 2) = stressVec.at(shearPos);
                stress.at(2, 1) = stressVec.at(shearPos);
                stress.at(2, 2) = stressVec.at(2);


                // Rotation matrix
                FloatMatrix rot(2, 2);
                rot.at(1, 1) =  cos(angles [ pointIndex ]);
                rot.at(1, 2) = -sin(angles [ pointIndex ]);
                rot.at(2, 1) =  sin(angles [ pointIndex ]);
                rot.at(2, 2) =  cos(angles [ pointIndex ]);

                FloatArray tRot, nRot;
                tRot.beProductOf(rot, t);
                nRot.beProductOf(rot, n);

                FloatMatrix rotTot(2, 2);
                rotTot.setColumn(tRot, 1);
                rotTot.setColumn(nRot, 2);


                FloatMatrix tmp, stressRot;

                tmp.beTProductOf(rotTot, stress);
                stressRot.beProductOf(tmp, rotTot);


                const double sigThetaTheta      =               stressRot.at(2, 2);
                sigTTArray.push_back(sigThetaTheta);

                const double sigRTheta          =               stressRot.at(1, 2);
                sigRTArray.push_back(sigRTheta);
            }

            //////////////////////////////
            // Compute propagation angle

            // Find angles that fulfill sigRT = 0
            const double stressTol = 1.0e-9;
            double maxSigTT = 0.0, maxAngle = 0.0;
            bool foundZeroLevel = false;
            for ( size_t segIndex = 0; segIndex < ( circPoints.size() - 1 ); segIndex++ ) {
                // If the shear stress sigRT changes sign over the segment
                if ( sigRTArray [ segIndex ] * sigRTArray [ segIndex + 1 ] < stressTol ) {
                    // Compute location of zero level
                    double xi = EnrichmentItem :: calcXiZeroLevel(sigRTArray [ segIndex ], sigRTArray [ segIndex + 1 ]);

                    double theta                    = 0.5 * ( 1.0 - xi ) * angles [ segIndex ]         + 0.5 * ( 1.0 + xi ) * angles [ segIndex + 1 ];
                    double sigThetaTheta    = 0.5 * ( 1.0 - xi ) * sigTTArray [ segIndex ] + 0.5 * ( 1.0 + xi ) * sigTTArray [ segIndex + 1 ];

                    //					printf("Found candidate: theta: %e sigThetaTheta: %e\n", theta, sigThetaTheta);

                    if ( sigThetaTheta > maxSigTT ) {
                        foundZeroLevel = true;
                        maxSigTT = sigThetaTheta;
                        maxAngle = theta;
                    }
                }
            }

            if ( !foundZeroLevel ) {
                printf("No zero level was found.\n");
            }

            if ( iDomain.giveXfemManager()->giveVtkDebug() ) {
                XFEMDebugTools :: WriteArrayToMatlab("sigTTvsAngle.m", angles, sigTTArray);
                XFEMDebugTools :: WriteArrayToMatlab("sigRTvsAngle.m", angles, sigRTArray);

                XFEMDebugTools :: WriteArrayToGnuplot("sigTTvsAngle.dat", angles, sigTTArray);
                XFEMDebugTools :: WriteArrayToGnuplot("sigRTvsAngle.dat", angles, sigRTArray);
            }

            // Compare with threshold
            if ( maxSigTT > mHoopStressThreshold && foundZeroLevel ) {
                // Rotation matrix
                FloatMatrix rot(2, 2);
                rot.at(1, 1) =  cos(maxAngle);
                rot.at(1, 2) = -sin(maxAngle);
                rot.at(2, 1) =  sin(maxAngle);
                rot.at(2, 2) =  cos(maxAngle);

                FloatArray dir;
                dir.beProductOf(rot, tipInfo [ tipIndex ].mTangDir);

                // Fill up struct
                std :: vector< TipPropagation >tipPropagations;
                TipPropagation tipProp;
                tipProp.mTipIndex = tipIndex;
                tipProp.mPropagationDir = dir;
                tipProp.mPropagationLength = mIncrementLength;
                tipPropagations.push_back(tipProp);


                // Propagate
                ioEnrDom.propagateTips(tipPropagations);
            }
        }
    }
}
示例#14
0
void FE2FluidMaterial :: giveStiffnessMatrices(FloatMatrix &dsdd, FloatArray &dsdp, FloatArray &dedd, double &dedp,
                                               MatResponseMode mode, GaussPoint *gp, TimeStep *tStep)
{
    FE2FluidMaterialStatus *ms = static_cast< FE2FluidMaterialStatus * >( this->giveStatus(gp) );
    ms->computeTangents(tStep);
    if ( mode == TangentStiffness ) {
        dsdd = ms->giveDeviatoricTangent();
        dsdp = ms->giveDeviatoricPressureTangent();
        dedd = ms->giveVolumetricDeviatoricTangent();
        dedp = ms->giveVolumetricPressureTangent();
#if 0
        // Numerical ATS for debugging
        FloatMatrix numericalATS(6, 6);
        FloatArray dsig;
        FloatArray tempStrain(6);

        tempStrain.zero();
        FloatArray sig, strain, sigPert;
        double epspvol;
        computeDeviatoricStressVector(sig, epspvol, gp, tempStrain, 0., tStep);
        double h = 0.001; // Linear problem, size of this doesn't matter.
        for ( int k = 1; k <= 6; ++k ) {
            strain = tempStrain;
            strain.at(k) += h;
            double tmp = strain.at(1) + strain.at(2) + strain.at(3);
            strain.at(1) -= tmp/3.0;
            strain.at(2) -= tmp/3.0;
            strain.at(3) -= tmp/3.0;
            strain.printYourself();
            computeDeviatoricStressVector(sigPert, epspvol, gp, strain, 0., tStep);
            sigPert.printYourself();
            dsig.beDifferenceOf(sigPert, sig);
            numericalATS.setColumn(dsig, k);
        }
        numericalATS.times(1. / h);

        printf("Analytical deviatoric tangent = ");
        dsdd.printYourself();
        printf("Numerical deviatoric tangent = ");
        numericalATS.printYourself();
        numericalATS.subtract(dsdd);
        double norm = numericalATS.computeFrobeniusNorm();
        if ( norm > dsdd.computeFrobeniusNorm() * DEBUG_ERR && norm > 0.0 ) {
            OOFEM_ERROR("Error in deviatoric tangent");
        }
#endif
#if 0
        // Numerical ATS for debugging
        FloatArray strain(3);
        strain.zero();
        FloatArray sig, sigh;
        double epspvol, pressure = 0.0;
        double h = 1.00; // Linear problem, size of this doesn't matter.
        computeDeviatoricStressVector(sig, epspvol, gp, strain, pressure, tStep);
        computeDeviatoricStressVector(sigh, epspvol, gp, strain, pressure + h, tStep);

        FloatArray dsigh;
        dsigh.beDifferenceOf(sigh, sig);
        dsigh.times(1 / h);

        printf("Analytical deviatoric pressure tangent = ");
        dsdp.printYourself();
        printf("Numerical deviatoric pressure tangent = ");
        dsigh.printYourself();
        dsigh.subtract(dsdp);
        double norm = dsigh.computeNorm();
        if ( norm > dsdp.computeNorm() * DEBUG_ERR && norm > 0.0 ) {
            OOFEM_ERROR("Error in deviatoric pressure tangent");
        }
#endif
#if 0
        // Numerical ATS for debugging
        FloatArray tempStrain(3);
        tempStrain.zero();
        FloatArray sig, strain;
        double epspvol, epspvol11, epspvol22, epspvol12, pressure = 0.0;
        double h = 1.0; // Linear problem, size of this doesn't matter.

        computeDeviatoricStressVector(sig, epspvol, gp, tempStrain, pressure, tStep);
        strain = tempStrain;
        strain.at(1) += h;
        computeDeviatoricStressVector(sig, epspvol11, gp, strain, pressure, tStep);
        strain = tempStrain;
        strain.at(2) += h;
        computeDeviatoricStressVector(sig, epspvol22, gp, strain, pressure, tStep);
        strain = tempStrain;
        strain.at(3) += h;
        computeDeviatoricStressVector(sig, epspvol12, gp, strain, pressure, tStep);

        FloatArray dvol(3);
        dvol.at(1) = ( epspvol11 - epspvol ) / h;
        dvol.at(2) = ( epspvol22 - epspvol ) / h;
        dvol.at(3) = ( epspvol12 - epspvol ) / h;
        dvol.at(1) += 1.0;
        dvol.at(2) += 1.0;

        printf("Analytical volumetric deviatoric tangent = ");
        dedd.printYourself();
        printf("Numerical volumetric deviatoric tangent = ");
        dvol.printYourself();
        dvol.subtract(dedd);
        double norm = dvol.computeNorm();
        if ( norm > dedd.computeNorm() * DEBUG_ERR && norm > 0.0 ) {
            OOFEM_ERROR("Error in volumetric deviatoric tangent");
        }
#endif
#if 0
        // Numerical ATS for debugging
        FloatArray strain(3);
        strain.zero();
        FloatArray sig;
        double epspvol, epspvolh, pressure = 0.0;
        double h = 1.0; // Linear problem, size of this doesn't matter.

        computeDeviatoricStressVector(sig, epspvol, gp, strain, pressure, tStep);
        computeDeviatoricStressVector(sig, epspvolh, gp, strain, pressure + h, tStep);

        double dvol = -( epspvolh - epspvol ) / h;

        printf("Analytical volumetric pressure tangent = %e\n", dedp);
        printf("Numerical volumetric pressure tangent = %e\n", dvol);

        double norm = fabs(dvol - dedp);
        if ( norm > fabs(dedp) * DEBUG_ERR && norm > 0.0 ) {
            OOFEM_ERROR("Error in volumetric pressure tangent");
        }
#endif
    } else {
        OOFEM_ERROR("Mode not implemented");
    }
}
示例#15
0
void IntMatBilinearCZ :: giveFirstPKTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump,
                                                const FloatMatrix &F, TimeStep *tStep)
{
    IntMatBilinearCZStatus *status = static_cast< IntMatBilinearCZStatus * >( this->giveStatus(gp) );

    status->mJumpNew = jump;

    FloatArray jumpInc;
    jumpInc.beDifferenceOf(status->mJumpNew, status->mJumpOld);

    FloatArray tractionTrial = status->mTractionOld;
    tractionTrial.add(mPenaltyStiffness, jumpInc);

    double TTrNormal    = tractionTrial.at(3);
    double TTrTang              = sqrt( pow(tractionTrial.at(1), 2.0) + pow(tractionTrial.at(2), 2.0) );
    double phiTr = computeYieldFunction(TTrNormal, TTrTang);

    const double damageTol = 1.0e-6;
    if ( status->mDamageOld > ( 1.0 - damageTol ) ) {
        status->mDamageNew = 1.0;
        status->mPlastMultIncNew = 0.0;
        answer.resize(3);
        answer.zero();
        status->mTractionNew = answer;

        status->letTempJumpBe(jump);
        status->letTempFirstPKTractionBe(answer);
        status->letTempTractionBe(answer);

        return;
    }


    answer = tractionTrial;

    if ( phiTr < 0.0 ) {
        status->mDamageNew = status->mDamageOld;
        status->mPlastMultIncNew = 0.0;
        answer.beScaled( ( 1.0 - status->mDamageNew ), answer );

        status->mTractionNew = answer;

        status->letTempJumpBe(jump);
        status->letTempFirstPKTractionBe(answer);
        status->letTempTractionBe(answer);

        return;
    } else {
        // Iterate to find plastic strain increment.
        int maxIter = 50;
        int minIter = 1;
        double absTol = 1.0e-9; // Absolute error tolerance
        double relTol = 1.0e-9; // Relative error tolerance
        double eps = 1.0e-12; // Small value for perturbation when computing numerical Jacobian
        double plastMultInc = 0.0;
        double initialRes = 0.0;

        for ( int iter = 0; iter < maxIter; iter++ ) {
            // Evaluate residual (i.e. yield function)
            computeTraction(answer, tractionTrial, plastMultInc);

            double TNormal      = answer.at(3);
            double TTang                = sqrt( pow(answer.at(1), 2.0) + pow(answer.at(2), 2.0) );
            double phi = computeYieldFunction(TNormal, TTang);

            //          if(iter > 20) {
            //              printf("iter: %d res: %e\n", iter, fabs(phi) );
            //          }

            if ( iter == 0 ) {
                initialRes = fabs(phi);
                initialRes = max(initialRes, 1.0e-12);
            }

            if ( (iter >= minIter && fabs(phi) < absTol) || ( iter >= minIter && ( fabs(phi) / initialRes ) < relTol ) ) {
                // Add damage evolution
                double S = mGIc / mSigmaF;
                status->mPlastMultIncNew = plastMultInc;

                double damageInc = status->mPlastMultIncNew / S;
                status->mDamageNew = status->mDamageOld + damageInc;

                if ( status->mDamageNew > 1.0 ) {
                    status->mDamageNew = 1.0;
                }

                if(mSemiExplicit) {
//                    computeTraction(answer, tractionTrial, status->mPlastMultIncOld);
                    answer.beScaled( ( 1.0 - status->mDamageOld ), answer );
               }
                else {
                    answer.beScaled( ( 1.0 - status->mDamageNew ), answer );
                }

                status->mTractionNew = answer;

                // Jim
                status->letTempJumpBe(jump);
                status->letTempFirstPKTractionBe(answer);
                status->letTempTractionBe(answer);

                return;
            }

            // Numerical Jacobian
            FloatArray tractionPert(3);
            computeTraction(tractionPert, tractionTrial, plastMultInc + eps);
            double TNormalPert          = tractionPert.at(3);
            double TTangPert            = sqrt( pow(tractionPert.at(1), 2.0) + pow(tractionPert.at(2), 2.0) );
            double phiPert = computeYieldFunction(TNormalPert, TTangPert);

            double Jac = ( phiPert - phi ) / eps;
            plastMultInc -= ( 1.0 / Jac ) * phi;
        }
    }

    OOFEM_ERROR("No convergence in.");
}
NM_Status
DynamicRelaxationSolver :: solve(SparseMtrx &k, FloatArray &R, FloatArray *R0, FloatArray *iR,
                  FloatArray &X, FloatArray &dX, FloatArray &F,
                  const FloatArray &internalForcesEBENorm, double &l, referenceLoadInputModeType rlm,
                  int &nite, TimeStep *tStep)

{
    // residual, iteration increment of solution, total external force
    FloatArray rhs, ddX, RT, X_0, X_n, X_n1, M;

    double RRT;
    int neq = X.giveSize();
    NM_Status status = NM_None;
    bool converged, errorOutOfRangeFlag;
    ParallelContext *parallel_context = engngModel->giveParallelContext( this->domain->giveNumber() );
    if ( engngModel->giveProblemScale() == macroScale ) {
        OOFEM_LOG_INFO("DRSolver: Iteration");
        if ( rtolf.at(1) > 0.0 ) {
            OOFEM_LOG_INFO(" ForceError");
        }
        if ( rtold.at(1) > 0.0 ) {
            OOFEM_LOG_INFO(" DisplError");
        }
        OOFEM_LOG_INFO("\n----------------------------------------------------------------------------\n");
    }

    // compute total load R = R+R0
    l = 1.0;
    RT = R;
    if ( R0 ) {
        RT.add(* R0);
    }

    RRT = parallel_context->localNorm(RT);
    RRT *= RRT;

    ddX.resize(neq);
    ddX.zero();

    X_0 = X;
    X_n = X_0;
    X_n1 = X_0;

    // Compute the mass "matrix" (lumped, only storing the diagonal)
    M.resize(neq);
    M.zero();
    engngModel->assembleVector(M, tStep, LumpedMassVectorAssembler(), VM_Total, EModelDefaultEquationNumbering(), domain);

    double Le = -1.0;
    for ( auto &elem : domain->giveElements() ) {
        double size = elem->computeMeanSize();
        if ( Le < 0 || Le >= size ) {
            Le = size;
        }
    }

    for ( nite = 0; ; ++nite ) {
        // Compute the residual
        engngModel->updateComponent(tStep, InternalRhs, domain);
        rhs.beDifferenceOf(RT, F);

        converged = this->checkConvergence(RT, F, rhs, ddX, X, RRT, internalForcesEBENorm, nite, errorOutOfRangeFlag);
        if ( errorOutOfRangeFlag ) {
            status = NM_NoSuccess;
            dX.zero();
            X.zero();
            OOFEM_WARNING("Divergence reached after %d iterations", nite);
            break;
        } else if ( converged && ( nite >= minIterations ) ) {
            status |= NM_Success;
            break;
        } else if ( nite >= nsmax ) {
            OOFEM_LOG_DEBUG("Maximum number of iterations reached\n");
            break;
        }

        double density = 1.;
        double lambda = 210e9;
        double mu = 210e9;
        double c = sqrt((lambda + 2*mu) / density);
        double dt = 0.25 * Le / c;
        double alpha = 0.1 / dt;
        printf("dt = %e\n", dt);
        for ( int j = 0; j < neq; ++j ) {
            //M * x'' + C*x' * dt = rhs * dt*dt
            X[j] = rhs[j] * dt * dt / M[j] - ( -2*X_n1[j] + X_n[j] ) - alpha * (X_n1[j] - X_n[j]) * dt;
        }
        X_n = X_n1;
        X_n1 = X;

        dX.beDifferenceOf(X, X_0);
        tStep->incrementStateCounter(); // update solution state counter
        tStep->incrementSubStepNumber();
    }

    return status;
}
示例#17
0
void
TutorialMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp,
                                 const FloatArray &totalStrain, TimeStep *tStep)
{
    FloatArray strain;
    TutorialMaterialStatus *status = static_cast< TutorialMaterialStatus * >( this->giveStatus(gp) );

    // subtract stress thermal expansion
    this->giveStressDependentPartOfStrainVector_3d(strain, gp, totalStrain, tStep, VM_Total);
    
    FloatArray trialElastStrain;
    trialElastStrain.beDifferenceOf(strain, status->givePlasticStrain());

    // Compute trial stress = sig_tr = sig_old + E*delta_eps
    FloatMatrix elasticStiffness;
    D.give3dMaterialStiffnessMatrix(elasticStiffness, TangentStiffness, gp, tStep);
    FloatArray trialStress;
    trialStress.beProductOf(elasticStiffness, trialElastStrain);

    FloatArray sphTrialStress, devTrialStress;
    computeSphDevPartOf(trialStress, sphTrialStress, devTrialStress);
    
    double J2 = this->computeSecondStressInvariant(devTrialStress);
    double effectiveTrialStress = sqrt(3 * J2);

#if 1
    double temperatureScaling = 1.0;
#else
    double temperature;
    FloatArray et;
    static_cast< StructuralElement *>(gp->giveIntegrationRule()->giveElement())->computeResultingIPTemperatureAt(et, tStep, gp, VM_Total);
    temperature = et.at(1) + 800;

    double temperatureScaling = temperature <= 400 ? 1.0 : 1.0 - (temperature - 400) * 0.5 / 400;
#endif

    // evaluate the yield surface
    double k = status->giveK();
    double phiTrial = effectiveTrialStress - ( temperatureScaling * this->sig0 +  temperatureScaling * H * k );
    
    if ( phiTrial < 0.0 ) { // elastic
        answer = trialStress;

        status->letTempPlasticStrainBe(status->givePlasticStrain());
    } else { // plastic loading
        double G = D.giveShearModulus();
        double mu = phiTrial / ( 3.0 * G + temperatureScaling * H ); // plastic multiplier
        answer = devTrialStress * ( 1.0 - 3.0*G*mu/effectiveTrialStress); // radial return
        answer.add(sphTrialStress);
        k += mu;

        FloatArray plasticStrain = status->givePlasticStrain();
        FloatArray dPlStrain;
        applyDeviatoricElasticCompliance(dPlStrain, devTrialStress, 0.5);
        plasticStrain.add(mu * 3. / (2. * effectiveTrialStress), dPlStrain);
        status->letTempPlasticStrainBe(plasticStrain);
    }
    
    // Store the temporary values for the given iteration
    status->letTempStrainVectorBe(totalStrain);
    status->letTempStressVectorBe(answer);
    status->letTempKBe(k);
    status->letTempDevTrialStressBe(devTrialStress);
}
示例#18
0
void
PlasticMaterial :: giveRealStressVector(FloatArray &answer,
                                        GaussPoint *gp,
                                        const FloatArray &totalStrain,
                                        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
//
// completely formulated in Reduced stress-strain space
{
    FloatArray strainSpaceHardeningVariables;
    FloatArray fullStressVector, *fullStressSpaceHardeningVars, *residualVectorR;
    FloatArray elasticStrainVectorR;
    FloatArray strainVectorR, plasticStrainVectorR, *gradientVectorR;
    FloatArray helpVec, helpVec2;
    double yieldValue, Gamma, dGamma, helpVal1, helpVal2;
    int strSize, totSize, nIterations = 0;
    FloatMatrix elasticModuli, hardeningModuli, consistentModuli;
    FloatMatrix elasticModuliInverse, hardeningModuliInverse;
    FloatMatrix helpMtrx, helpMtrx2;

    PlasticMaterialStatus *status = static_cast< PlasticMaterialStatus * >( this->giveStatus(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(strainVectorR, gp, totalStrain,
                                                tStep, VM_Total);

    plasticStrainVectorR = status->givePlasticStrainVector();
    strainSpaceHardeningVariables = status->giveStrainSpaceHardeningVars();

    // tady konec debugovani - strainSpaceHardeningVariables ve statusu neinicializovany
    // to musi udelat material.

    Gamma = 0.;
    strSize = strainVectorR.giveSize(); // size of reducedStrain Vector
    totSize = strSize + strainSpaceHardeningVariables.giveSize();

    // compute elastic moduli and its inverse
    this->computeReducedElasticModuli(elasticModuli, gp, tStep);
    elasticModuliInverse.beInverseOf(elasticModuli);

    do {
        elasticStrainVectorR.beDifferenceOf(strainVectorR, plasticStrainVectorR);
        // stress vector in full form due to computational convenience
        this->computeTrialStressIncrement(fullStressVector, gp, elasticStrainVectorR, tStep);
        fullStressSpaceHardeningVars = this->ComputeStressSpaceHardeningVars(gp, & strainSpaceHardeningVariables);
        yieldValue = this->computeYieldValueAt(gp, & fullStressVector, fullStressSpaceHardeningVars);
        gradientVectorR = this->ComputeGradientVector(gp, & fullStressVector, fullStressSpaceHardeningVars);
        residualVectorR = this->ComputeResidualVector(gp, Gamma, & plasticStrainVectorR,
                                                      & strainSpaceHardeningVariables,
                                                      gradientVectorR);

        // check for end of iteration
        if ( ( yieldValue < YIELD_TOL ) && ( residualVectorR->computeNorm() < RES_TOL ) ) {
            delete fullStressSpaceHardeningVars;
            delete gradientVectorR;
            delete residualVectorR;
            break;
        }

        // compute  consistent tangent moduli
        this->computeHardeningReducedModuli(hardeningModuli, gp, & strainSpaceHardeningVariables, tStep);
        if ( hardeningModuli.giveNumberOfRows() ) {
            hardeningModuliInverse.beInverseOf(hardeningModuli);
        } else {
            hardeningModuliInverse.clear();
        }

        this->computeConsistentModuli(consistentModuli, gp, elasticModuliInverse,
                                      hardeningModuliInverse, Gamma,
                                      fullStressVector, * fullStressSpaceHardeningVars);

        // obtain increment to consistency parameter
        helpMtrx.initFromVector(* gradientVectorR, 1);
        helpMtrx2.beProductOf(helpMtrx, consistentModuli);
        helpVec.beProductOf(helpMtrx2, * gradientVectorR);
        helpVal1 = helpVec.at(1);
        helpVec.beProductOf(helpMtrx2, * residualVectorR);
        helpVal2 = helpVec.at(1);
        dGamma = ( yieldValue - helpVal2 ) / helpVal1;

        // obtain incremental plastic strains and internal variables
        // we overwrite residualVectorR and gradientVectorR vectors
        // but they are computed once again when iteration continues
        gradientVectorR->times(dGamma);
        residualVectorR->add(* gradientVectorR);
        helpVec.beProductOf(consistentModuli, * residualVectorR);
        // note elasticModuli and hardeningModuli are yet inverted
        this->computeDiagModuli(helpMtrx, gp, elasticModuliInverse, hardeningModuliInverse);
        helpVec2.beProductOf(helpMtrx, helpVec);

        // Update state variables and consistency parameter
        for ( int i = 1; i <= strSize; i++ ) {
            plasticStrainVectorR.at(i) += helpVec2.at(i);
        }

        for ( int i = strSize + 1; i <= totSize; i++ ) {
            strainSpaceHardeningVariables.at(i - strSize) += helpVec2.at(i);
        }

        Gamma += dGamma;

        // increment iteration count
        nIterations++;

        // free allocated memory inside loop
        delete fullStressSpaceHardeningVars;
        delete gradientVectorR;
        delete residualVectorR;

        if ( nIterations > PLASTIC_MATERIAL_MAX_ITERATIONS ) {
            OOFEM_WARNING("local equlibrium not reached in %d iterations\nElement %d, gp %d, continuing",
                      PLASTIC_MATERIAL_MAX_ITERATIONS, gp->giveElement()->giveNumber(), gp->giveNumber() );
            break;
        }
    } while ( 1 );

    // update temp state variables in gp and associted material status

    status->letTempStrainVectorBe(totalStrain);
    StructuralMaterial :: giveReducedSymVectorForm( helpVec, fullStressVector, gp->giveMaterialMode() );
    status->letTempStressVectorBe(helpVec);
    status->letTempPlasticStrainVectorBe(plasticStrainVectorR);
    status->letTempStrainSpaceHardeningVarsVectorBe(strainSpaceHardeningVariables);
    // update plastic consistency parameter
    status->letTempPlasticConsistencyPrameterBe(Gamma);

    // update state flag
    int newState, state = status->giveStateFlag();
    if ( Gamma > 0. ) {
        newState = PM_Yielding;            // test if plastic loading occur
    }
    // no plastic loading - check for unloading
    else if ( ( state == PM_Yielding ) || ( state == PM_Unloading ) ) {
        newState = PM_Unloading;
    } else {
        newState = PM_Elastic;
    }

    status->letTempStateFlagBe(newState);

    answer = status->giveTempStressVector();
}
示例#19
0
void PolygonLine :: computeNormalSignDist(double &oDist, const FloatArray &iPoint) const
{
    const FloatArray &point = {iPoint[0], iPoint[1]};

    oDist = std :: numeric_limits< double > :: max();
    int numSeg = this->giveNrVertices() - 1;

    // TODO: This can probably be done in a nicer way.
    // Ensure that we work in 2d.
    const int dim = 2;

    for ( int segId = 1; segId <= numSeg; segId++ ) {
        // Crack segment
        const FloatArray &crackP1( this->giveVertex ( segId ) );

        const FloatArray &crackP2( this->giveVertex ( segId + 1 ) );

        double dist2 = 0.0;
        if ( segId == 1 ) {
            // Vector from start P1 to point X
            FloatArray u = {point.at(1) - crackP1.at(1), point.at(2) - crackP1.at(2)};

            // Line tangent vector
            FloatArray t = {crackP2.at(1) - crackP1.at(1), crackP2.at(2) - crackP1.at(2)};
            double l2 = t.computeSquaredNorm();

            if ( l2 > 0.0 ) {
                double l = t.normalize();
                double s = dot(u, t);

                if ( s > l ) {
                    // X is closest to P2
                    dist2 = point.distance_square(crackP2);
                } else {
                    double xi = s / l;
                    FloatArray q = ( 1.0 - xi ) * crackP1 + xi * crackP2;
                    dist2 = point.distance_square(q);
                }
            } else {
                // If the points P1 and P2 coincide,
                // we can compute the distance to any
                // of these points.
                dist2 = point.distance_square(crackP1);
            }
        } else if ( segId == numSeg ) {
            // Vector from start P1 to point X
            FloatArray u = {point.at(1) - crackP1.at(1), point.at(2) - crackP1.at(2)};

            // Line tangent vector
            FloatArray t = {crackP2.at(1) - crackP1.at(1), crackP2.at(2) - crackP1.at(2)};
            double l2 = t.computeSquaredNorm();

            if ( l2 > 0.0 ) {
                double l = t.normalize();
                double s = dot(u, t);

                if ( s < 0.0 ) {
                    // X is closest to P1
                    dist2 = point.distance_square(crackP1);
                } else {
                    double xi = s / l;
                    FloatArray q = ( 1.0 - xi ) * crackP1 + xi * crackP2;
                    dist2 = point.distance_square(q);
                }
            } else {
                // If the points P1 and P2 coincide,
                // we can compute the distance to any
                // of these points.
                dist2 = point.distance_square(crackP1);
            }
        } else {
            double arcPos = -1.0, dummy;
            dist2 = point.distance_square(crackP1, crackP2, arcPos, dummy);
        }

        if ( dist2 < oDist*oDist ) {
            FloatArray lineToP;
            lineToP.beDifferenceOf(point, crackP1, dim);

            FloatArray t;
            t.beDifferenceOf(crackP2, crackP1, dim);

            FloatArray n = {-t.at(2), t.at(1)};

            oDist = sgn( lineToP.dotProduct(n) ) * sqrt(dist2);
        }
    }
}
示例#20
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
        }
    }
}
示例#21
0
void AbaqusUserMaterial :: giveRealStressVector(FloatArray &answer, MatResponseForm form, GaussPoint *gp,
                                                const FloatArray &reducedStrain, TimeStep *tStep)
{
    AbaqusUserMaterialStatus *ms = static_cast< AbaqusUserMaterialStatus * >( this->giveStatus(gp) );
    /* User-defined material name, left justified. Some internal material models are given names starting with
     * the “ABQ_” character string. To avoid conflict, you should not use “ABQ_” as the leading string for
     * CMNAME. */
    //char cmname[80];

    MaterialMode mMode = gp->giveMaterialMode();
    // Sizes of the tensors.
    int ndi;
    int nshr;
    ///@todo Check how to deal with large deformations.
    ///@todo Check order of entries in the Voigt notation (which order does Abaqus use? convert to that).
    if ( mMode == _3dMat ) {
        ndi = 3;
        nshr = 3;
    } else if ( mMode == _PlaneStress ) {
        ndi = 2;
        nshr = 1;
    } else if ( mMode == _PlaneStrain ) {
        ndi = 3;
        nshr = 1;
    } /*else if ( mMode == _3dMat_F ) {
       * ndi = 3;
       * nshr = 6;
       * } */
    else if ( mMode == _1dMat ) {
        ndi = 1;
        nshr = 0;
    } else {
        ndi = nshr = 0;
        OOFEM_ERROR2( "AbaqusUserMaterial :: giveRealStressVector : unsupported material mode (%s)", __MaterialModeToString(mMode) );
    }

    int ntens = ndi + nshr;
    FloatArray stress(ntens);
    FloatArray strain = ms->giveStrainVector();
    FloatArray strainIncrement;
    strainIncrement.beDifferenceOf(reducedStrain, strain);
    FloatArray state = ms->giveStateVector();
    FloatMatrix jacobian(ntens, ntens);
    int numProperties = this->properties.giveSize();

    // Temperature and increment
    double temp = 0.0, dtemp = 0.0;

    // Times and increment
    double dtime = tStep->giveTimeIncrement();
    ///@todo Check this. I'm just guessing. Maybe intrinsic time instead?
    double time [ 2 ] = {
        tStep->giveTargetTime() - dtime, tStep->giveTargetTime()
    };
    double pnewdt = 1.0; ///@todo Right default value? umat routines may change this (although we ignore it)

    /* Specific elastic strain energy, plastic dissipation, and “creep” dissipation, respectively. These are passed
     * in as the values at the start of the increment and should be updated to the corresponding specific energy
     * values at the end of the increment. They have no effect on the solution, except that they are used for
     * energy output. */
    double sse, spd, scd;

    // Outputs only in a fully coupled thermal-stress analysis:
    double rpl = 0.0; // Volumetric heat generation per unit time at the end of the increment caused by mechanical working of the material.
    FloatArray ddsddt(ntens); // Variation of the stress increments with respect to the temperature.
    FloatArray drplde(ntens); // Variation of RPL with respect to the strain increments.
    double drpldt = 0.0; // Variation of RPL with respect to the temperature.

    /* An array containing the coordinates of this point. These are the current coordinates if geometric
     * nonlinearity is accounted for during the step (see “Procedures: overview,” Section 6.1.1); otherwise,
     * the array contains the original coordinates of the point */
    FloatArray coords;
    gp->giveElement()->computeGlobalCoordinates( coords, * gp->giveCoordinates() ); ///@todo Large deformations?

    /* Rotation increment matrix. This matrix represents the increment of rigid body rotation of the basis
     * system in which the components of stress (STRESS) and strain (STRAN) are stored. It is provided so
     * that vector- or tensor-valued state variables can be rotated appropriately in this subroutine: stress and
     * strain components are already rotated by this amount before UMAT is called. This matrix is passed in
     * as a unit matrix for small-displacement analysis and for large-displacement analysis if the basis system
     * for the material point rotates with the material (as in a shell element or when a local orientation is used).*/
    FloatMatrix drot(3, 3);
    drot.beUnitMatrix();

    /* Characteristic element length, which is a typical length of a line across an element for a first-order
     * element; it is half of the same typical length for a second-order element. For beams and trusses it is a
     * characteristic length along the element axis. For membranes and shells it is a characteristic length in
     * the reference surface. For axisymmetric elements it is a characteristic length in the
     * plane only.
     * For cohesive elements it is equal to the constitutive thickness.*/
    double celent = 0.0; /// @todo Include the characteristic element length

    /* Array containing the deformation gradient at the beginning of the increment. See the discussion
     * regarding the availability of the deformation gradient for various element types. */
    FloatMatrix dfgrd0(3, 3);
    /* Array containing the deformation gradient at the end of the increment. The components of this array
     * are set to zero if nonlinear geometric effects are not included in the step definition associated with
     * this increment. See the discussion regarding the availability of the deformation gradient for various
     * element types. */
    FloatMatrix dfgrd1(3, 3);

    int noel = gp->giveElement()->giveNumber(); // Element number.
    int npt = 0; // Integration point number.

    int layer = 0; // Layer number (for composite shells and layered solids)..
    int kspt = 0.0; // Section point number within the current layer.
    int kstep = 0; // Step number.
    int kinc = 0; // Increment number.

    ///@todo No idea about these parameters
    double predef;
    double dpred;

    OOFEM_LOG_DEBUG("AbaqusUserMaterial :: giveRealStressVector - Calling subroutine");
    this->umat(stress.givePointer(), // STRESS
               state.givePointer(), // STATEV
               jacobian.givePointer(), // DDSDDE
               & sse, // SSE
               & spd, // SPD
               & scd, // SCD
               & rpl, // RPL
               ddsddt.givePointer(), // DDSDDT
               drplde.givePointer(), // DRPLDE
               & drpldt, // DRPLDT
               strain.givePointer(), // STRAN
               strainIncrement.givePointer(), // DSTRAN
               time, // TIME
               & dtime, // DTIME
               & temp, // TEMP
               & dtemp, // DTEMP
               & predef, // PREDEF
               & dpred, // DPRED
               this->cmname, // CMNAME
               & ndi, // NDI
               & nshr, // NSHR
               & ntens, // NTENS
               & numState, // NSTATV
               properties.givePointer(), // PROPS
               & numProperties, // NPROPS
               coords.givePointer(), // COORDS
               drot.givePointer(), // DROT
               & pnewdt, // PNEWDT
               & celent, // CELENT
               dfgrd0.givePointer(), // DFGRD0
               dfgrd1.givePointer(), // DFGRD1
               & noel, // NOEL
               & npt, // NPT
               & layer, // LAYER
               & kspt, // KSPT
               & kstep, // KSTEP
               & kinc); // KINC

    ms->letTempStrainVectorBe(reducedStrain);
    ms->letTempStressVectorBe(stress);
    ms->letTempStateVectorBe(state);
    ms->letTempTangentBe(jacobian);
    answer = stress;

    OOFEM_LOG_DEBUG("AbaqusUserMaterial :: giveRealStressVector - Calling subroutine was successful");
}
示例#22
0
void AbaqusUserMaterial :: giveFirstPKStressVector_3d(FloatArray &answer, GaussPoint *gp,
                                                      const FloatArray &vF, TimeStep *tStep)
{
    AbaqusUserMaterialStatus *ms = static_cast< AbaqusUserMaterialStatus * >( this->giveStatus(gp) );
    /* User-defined material name, left justified. Some internal material models are given names starting with
     * the “ABQ_” character string. To avoid conflict, you should not use “ABQ_” as the leading string for
     * CMNAME. */
    //char cmname[80];

    // Sizes of the tensors.
    int ndi = 3;
    int nshr = 3;

    int ntens = ndi + nshr;
    FloatArray stress(9); // PK1
    FloatArray strainIncrement;

    // compute Green-Lagrange strain
    FloatArray strain;
    FloatArray vS;
    FloatMatrix F, E;
    F.beMatrixForm(vF);
    E.beTProductOf(F, F);
    E.at(1, 1) -= 1.0;
    E.at(2, 2) -= 1.0;
    E.at(3, 3) -= 1.0;
    E.times(0.5);
    strain.beSymVectorFormOfStrain(E);

    strainIncrement.beDifferenceOf(strain, ms->giveStrainVector());
    FloatArray state = ms->giveStateVector();
    FloatMatrix jacobian(9, 9); // dPdF
    int numProperties = this->properties.giveSize();

    // Temperature and increment
    double temp = 0.0, dtemp = 0.0;

    // Times and increment
    double dtime = tStep->giveTimeIncrement();
    ///@todo Check this. I'm just guessing. Maybe intrinsic time instead?
    double time [ 2 ] = {
        tStep->giveTargetTime() - dtime, tStep->giveTargetTime()
    };
    double pnewdt = 1.0; ///@todo Right default value? umat routines may change this (although we ignore it)

    /* Specific elastic strain energy, plastic dissipation, and “creep” dissipation, respectively. These are passed
     * in as the values at the start of the increment and should be updated to the corresponding specific energy
     * values at the end of the increment. They have no effect on the solution, except that they are used for
     * energy output. */
    double sse, spd, scd;

    // Outputs only in a fully coupled thermal-stress analysis:
    double rpl = 0.0; // Volumetric heat generation per unit time at the end of the increment caused by mechanical working of the material.
    FloatArray ddsddt(ntens); // Variation of the stress increments with respect to the temperature.
    FloatArray drplde(ntens); // Variation of RPL with respect to the strain increments.
    double drpldt = 0.0; // Variation of RPL with respect to the temperature.

    /* An array containing the coordinates of this point. These are the current coordinates if geometric
     * nonlinearity is accounted for during the step (see “Procedures: overview,” Section 6.1.1); otherwise,
     * the array contains the original coordinates of the point */
    FloatArray coords;
    gp->giveElement()->computeGlobalCoordinates( coords, gp->giveNaturalCoordinates() ); ///@todo Large deformations?

    /* Rotation increment matrix. This matrix represents the increment of rigid body rotation of the basis
     * system in which the components of stress (STRESS) and strain (STRAN) are stored. It is provided so
     * that vector- or tensor-valued state variables can be rotated appropriately in this subroutine: stress and
     * strain components are already rotated by this amount before UMAT is called. This matrix is passed in
     * as a unit matrix for small-displacement analysis and for large-displacement analysis if the basis system
     * for the material point rotates with the material (as in a shell element or when a local orientation is used).*/
    FloatMatrix drot(3, 3);
    drot.beUnitMatrix();

    /* Characteristic element length, which is a typical length of a line across an element for a first-order
     * element; it is half of the same typical length for a second-order element. For beams and trusses it is a
     * characteristic length along the element axis. For membranes and shells it is a characteristic length in
     * the reference surface. For axisymmetric elements it is a characteristic length in the
     * plane only.
     * For cohesive elements it is equal to the constitutive thickness.*/
    double celent = 0.0; /// @todo Include the characteristic element length

    /* Array containing the deformation gradient at the beginning of the increment. See the discussion
     * regarding the availability of the deformation gradient for various element types. */
    FloatMatrix dfgrd0(3, 3);
    /* Array containing the deformation gradient at the end of the increment. The components of this array
     * are set to zero if nonlinear geometric effects are not included in the step definition associated with
     * this increment. See the discussion regarding the availability of the deformation gradient for various
     * element types. */
    FloatMatrix dfgrd1(3, 3);

    dfgrd0.beMatrixForm( ms->giveFVector() );
    dfgrd1.beMatrixForm(vF);

    int noel = gp->giveElement()->giveNumber(); // Element number.
    int npt = 0; // Integration point number.

    // We intentionally ignore the layer number since that is handled by the layered cross-section in OOFEM.
    int layer = 0; // Layer number (for composite shells and layered solids)..
    int kspt = 0; // Section point number within the current layer.
    int kstep = tStep->giveMetaStepNumber(); // Step number.
    int kinc = 0; // Increment number.

    ///@todo No idea about these parameters
    double predef;
    double dpred;

    // Change to Abaqus's component order
    stress.changeComponentOrder();
    strain.changeComponentOrder();
    strainIncrement.changeComponentOrder();

    OOFEM_LOG_DEBUG("AbaqusUserMaterial :: giveRealStressVector - Calling subroutine");
    this->umat(stress.givePointer(), // STRESS
               state.givePointer(), // STATEV
               jacobian.givePointer(), // DDSDDE
               & sse, // SSE
               & spd, // SPD
               & scd, // SCD
               & rpl, // RPL
               ddsddt.givePointer(), // DDSDDT
               drplde.givePointer(), // DRPLDE
               & drpldt, // DRPLDT
               strain.givePointer(), // STRAN
               strainIncrement.givePointer(), // DSTRAN
               time, // TIME
               & dtime, // DTIME
               & temp, // TEMP
               & dtemp, // DTEMP
               & predef, // PREDEF
               & dpred, // DPRED
               this->cmname, // CMNAME
               & ndi, // NDI
               & nshr, // NSHR
               & ntens, // NTENS
               & numState, // NSTATV
               properties.givePointer(), // PROPS
               & numProperties, // NPROPS
               coords.givePointer(), // COORDS
               drot.givePointer(), // DROT
               & pnewdt, // PNEWDT
               & celent, // CELENT
               dfgrd0.givePointer(), // DFGRD0
               dfgrd1.givePointer(), // DFGRD1
               & noel, // NOEL
               & npt, // NPT
               & layer, // LAYER
               & kspt, // KSPT
               & kstep, // KSTEP
               & kinc); // KINC


    // Change to OOFEM's component order
    stress.changeComponentOrder();
    strain.changeComponentOrder();
    strainIncrement.changeComponentOrder();
    jacobian.changeComponentOrder();


    if ( mStressInterpretation == 0 ) {
        FloatMatrix P, cauchyStress;
        P.beMatrixForm(stress);

        FloatArray vP;
        vP.beVectorForm(P);

        cauchyStress.beProductTOf(P, F);
        cauchyStress.times( 1.0 / F.giveDeterminant() );

        FloatArray vCauchyStress;
        vCauchyStress.beSymVectorForm(cauchyStress);

        ms->letTempStrainVectorBe(strain);
        ms->letTempStressVectorBe(vCauchyStress);
        ms->letTempStateVectorBe(state);
        ms->letTempTangentBe(jacobian);
        ms->letTempPVectorBe(vP);
        ms->letTempFVectorBe(vF);

        answer = vP;
    } else   {
        FloatArray vP;
        FloatMatrix P, sigma, F_inv;
        F_inv.beInverseOf(F);

        sigma.beMatrixForm(stress);
        P.beProductOf(F, sigma);
        vP.beVectorForm(P);
        answer = vP;

        // Convert from sigma to S
        FloatMatrix S;
        S.beProductOf(F_inv, P);
        vS.beSymVectorForm(S);

        // @todo Should convert from dsigmadE to dSdE here
        // L2=detF*matmul( matmul ( inv(op_a_V9(F,F), cm-op_a_V9(ident,Tau)-op_b_V9(Tau,ident) ), inv(op_a_V9(Ft,Ft)))

        ms->letTempStrainVectorBe(strain);
        ms->letTempStressVectorBe(vS);
        ms->letTempStateVectorBe(state);
        ms->letTempTangentBe(jacobian);
        ms->letTempPVectorBe(vP);
        ms->letTempFVectorBe(vF);
    }

    OOFEM_LOG_DEBUG("AbaqusUserMaterial :: giveRealStressVector_3d - Calling subroutine was successful");
}
示例#23
0
void Line :: computeProjection(FloatArray &answer)
{
    answer.beDifferenceOf(mVertices [ 1 ], mVertices [ 0 ]);
}
bool XfemStructuralElementInterface :: XfemElementInterface_updateIntegrationRule()
{
    const double tol2 = 1.0e-18;

    bool partitionSucceeded = false;


    if ( mpCZMat != NULL ) {
        mpCZIntegrationRules.clear();
        mCZEnrItemIndices.clear();
        mCZTouchingEnrItemIndices.clear();
    }

    XfemManager *xMan = this->element->giveDomain()->giveXfemManager();
    if ( xMan->isElementEnriched(element) ) {
        if ( mpCZMat == NULL && mCZMaterialNum > 0 ) {
            initializeCZMaterial();
        }


        MaterialMode matMode = element->giveMaterialMode();

        bool firstIntersection = true;

        std :: vector< std :: vector< FloatArray > >pointPartitions;
        mSubTri.clear();

        std :: vector< int >enrichingEIs;
        int elPlaceInArray = xMan->giveDomain()->giveElementPlaceInArray( element->giveGlobalNumber() );
        xMan->giveElementEnrichmentItemIndices(enrichingEIs, elPlaceInArray);


        for ( size_t p = 0; p < enrichingEIs.size(); p++ ) {
            // Index of current ei
            int eiIndex = enrichingEIs [ p ];

            // Indices of other ei interaction with this ei through intersection enrichment fronts.
            std :: vector< int >touchingEiIndices;
            giveIntersectionsTouchingCrack(touchingEiIndices, enrichingEIs, eiIndex, * xMan);

            if ( firstIntersection ) {
                // Get the points describing each subdivision of the element
                double startXi, endXi;
                bool intersection = false;
                this->XfemElementInterface_prepareNodesForDelaunay(pointPartitions, startXi, endXi, eiIndex, intersection);

                if ( intersection ) {
                    firstIntersection = false;

                    // Use XfemElementInterface_partitionElement to subdivide the element
                    for ( int i = 0; i < int ( pointPartitions.size() ); i++ ) {
                        // Triangulate the subdivisions
                        this->XfemElementInterface_partitionElement(mSubTri, pointPartitions [ i ]);
                    }


                    if ( mpCZMat != NULL ) {
                        Crack *crack = dynamic_cast< Crack * >( xMan->giveEnrichmentItem(eiIndex) );
                        if ( crack == NULL ) {
                            OOFEM_ERROR("Cohesive zones are only available for cracks.")
                        }

                        // We have xi_s and xi_e. Fetch sub polygon.
                        std :: vector< FloatArray >crackPolygon;
                        crack->giveSubPolygon(crackPolygon, startXi, endXi);

                        ///////////////////////////////////
                        // Add cohesive zone Gauss points
                        size_t numSeg = crackPolygon.size() - 1;

                        for ( size_t segIndex = 0; segIndex < numSeg; segIndex++ ) {
                            int czRuleNum = 1;
                            mpCZIntegrationRules.emplace_back( new GaussIntegrationRule(czRuleNum, element) );

                            // Add index of current ei
                            mCZEnrItemIndices.push_back(eiIndex);

                            // Add indices of other ei, that cause interaction through
                            // intersection enrichment fronts
                            mCZTouchingEnrItemIndices.push_back(touchingEiIndices);

                            // Compute crack normal
                            FloatArray crackTang;
                            crackTang.beDifferenceOf(crackPolygon [ segIndex + 1 ], crackPolygon [ segIndex ]);

                            if ( crackTang.computeSquaredNorm() > tol2 ) {
                                crackTang.normalize();
                            }

                            FloatArray crackNormal = {
                                -crackTang.at(2), crackTang.at(1)
                            };

                            mpCZIntegrationRules [ segIndex ]->SetUpPointsOn2DEmbeddedLine(mCSNumGaussPoints, matMode,
                                                                                           crackPolygon [ segIndex ], crackPolygon [ segIndex + 1 ]);

                            for ( GaussPoint *gp: *mpCZIntegrationRules [ segIndex ] ) {
                                double gw = gp->giveWeight();
                                double segLength = crackPolygon [ segIndex ].distance(crackPolygon [ segIndex + 1 ]);
                                gw *= 0.5 * segLength;
                                gp->setWeight(gw);

                                // Fetch material status and set normal
                                StructuralInterfaceMaterialStatus *ms = dynamic_cast< StructuralInterfaceMaterialStatus * >( mpCZMat->giveStatus(gp) );
                                if ( ms == NULL ) {
                                    OOFEM_ERROR("Failed to fetch material status.");
                                }

                                ms->letNormalBe(crackNormal);

                                // Give Gauss point reference to the enrichment item
                                // to simplify post processing.
                                crack->AppendCohesiveZoneGaussPoint(gp);
                            }
                        }
                    }



                    partitionSucceeded = true;
                }
            } // if(firstIntersection)
            else {
                // Loop over triangles
                std :: vector< Triangle >allTriCopy;
                for ( size_t triIndex = 0; triIndex < mSubTri.size(); triIndex++ ) {
                    // Call alternative version of XfemElementInterface_prepareNodesForDelaunay
                    std :: vector< std :: vector< FloatArray > >pointPartitionsTri;
                    double startXi, endXi;
                    bool intersection = false;
                    XfemElementInterface_prepareNodesForDelaunay(pointPartitionsTri, startXi, endXi, mSubTri [ triIndex ], eiIndex, intersection);

                    if ( intersection ) {
                        // Use XfemElementInterface_partitionElement to subdivide triangle j
                        for ( int i = 0; i < int ( pointPartitionsTri.size() ); i++ ) {
                            this->XfemElementInterface_partitionElement(allTriCopy, pointPartitionsTri [ i ]);
                        }


                        // Add cohesive zone Gauss points

                        if ( mpCZMat != NULL ) {
                            Crack *crack = dynamic_cast< Crack * >( xMan->giveEnrichmentItem(eiIndex) );
                            if ( crack == NULL ) {
                                OOFEM_ERROR("Cohesive zones are only available for cracks.")
                            }

                            // We have xi_s and xi_e. Fetch sub polygon.
                            std :: vector< FloatArray >crackPolygon;
                            crack->giveSubPolygon(crackPolygon, startXi, endXi);

                            int numSeg = crackPolygon.size() - 1;

                            for ( int segIndex = 0; segIndex < numSeg; segIndex++ ) {
                                int czRuleNum = 1;
                                mpCZIntegrationRules.emplace_back( new GaussIntegrationRule(czRuleNum, element) );
                                size_t newRuleInd = mpCZIntegrationRules.size() - 1;
                                mCZEnrItemIndices.push_back(eiIndex);

                                mCZTouchingEnrItemIndices.push_back(touchingEiIndices);

                                // Compute crack normal
                                FloatArray crackTang;
                                crackTang.beDifferenceOf(crackPolygon [ segIndex + 1 ], crackPolygon [ segIndex ]);

                                if ( crackTang.computeSquaredNorm() > tol2 ) {
                                    crackTang.normalize();
                                }

                                FloatArray crackNormal = {
                                    -crackTang.at(2), crackTang.at(1)
                                };

                                mpCZIntegrationRules [ newRuleInd ]->SetUpPointsOn2DEmbeddedLine(mCSNumGaussPoints, matMode,
                                                                                                 crackPolygon [ segIndex ], crackPolygon [ segIndex + 1 ]);

                                for ( GaussPoint *gp: *mpCZIntegrationRules [ newRuleInd ] ) {
                                    double gw = gp->giveWeight();
                                    double segLength = crackPolygon [ segIndex ].distance(crackPolygon [ segIndex + 1 ]);
                                    gw *= 0.5 * segLength;
                                    gp->setWeight(gw);

                                    // Fetch material status and set normal
                                    StructuralInterfaceMaterialStatus *ms = dynamic_cast< StructuralInterfaceMaterialStatus * >( mpCZMat->giveStatus(gp) );
                                    if ( ms == NULL ) {
                                        OOFEM_ERROR("Failed to fetch material status.");
                                    }

                                    ms->letNormalBe(crackNormal);

                                    // Give Gauss point reference to the enrichment item
                                    // to simplify post processing.
                                    crack->AppendCohesiveZoneGaussPoint(gp);
                                }
                            }
                        }
                    } else {
                        allTriCopy.push_back(mSubTri [ triIndex ]);
                    }
                }
示例#25
0
double BasicGeometry :: computeLineDistance(const FloatArray &iP1, const FloatArray &iP2, const FloatArray &iQ1, const FloatArray &iQ2)
{
    FloatArray u;
    u.beDifferenceOf(iP2, iP1);

    const double LengthP = u.computeNorm();

    FloatArray v;
    v.beDifferenceOf(iQ2, iQ1);
    const double LengthQ = v.computeNorm();


    // Regularization coefficients (to make it possible to solve when lines are parallel)
    const double c1 = (1.0e-14)*LengthP*LengthP;
    const double c2 = (1.0e-14)*LengthQ*LengthQ;

    const size_t minIter = 2;
    const size_t maxIter = 5;
    const double absTol = 1.0e-12;

    double xi = 0.0, eta = 0.0;

    FloatArray d;
    d = iP1;
    d.add(xi,u);
    d.add(-1.0, iQ1);
    d.add(-eta, v);

    FloatMatrix K(2,2), KInv;
    FloatArray dXi;

    bool lockXi = false, lockEta = false;

    for(size_t iter = 0; iter < maxIter; iter++) {

        if(xi < 0.0) {
            xi = 0.0;
            lockXi = true;
        }

        if(xi > 1.0) {
            xi = 1.0;
            lockXi = true;
        }


        if(eta < 0.0) {
            eta = 0.0;
            lockEta = true;
        }

        if(eta > 1.0) {
            eta = 1.0;
            lockEta = true;
        }

        FloatArray R = {   d.dotProduct(u) + c1*xi,
                          -d.dotProduct(v) + c2*eta};

        if(lockXi) {
            R[0] = 0.0;
        }

        if(lockEta) {
            R[1] = 0.0;
        }

        const double res = R.computeNorm();
//        printf("iter: %lu res: %e\n", iter, res);

        if(res < absTol && iter >= minIter) {
//            printf("xi: %e eta: %e\n", xi, eta);
            break;
        }

        K(0,0) = -u.dotProduct(u)-c1;
        K(0,1) =  u.dotProduct(v);
        K(1,0) =  u.dotProduct(v);
        K(1,1) = -v.dotProduct(v)-c2;


        if(lockXi) {
            K(0,0) = -1.0;
            K(0,1) = K(1,0) = 0.0;
        }

        if(lockEta) {
            K(0,1) = K(1,0) = 0.0;
            K(1,1) = -1.0;
        }


        KInv.beInverseOf(K);

        dXi.beProductOf(KInv, R);

        xi  += dXi[0];
        eta += dXi[1];

        d = iP1;
        d.add(xi,u);
        d.add(-1.0, iQ1);
        d.add(-eta, v);
    }

    if(xi < 0.0) {
        xi = 0.0;
    }

    if(xi > 1.0) {
        xi = 1.0;
    }

    if(eta < 0.0) {
        eta = 0.0;
    }

    if(eta > 1.0) {
        eta = 1.0;
    }

    d = iP1;
    d.add(xi,u);
    d.add(-1.0, iQ1);
    d.add(-eta, v);

    const double dist = d.computeNorm();

    return dist;
}