Example #1
0
bool
RerShell :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coords)
{
    //set size of return value to 3 area coordinates
    answer.resize(3);

    //rotate the input point Coordinate System into the element CS
    FloatArray inputCoords_ElCS;
    this->giveLocalCoordinates( inputCoords_ElCS, const_cast< FloatArray & >(coords) );

    //Nodes are defined in the global CS, so they also need to be rotated into the element CS, therefore get the node points and
    //rotate them into the element CS
    FloatArray nodeCoords;
    double x1, x2, x3, y1, y2, y3, z1, z2, z3;

    this->giveLocalCoordinates( nodeCoords, * ( this->giveNode(1)->giveCoordinates() ) );
    x1 = nodeCoords.at(1);
    y1 = nodeCoords.at(2);
    z1 = nodeCoords.at(3);

    this->giveLocalCoordinates( nodeCoords, * ( this->giveNode(2)->giveCoordinates() ) );
    x2 = nodeCoords.at(1);
    y2 = nodeCoords.at(2);
    z2 = nodeCoords.at(3);

    this->giveLocalCoordinates( nodeCoords, * ( this->giveNode(3)->giveCoordinates() ) );
    x3 = nodeCoords.at(1);
    y3 = nodeCoords.at(2);
    z3 = nodeCoords.at(3);

    //Compute the area coordinates corresponding to this point
    double area;
    area = 0.5 * ( x2 * y3 + x1 * y2 + y1 * x3 - x2 * y1 - x3 * y2 - x1 * y3 );

    answer.at(1) = ( ( x2 * y3 - x3 * y2 ) + ( y2 - y3 ) * inputCoords_ElCS.at(1) + ( x3 - x2 ) * inputCoords_ElCS.at(2) ) / 2. / area;
    answer.at(2) = ( ( x3 * y1 - x1 * y3 ) + ( y3 - y1 ) * inputCoords_ElCS.at(1) + ( x1 - x3 ) * inputCoords_ElCS.at(2) ) / 2. / area;
    answer.at(3) = ( ( x1 * y2 - x2 * y1 ) + ( y1 - y2 ) * inputCoords_ElCS.at(1) + ( x2 - x1 ) * inputCoords_ElCS.at(2) ) / 2. / area;

    //get midplane location at this point
    double midplZ;
    midplZ = z1 * answer.at(1) + z2 *answer.at(2) + z3 *answer.at(3);

    //check that the z is within the element
    StructuralCrossSection *cs = this->giveStructuralCrossSection();
    GaussPoint _gp(NULL, 1, new FloatArray ( answer ), 1.0, _2dPlate);

    double elthick;

    elthick = cs->give(CS_Thickness, & _gp);

    if ( elthick / 2.0 + midplZ - fabs( inputCoords_ElCS.at(3) ) < -POINT_TOL ) {
        answer.zero();
        return false;
    }

    //check that the point is in the element and set flag
    for ( int i = 1; i <= 3; i++ ) {
        if ( answer.at(i) < ( 0. - POINT_TOL ) ) {
            return false;
        }

        if ( answer.at(i) > ( 1. + POINT_TOL ) ) {
            return false;
        }
    }

    return true;
}
void
PerfectlyPlasticMaterial :: giveRealStressVector(FloatArray &answer,
                                                 GaussPoint *gp,
                                                 const FloatArray &totalStrain,
                                                 TimeStep *atTime)
