void MisesMatNl :: giveRemoteNonlocalStiffnessContribution(GaussPoint *gp, IntArray &rloc, const UnknownNumberingScheme &s, FloatArray &rcontrib, TimeStep *tStep) { double kappa, tempKappa; MisesMatNlStatus *status = static_cast< MisesMatNlStatus * >( this->giveStatus(gp) ); StructuralElement *elem = static_cast< StructuralElement * >( gp->giveElement() ); FloatMatrix b; LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); double E = lmat->give('E', gp); elem->giveLocationArray(rloc, s); elem->computeBmatrixAt(gp, b); kappa = status->giveCumulativePlasticStrain(); tempKappa = status->giveTempCumulativePlasticStrain(); rcontrib.clear(); if ( ( tempKappa - kappa ) > 0 ) { const FloatArray &stress = status->giveTempEffectiveStress(); if ( gp->giveMaterialMode() == _1dMat ) { double coeff = sgn( stress.at(1) ) * E / ( E + H ); rcontrib.plusProduct(b, stress, coeff); return; } } rcontrib.resize(b.giveNumberOfColumns()); rcontrib.zero(); }
void MisesMatNl :: give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { answer.resize(1, 1); answer.zero(); LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); double E = lmat->give('E', gp); double nlKappa; MisesMatNlStatus *status = static_cast< MisesMatNlStatus * >( this->giveStatus(gp) ); double kappa = status->giveCumulativePlasticStrain(); double tempKappa = status->giveTempCumulativePlasticStrain(); double tempDamage = status->giveTempDamage(); double damage = status->giveDamage(); answer.at(1, 1) = ( 1 - tempDamage ) * E; if ( mode != TangentStiffness ) { return; } if ( tempKappa <= kappa ) { // elastic loading - elastic stiffness plays the role of tangent stiffness return; } // === plastic loading === const FloatArray &stressVector = status->giveTempEffectiveStress(); double stress = stressVector.at(1); answer.at(1, 1) = ( 1. - tempDamage ) * E * H / ( E + H ); if ( tempDamage > damage ) { this->computeCumPlasticStrain(nlKappa, gp, tStep); answer.at(1, 1) = answer.at(1, 1) - ( 1 - mm ) * computeDamageParamPrime(nlKappa) * E / ( E + H ) * stress * sgn(stress); } }
void MisesMat :: giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &totalStrain, TimeStep *tStep) { /// @note: One should obtain the same answer using the iterations in the default implementation (this is verified for this model). #if 1 MisesMatStatus *status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); this->performPlasticityReturn(gp, totalStrain); double omega = computeDamage(gp, tStep); answer = status->giveTempEffectiveStress(); answer.times(1 - omega); // Compute the other components of the strain: LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); double E = lmat->give('E', gp), nu = lmat->give('n', gp); FloatArray strain = status->getTempPlasticStrain(); strain[0] = totalStrain[0]; strain[1] -= nu / E * status->giveTempEffectiveStress()[0]; strain[2] -= nu / E * status->giveTempEffectiveStress()[0]; status->letTempStrainVectorBe(strain); status->setTempDamage(omega); status->letTempStressVectorBe(answer); #else StructuralMaterial :: giveRealStressVector_1d(answer, gp, totalStrain, tStep); #endif }
void IDGMaterial :: give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { IsotropicDamageMaterialStatus *status = static_cast< IsotropicDamageMaterialStatus * >( this->giveStatus(gp) ); LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); double om; om = status->giveTempDamage(); om = min(om, maxOmega); answer.resize(1, 1); answer.at(1, 1) = lmat->give('E', gp); answer.times(1.0 - om); }
void MisesMatGrad :: give1dKappaMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { answer.resize(1, 1); answer.zero(); LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); double E = lmat->give('E', gp); MisesMatGradStatus *status = static_cast< MisesMatGradStatus * >( this->giveStatus(gp) ); double tempKappa = status->giveTempCumulativePlasticStrain(); double dKappa = tempKappa - status->giveCumulativePlasticStrain(); const FloatArray &effStress = status->giveTempEffectiveStress(); double stress = effStress.at(1); if ( dKappa > 0 ) { double trialS = signum(stress); double factor = trialS * E / ( E + H ); answer.at(1, 1) = factor; } }
void IDGMaterial :: give1dGprime(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { IDGMaterialStatus *status = static_cast< IDGMaterialStatus * >( this->giveStatus(gp) ); LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); double damage = status->giveDamage(); double tempDamage = status->giveTempDamage(); double E = lmat->give('E', gp); answer.resize(1, 1); if ( tempDamage > damage ) { double nlKappa = status->giveNonlocalCumulatedStrain(); answer.at(1, 1) = E * status->giveTempStrainVector().at(1); double gPrime = damageFunctionPrime(nlKappa, gp); answer.times(gPrime); } else { answer.zero(); } }
void MisesMatNl :: giveRemoteNonlocalStiffnessContribution(GaussPoint *gp, IntArray &rloc, const UnknownNumberingScheme &s, FloatArray &rcontrib, TimeStep *atTime) { int ncols, nsize, i, j; double sum, kappa, tempKappa; MisesMatNlStatus *status = ( MisesMatNlStatus * ) this->giveStatus(gp); StructuralElement *elem = ( StructuralElement * )( gp->giveElement() ); FloatMatrix b; FloatArray stress; LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); double E = lmat->give('E', gp); elem->giveLocationArray(rloc, EID_MomentumBalance, s); elem->computeBmatrixAt(gp, b); ncols = b.giveNumberOfColumns(); rcontrib.resize(ncols); kappa = status->giveCumulativePlasticStrain(); tempKappa = status->giveTempCumulativePlasticStrain(); if ( ( tempKappa - kappa ) > 0 ) { status->giveTempEffectiveStress(stress); if ( gp->giveMaterialMode() == _1dMat ) { nsize = stress.giveSize(); double coeff = sgn( stress.at(1) ) * E / ( E + H ); for ( i = 1; i <= ncols; i++ ) { sum = 0.; for ( j = 1; j <= nsize; j++ ) { sum += stress.at(j) * coeff * b.at(j, i); } rcontrib.at(i) = sum; } } } else { rcontrib.zero(); } }
void MisesMatGrad :: give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { answer.resize(1, 1); LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); double E = lmat->give('E', gp); answer.at(1, 1) = E; if ( mode != TangentStiffness ) { return; } MisesMatGradStatus *status = static_cast< MisesMatGradStatus * >( this->giveStatus(gp) ); double tempKappa = status->giveTempCumulativePlasticStrain(); // increment of cumulative plastic strain as an indicator of plastic loading double dKappa = ( tempKappa - status->giveCumulativePlasticStrain() ); /********************************************************************/ double tempDamage = status->giveTempDamage(); double damage = status->giveDamage(); /*********************************************************************/ double nlKappa = status->giveNonlocalCumulatedStrain(); double kappa = mParam * nlKappa + ( 1. - mParam ) * tempKappa; if ( dKappa <= 0.0 ) { answer.at(1, 1) = ( 1. - tempDamage ) * E; return; } // === plastic loading === const FloatArray &stressVector = status->giveTempEffectiveStress(); double stress = stressVector.at(1); answer.at(1, 1) = ( 1. - tempDamage ) * E * H / ( E + H ); if ( ( tempDamage - damage ) > 0 ) { answer.at(1, 1) = answer.at(1, 1) - ( 1. - mParam ) * computeDamageParamPrime(kappa) * E / ( E + H ) * signum(stress) * stress; } }
void MisesMat :: performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain) { MisesMatStatus *status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); double kappa; FloatArray plStrain; FloatArray fullStress; // get the initial plastic strain and initial kappa from the status plStrain = status->givePlasticStrain(); kappa = status->giveCumulativePlasticStrain(); // === radial return algorithm === if ( totalStrain.giveSize() == 1 ) { LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); double E = lmat->give('E', gp); /*trial stress*/ fullStress.resize(6); fullStress.at(1) = E * ( totalStrain.at(1) - plStrain.at(1) ); double trialS = fabs(fullStress.at(1)); /*yield function*/ double yieldValue = trialS - (sig0 + H * kappa); // === radial return algorithm === if ( yieldValue > 0 ) { double dKappa = yieldValue / ( H + E ); kappa += dKappa; plStrain.at(1) += dKappa * signum( fullStress.at(1) ); plStrain.at(2) -= 0.5 * dKappa * signum( fullStress.at(1) ); plStrain.at(3) -= 0.5 * dKappa * signum( fullStress.at(1) ); fullStress.at(1) -= dKappa * E * signum( fullStress.at(1) ); } } else { // elastic predictor FloatArray elStrain = totalStrain; elStrain.subtract(plStrain); FloatArray elStrainDev; double elStrainVol; elStrainVol = computeDeviatoricVolumetricSplit(elStrainDev, elStrain); FloatArray trialStressDev; applyDeviatoricElasticStiffness(trialStressDev, elStrainDev, G); /**************************************************************/ double trialStressVol = 3 * K * elStrainVol; /**************************************************************/ // store the deviatoric and trial stress (reused by algorithmic stiffness) status->letTrialStressDevBe(trialStressDev); status->setTrialStressVol(trialStressVol); // check the yield condition at the trial state double trialS = computeStressNorm(trialStressDev); double yieldValue = sqrt(3./2.) * trialS - (sig0 + H * kappa); if ( yieldValue > 0. ) { // increment of cumulative plastic strain double dKappa = yieldValue / ( H + 3. * G ); kappa += dKappa; FloatArray dPlStrain; // the following line is equivalent to multiplication by scaling matrix P applyDeviatoricElasticCompliance(dPlStrain, trialStressDev, 0.5); // increment of plastic strain plStrain.add(sqrt(3. / 2.) * dKappa / trialS, dPlStrain); // scaling of deviatoric trial stress trialStressDev.times(1. - sqrt(6.) * G * dKappa / trialS); } // assemble the stress from the elastically computed volumetric part // and scaled deviatoric part computeDeviatoricVolumetricSum(fullStress, trialStressDev, trialStressVol); } // store the effective stress in status status->letTempEffectiveStressBe(fullStress); // store the plastic strain and cumulative plastic strain status->letTempPlasticStrainBe(plStrain); status->setTempCumulativePlasticStrain(kappa); }
void IDGMaterial :: giveRealStressVectorGrad(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalCumulatedStrain, TimeStep *tStep) // // returns real stress vector in 3d stress space of receiver according to // previous level of stress and current // strain increment, the only way, how to correctly update gp records // { IDGMaterialStatus *status = static_cast< IDGMaterialStatus * >( this->giveStatus(gp) ); LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); FloatArray reducedTotalStrainVector, strain; FloatMatrix de; double f, equivStrain, tempKappa = 0.0, omega = 0.0; this->initTempStatus(gp); // subtract stress independent part // note: eigenStrains (temperature) is not contained in mechanical strain stored in gp // therefore it is necessary to subtract always the total eigen strain value this->giveStressDependentPartOfStrainVector(reducedTotalStrainVector, gp, totalStrain, tStep, VM_Total); // compute equivalent strain this->computeEquivalentStrain(equivStrain, reducedTotalStrainVector, gp, tStep); if ( llcriteria == idm_strainLevelCR ) { // compute value of loading function if strainLevel crit apply f = nonlocalCumulatedStrain - status->giveKappa(); if ( f <= 0.0 ) { // damage does not grow tempKappa = status->giveKappa(); omega = status->giveDamage(); } else { // damage grow this->initDamaged(tempKappa, reducedTotalStrainVector, gp); // evaluate damage parameter this->computeDamageParam(omega, nonlocalCumulatedStrain, reducedTotalStrainVector, gp); } } else if ( llcriteria == idm_damageLevelCR ) { // evaluate damage parameter first tempKappa = nonlocalCumulatedStrain; this->initDamaged(tempKappa, strain, gp); this->computeDamageParam(omega, tempKappa, reducedTotalStrainVector, gp); if ( omega < status->giveDamage() ) { // unloading takes place omega = status->giveDamage(); //printf ("."); } } else { OOFEM_ERROR("unsupported loading/uloading criteria"); } lmat->giveStiffnessMatrix(de, SecantStiffness, gp, tStep); de.times(1.0 - omega); answer1.beProductOf(de, strain); answer2 = equivStrain; // update gp status->letTempStrainVectorBe(totalStrain); status->letTempStressVectorBe(answer1); status->setNonlocalCumulatedStrain(nonlocalCumulatedStrain); status->setTempKappa(tempKappa); status->setTempDamage(omega); }
// returns the stress vector in 3d stress space // computed from the previous plastic strain and current total strain void MisesMat :: performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain) { double kappa, yieldValue, dKappa; FloatArray reducedStress; FloatArray strain, plStrain; MaterialMode mode = gp->giveMaterialMode(); MisesMatStatus *status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); StressVector fullStress(mode); this->initTempStatus(gp); this->initGpForNewStep(gp); // get the initial plastic strain and initial kappa from the status status->givePlasticStrain(plStrain); kappa = status->giveCumulativePlasticStrain(); // === radial return algorithm === if ( mode == _1dMat ) { LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); double E = lmat->give('E', gp); /*trial stress*/ fullStress.at(1) = E * ( totalStrain.at(1) - plStrain.at(1) ); double sigmaY = sig0 + H * kappa; double trialS = fullStress.at(1); trialS = fabs(trialS); /*yield function*/ yieldValue = trialS - sigmaY; // === radial return algorithm === if ( yieldValue > 0 ) { dKappa = yieldValue / ( H + E ); kappa += dKappa; fullStress.at(1) = fullStress.at(1) - dKappa *E *signum( fullStress.at(1) ); plStrain.at(1) = plStrain.at(1) + dKappa *signum( fullStress.at(1) ); } } else if ( ( mode == _PlaneStrain ) || ( mode == _3dMat ) ) { // elastic predictor StrainVector elStrain(totalStrain, mode); elStrain.subtract(plStrain); StrainVector elStrainDev(mode); double elStrainVol; elStrain.computeDeviatoricVolumetricSplit(elStrainDev, elStrainVol); StressVector trialStressDev(mode); elStrainDev.applyDeviatoricElasticStiffness(trialStressDev, G); /**************************************************************/ double trialStressVol; trialStressVol = 3 * K * elStrainVol; /**************************************************************/ // store the deviatoric and trial stress (reused by algorithmic stiffness) status->letTrialStressDevBe(trialStressDev); status->setTrialStressVol(trialStressVol); // check the yield condition at the trial state double trialS = trialStressDev.computeStressNorm(); double sigmaY = sig0 + H * kappa; yieldValue = sqrt(3. / 2.) * trialS - sigmaY; if ( yieldValue > 0. ) { // increment of cumulative plastic strain dKappa = yieldValue / ( H + 3. * G ); kappa += dKappa; StrainVector dPlStrain(mode); // the following line is equivalent to multiplication by scaling matrix P trialStressDev.applyDeviatoricElasticCompliance(dPlStrain, 0.5); // increment of plastic strain dPlStrain.times(sqrt(3. / 2.) * dKappa / trialS); plStrain.add(dPlStrain); // scaling of deviatoric trial stress trialStressDev.times(1. - sqrt(6.) * G * dKappa / trialS); } // assemble the stress from the elastically computed volumetric part // and scaled deviatoric part double stressVol = 3. * K * elStrainVol; trialStressDev.computeDeviatoricVolumetricSum(fullStress, stressVol); } // store the effective stress in status status->letTempEffectiveStressBe(fullStress); // store the plastic strain and cumulative plastic strain status->letTempPlasticStrainBe(plStrain); status->setTempCumulativePlasticStrain(kappa); }