void PerfectlyPlasticMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &totalStrain, TimeStep *tStep) // // 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, tStep, VM_Total); reducedStrainIncrement.beDifferenceOf( reducedStrain, status->giveStrainVector() ); StructuralMaterial :: giveFullSymVectorForm( strainIncrement, reducedStrainIncrement, gp->giveMaterialMode() ); plasticStrainVector = status->givePlasticStrainVector(); 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, tStep); // // 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, tStep, 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() ); }
void PerfectlyPlasticMaterial :: computePlasticStiffnessAt(FloatMatrix &answer, GaussPoint *gp, FloatArray *currentStressVector, FloatArray *currentPlasticStrainVector, FloatArray *strainIncrement3d, TimeStep *tStep, 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; // // 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, tStep); 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 ( int 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 ( int i = 1; i <= 6; i++ ) { nominator += yeldStressGrad->at(i) * help.at(i); } lambda = nominator / denominator; } delete yeldStressGrad; }