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()); }
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; }