//
// returns  stress vector (in full or reduced form )  of receiver according to
// previous level of stress and current
// strain increment, the only way, how to correctly update gp records
//
//
// may be good idea for nonlinear materials overload this function in order to
// capture strain - stress history for proper modelling receiver behaviour
// and in order to capture possible failure of material
//
// Note: formulated in full stress strain space
{
    FloatArray elasticStressIncrement;
    FloatArray workStress, *yieldStressGrad, workStress2, stressVector3d;
    FloatArray mStrainIncrement3d, mStressElasticIncrement3d, PlasticStrainVector3d;
    FloatArray dSigmaIncrement3d, *stressCorrection, *loadingStressGrad;
    FloatArray helpArray;
    FloatArray plasticStrainIncrement3d, strainIncrement, reducedStrain, reducedStrainIncrement;
    FloatArray statusFullStressVector, statusFullPlasticVector;
    FloatArray plasticStrainVector;
    PerfectlyPlasticMaterialStatus *status = static_cast< PerfectlyPlasticMaterialStatus * >( this->giveStatus(gp) );

    FloatMatrix dp;
    StructuralCrossSection *crossSection = static_cast< StructuralCrossSection * >
                                           ( gp->giveElement()->giveCrossSection() );
    double f0, f1, f2, help, dLambda, r, r1, m;

    // init temp variables (of YC,LC,Material) at the beginning of step
    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(reducedStrain, gp, totalStrain,
                                                atTime, VM_Total);

    reducedStrainIncrement.beDifferenceOf(reducedStrain, status->giveStrainVector());

    StructuralMaterial :: giveFullSymVectorForm(strainIncrement, reducedStrainIncrement, gp->giveMaterialMode());
    status->givePlasticStrainVector(plasticStrainVector);
    StructuralMaterial :: giveFullSymVectorForm(statusFullPlasticVector, plasticStrainVector, gp->giveMaterialMode());
    StructuralMaterial :: giveFullSymVectorForm(statusFullStressVector, status->giveStressVector(), gp->giveMaterialMode());

    //
    // Note : formulated in full stress strain space
    //
    this->computeTrialStressIncrement(elasticStressIncrement, gp, strainIncrement, atTime);
    //
    // calculate deltaSigmaPlastic
    //
    workStress = statusFullStressVector;
    workStress.add(elasticStressIncrement);

    f0 = this->computeYCValueAt(gp, & statusFullStressVector,
                                & statusFullPlasticVector);

    f1 = this->computeYCValueAt(gp, & workStress,
                                & statusFullPlasticVector);

    PlasticStrainVector3d = statusFullPlasticVector;


    if ( f1 >= 0. ) { // loading surface violated by the elastic trial set
        if ( f0 < 0. ) { // previously in elastic area
            // element not yielding - set the print status
            status->setTempYieldFlag(0);
            // compute scaling factor
            r1 = -f0 / ( f1 - f0 ); // linear interpolation in f (Zienkiewicz, 1969)
            yieldStressGrad = this->GiveYCStressGradient(gp, & statusFullStressVector,
                                                         & statusFullPlasticVector);
            crossSection->imposeStressConstrainsOnGradient(gp, yieldStressGrad);

            help = 0.;
            for ( int i = 1; i <= 6; i++ ) {
                help += yieldStressGrad->at(i) * elasticStressIncrement.at(i);
            }

            delete yieldStressGrad;

            workStress2 = elasticStressIncrement;
            workStress2.times(r1);
            workStress2.add(statusFullStressVector);

            f2 = this->computeYCValueAt(gp, & workStress2,
                                        & statusFullPlasticVector);

            if ( fabs(help) > 1.e-6 ) {
                r = r1 - f2 / help; // improved value of r (Nayak & Zienkiewicz, 1972)
            } else {
                r = r1;
            }
        } else { // f0 should be zero
            r  = 0.;
        }

        stressVector3d =  elasticStressIncrement;
        stressVector3d.times(r);
        stressVector3d.add(statusFullStressVector);

        m = STRAIN_STEPS;
        mStrainIncrement3d = strainIncrement;
        mStrainIncrement3d.times( ( 1.0 - r ) / m );
        mStressElasticIncrement3d = elasticStressIncrement;
        mStressElasticIncrement3d.times( ( 1.0 - r ) / m );

        // test if fracture or failure occurs
        this->updateIfFailure(gp, & stressVector3d, & PlasticStrainVector3d);
        // element yielding - set the print status
        status->setTempYieldFlag(1);
        // loop over m-steps
        for ( int i = 1; i <= m; i++ ) {
            //   yieldStressGrad = yieldCriteria->
            //    GiveStressGradient (gp, stressVector3d,
            //            PlasticStrainVector3d,
            //            gp-> giveHardeningParam());

            // compute dLambda and dp
            this->computePlasticStiffnessAt(dp, gp,
                                            & stressVector3d,
                                            & PlasticStrainVector3d,
                                            & mStrainIncrement3d,
                                            atTime,
                                            dLambda);
            if ( dLambda < 0. ) {
                dLambda = 0.;
            }

            dSigmaIncrement3d.beProductOf(dp, mStrainIncrement3d);
            dSigmaIncrement3d.negated();
            dSigmaIncrement3d.add(mStressElasticIncrement3d);
            // compute normal to loading surface
            loadingStressGrad = this->GiveLCStressGradient(gp, & stressVector3d,
                                                           & PlasticStrainVector3d);

            // update the stress state
            stressVector3d.add(dSigmaIncrement3d);
            // compute stress corrections

            stressCorrection = this->
                               GiveStressCorrectionBackToYieldSurface(gp, & stressVector3d,
                                                                      & PlasticStrainVector3d);
            // apply the stress correction -> correction is in the direction of
            // the normal to the yield surface
            stressVector3d.add(* stressCorrection);
            //   test = yieldCriteria-> computeValueAt(stressVector3d,
            //                 PlasticStrainVector3d,
            //                 gp-> giveHardeningParam());

            // calculate plastic strain increment

            crossSection->imposeStrainConstrainsOnGradient(gp, loadingStressGrad);
            loadingStressGrad->times(dLambda);
            PlasticStrainVector3d.add(* loadingStressGrad);
            // strainVector3d -> add (mStrainIncrement3d);

            // update yieldCriteria and loading criteria records to newly reached state
            // in loadingStressGrad is stored current plastic vector increment
            this->updateTempYC(gp, & stressVector3d, & PlasticStrainVector3d);
            this->updateTempLC(gp, & stressVector3d, & PlasticStrainVector3d);

            // test if fracture or failure occurs
            this->updateIfFailure(gp, & stressVector3d, & PlasticStrainVector3d);

            delete loadingStressGrad;
            delete stressCorrection;
        }

        // compute total stress increment during strainIncrement
        //  totalStressIncrement = statusFullStressVector;
        //  totalStressIncrement.times (-1.0);
        //  totalStressIncrement.add (stressVector3d);
        // update gp
        FloatArray helpArry;
        StructuralMaterial :: giveReducedSymVectorForm(helpArry, stressVector3d, gp->giveMaterialMode());

        status->letTempStressVectorBe(helpArry);
        status->letTempStrainVectorBe(totalStrain);
    } else {
        // element not yielding - set the print status
        status->setTempYieldFlag(0);
        stressVector3d = statusFullStressVector;
        stressVector3d.add(elasticStressIncrement);
        // test if fracture or failure occurs
        this->updateIfFailure(gp, & stressVector3d, & PlasticStrainVector3d);
        // update gp
        status->letTempStrainVectorBe(totalStrain);
        StructuralMaterial :: giveReducedSymVectorForm(helpArray, stressVector3d, gp->giveMaterialMode());
        status->letTempStressVectorBe(helpArray);
    }

    // update gp plastic strain
    plasticStrainIncrement3d.beDifferenceOf(PlasticStrainVector3d, statusFullPlasticVector);
    StructuralMaterial :: giveReducedSymVectorForm(helpArray, plasticStrainIncrement3d, gp->giveMaterialMode());
    status->letPlasticStrainIncrementVectorBe(helpArray);

    StructuralMaterial :: giveReducedSymVectorForm(answer, stressVector3d, gp->giveMaterialMode());
}
Example #3
0
void
NLStructuralElement :: computeStiffnessMatrix(FloatMatrix &answer,
                                              MatResponseMode rMode, TimeStep *tStep)
{
    StructuralCrossSection *cs = this->giveStructuralCrossSection();
    bool matStiffSymmFlag = cs->isCharacteristicMtrxSymmetric(rMode);

    answer.clear();

    if ( !this->isActivated(tStep) ) {
        return;
    }

    // Compute matrix from material stiffness (total stiffness for small def.) - B^T * dS/dE * B
    if ( integrationRulesArray.size() == 1 ) {
        FloatMatrix B, D, DB;
        for ( auto &gp : *this->giveDefaultIntegrationRulePtr() ) {

            // Engineering (small strain) stiffness
            if ( nlGeometry == 0 ) {
                this->computeBmatrixAt(gp, B);
                this->computeConstitutiveMatrixAt(D, rMode, gp, tStep);
            } else if ( nlGeometry == 1 ) {
                if ( this->domain->giveEngngModel()->giveFormulation() == AL ) { // Material stiffness dC/de
                    this->computeBmatrixAt(gp, B);
                    /// @todo We probably need overloaded function (like above) here as well.
                    cs->giveStiffnessMatrix_dCde(D, rMode, gp, tStep);
                } else { // Material stiffness dP/dF
                    this->computeBHmatrixAt(gp, B);
                    /// @todo We probably need overloaded function (like above) here as well.
                    cs->giveStiffnessMatrix_dPdF(D, rMode, gp, tStep);
                }
            }

            double dV = this->computeVolumeAround(gp);
            DB.beProductOf(D, B);
            if ( matStiffSymmFlag ) {
                answer.plusProductSymmUpper(B, DB, dV);
            } else {
                answer.plusProductUnsym(B, DB, dV);
            }
        }

        if ( this->domain->giveEngngModel()->giveFormulation() == AL ) {
            FloatMatrix initialStressMatrix;
            this->computeInitialStressMatrix(initialStressMatrix, tStep);
            answer.add(initialStressMatrix);
        }
    } else { /// @todo Verify that it works with large deformations
        if ( this->domain->giveEngngModel()->giveFormulation() == AL ) {
            OOFEM_ERROR("Updated lagrangian not supported yet");
        }

        int iStartIndx, iEndIndx, jStartIndx, jEndIndx;
        FloatMatrix Bi, Bj, D, Dij, DBj;
        for ( int i = 0; i < (int)integrationRulesArray.size(); i++ ) {
            iStartIndx = integrationRulesArray [ i ]->getStartIndexOfLocalStrainWhereApply();
            iEndIndx   = integrationRulesArray [ i ]->getEndIndexOfLocalStrainWhereApply();
            for ( int j = 0; j < (int)integrationRulesArray.size(); j++ ) {
                IntegrationRule *iRule;
                jStartIndx = integrationRulesArray [ j ]->getStartIndexOfLocalStrainWhereApply();
                jEndIndx   = integrationRulesArray [ j ]->getEndIndexOfLocalStrainWhereApply();
                if ( i == j ) {
                    iRule = integrationRulesArray [ i ].get();
                } else if ( integrationRulesArray [ i ]->giveNumberOfIntegrationPoints() < integrationRulesArray [ j ]->giveNumberOfIntegrationPoints() ) {
                    iRule = integrationRulesArray [ i ].get();
                } else {
                    iRule = integrationRulesArray [ j ].get();
                }

                for ( GaussPoint *gp: *iRule ) {

                    // Engineering (small strain) stiffness dSig/dEps
                    if ( nlGeometry == 0 ) {
                        this->computeBmatrixAt(gp, Bi, iStartIndx, iEndIndx);
                        this->computeConstitutiveMatrixAt(D, rMode, gp, tStep);
                    } else if ( nlGeometry == 1 ) {
                        if ( this->domain->giveEngngModel()->giveFormulation() == AL ) { // Material stiffness dC/de
                            this->computeBmatrixAt(gp, Bi);
                            cs->giveStiffnessMatrix_dCde(D, rMode, gp, tStep);
                        } else { // Material stiffness dP/dF
                            this->computeBHmatrixAt(gp, Bi);
                            cs->giveStiffnessMatrix_dPdF(D, rMode, gp, tStep);
                        }
                    }


                    if ( i != j ) {
                        if ( nlGeometry == 0 ) {
                            this->computeBmatrixAt(gp, Bj, jStartIndx, jEndIndx);
                        } else if ( nlGeometry == 1 ) {
                            if ( this->domain->giveEngngModel()->giveFormulation() == AL ) {
                                this->computeBmatrixAt(gp, Bj);
                            } else {
                                this->computeBHmatrixAt(gp, Bj);
                            }
                        }
                    } else {
                        Bj  = Bi;
                    }

                    Dij.beSubMatrixOf(D, iStartIndx, iEndIndx, jStartIndx, jEndIndx);
                    double dV = this->computeVolumeAround(gp);
                    DBj.beProductOf(Dij, Bj);
                    if ( matStiffSymmFlag ) {
                        answer.plusProductSymmUpper(Bi, DBj, dV);
                    } else {
                        answer.plusProductUnsym(Bi, DBj, dV);
                    }
                }
            }
        }
    }

    if ( matStiffSymmFlag ) {
        answer.symmetrized();
    }
}
void
PerfectlyPlasticMaterial :: computePlasticStiffnessAt(FloatMatrix &answer,
                                                      GaussPoint *gp,
                                                      FloatArray *currentStressVector,
                                                      FloatArray *currentPlasticStrainVector,
                                                      FloatArray *strainIncrement3d,
                                                      TimeStep *atTime,
                                                      double &lambda)
//
// Computes full form of  Plastic stiffness Matrix at given state.
// gp is used only and only for setting proper MaterialMode ()
// returns proportionality factor lambda also if strainIncrement3d != NULL
{
    StructuralCrossSection *crossSection = static_cast< StructuralCrossSection * >
                                           ( gp->giveElement()->giveCrossSection() );
    FloatMatrix de, *yeldStressGradMat, *loadingStressGradMat;
    FloatMatrix fsde, gsfsde;
    FloatArray *yeldStressGrad, *loadingStressGrad;
    FloatArray help;
    double denominator, nominator;
    int i;
    //
    // force de to be elastic even if gp in plastic state
    // to do this, a flag in this class exist -> ForceElasticResponce
    // if this flag is set to nonzero, function this::Give3dMaterialStiffnessMatrix
    // will be forced to return only elasticPart of 3dMaterialStiffnessMatrix
    // This function also set the ForceElasticFlagResponce to zero.
    //
    this->giveEffectiveMaterialStiffnessMatrix(de, TangentStiffness, gp, atTime);

    yeldStressGrad = this->GiveYCStressGradient(gp, currentStressVector,
                                                currentPlasticStrainVector);
    crossSection->imposeStressConstrainsOnGradient(gp, yeldStressGrad);
    yeldStressGradMat = new FloatMatrix(yeldStressGrad, 1); // transpose

    loadingStressGrad = this->GiveLCStressGradient(gp, currentStressVector,
                                                   currentPlasticStrainVector);

    crossSection->imposeStrainConstrainsOnGradient(gp, loadingStressGrad);
    loadingStressGradMat = new FloatMatrix(yeldStressGrad);

    help.beProductOf(de, * loadingStressGrad);
    delete loadingStressGrad;

    fsde.beProductOf(* yeldStressGradMat, de);
    delete yeldStressGradMat;
    gsfsde.beProductOf(* loadingStressGradMat, fsde);
    delete loadingStressGradMat;

    denominator = 0.;
    for ( i = 1; i <= 6; i++ ) {
        denominator += yeldStressGrad->at(i) * help.at(i);
    }

    answer.beProductOf(de, gsfsde);

    answer.times( -( 1. / denominator ) );

    if ( strainIncrement3d != NULL ) { // compute proportional factor lambda
        nominator = 0.;
        help.beProductOf(de, * strainIncrement3d);
        for ( i = 1; i <= 6; i++ ) {
            nominator += yeldStressGrad->at(i) * help.at(i);
        }

        lambda = nominator / denominator;
    }

    delete yeldStressGrad;
}