void RCM2Material :: giveEffectiveMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseForm form, MatResponseMode rMode, GaussPoint *gp, TimeStep *atTime) // // returns effective material stiffness matrix in full form // for gp stress strain mode // { RCM2MaterialStatus *status = ( RCM2MaterialStatus * ) this->giveStatus(gp); StructuralMaterial *lMat = static_cast< StructuralMaterial * >( this->giveLinearElasticMaterial() ); int numberOfActiveCracks = status->giveNumberOfTempActiveCracks(); int i, j, indi, indj, ii, jj; double G, princStressDis, princStrainDis; FloatMatrix de, invDe, compliance, dcr, d, df, t, tt, tempCrackDirs; FloatArray principalStressVector, principalStrainVector; IntArray mask; if ( ( rMode == ElasticStiffness ) || ( numberOfActiveCracks == 0 ) ) { lMat->giveCharacteristicMatrix(answer, form, rMode, gp, atTime); return; } // this->updateActiveCrackMap(gp) must be done after restart. this->updateActiveCrackMap(gp); status->giveTempCrackDirs(tempCrackDirs); this->giveNormalElasticStiffnessMatrix(de, ReducedForm, rMode, gp, atTime, tempCrackDirs); invDe.beInverseOf(de); this->giveCrackedStiffnessMatrix(dcr, rMode, gp, atTime); this->giveStressStrainMask( mask, ReducedForm, gp->giveMaterialMode() ); compliance.resize( mask.giveSize(), mask.giveSize() ); // we will set // first we set compliances for normal streses in // local coordinate system defined by crackplane for ( i = 1; i <= 3; i++ ) { if ( ( indi = this->giveStressStrainComponentIndOf(FullForm, gp->giveMaterialMode(), i) ) ) { for ( j = 1; j <= 3; j++ ) { if ( ( indj = this->giveStressStrainComponentIndOf(FullForm, gp->giveMaterialMode(), j) ) ) { compliance.at(indi, indj) += invDe.at(i, j); } } if ( status->isCrackActive(i) ) { if ( dcr.at(i, i) <= 1.e-8 ) { compliance.at(indi, indi) *= rcm2_BIGNUMBER; } else { compliance.at(indi, indi) += 1. / dcr.at(i, i); } } } } status->getPrincipalStressVector(principalStressVector); status->getPrincipalStrainVector(principalStrainVector); // now remain to set shears G = this->give(pscm_G, gp); for ( i = 4; i <= 6; i++ ) { if ( ( indi = this->giveStressStrainComponentIndOf(FullForm, gp->giveMaterialMode(), i) ) ) { if ( i == 4 ) { ii = 2; jj = 3; } else if ( i == 5 ) { ii = 1; jj = 3; } else { ii = 1; jj = 2; } princStressDis = principalStressVector.at(ii) - principalStressVector.at(jj); princStrainDis = principalStrainVector.at(ii) - principalStrainVector.at(jj); if ( fabs(princStrainDis) < rcm_SMALL_STRAIN ) { compliance.at(indi, indi) = 1. / G; } else if ( fabs(princStressDis) < 1.e-8 ) { compliance.at(indi, indi) = rcm2_BIGNUMBER; } else { compliance.at(indi, indi) = 2 * princStrainDis / princStressDis; } } } // now we invert compliance to get stiffness in reduced space d.beInverseOf(compliance); // delete compliance; // // now let d to grow to Full Format // this->giveStressStrainMask( mask, ReducedForm, gp->giveMaterialMode() ); df.beSubMatrixOfSizeOf(d, mask, 6); // // final step - transform stiffnes to global c.s // this->giveStressVectorTranformationMtrx(t, tempCrackDirs, 1); tt.beTranspositionOf(t); df.rotatedWith(tt); if ( form == FullForm ) { answer = df; } else { // reduced form asked this->giveStressStrainMask( mask, FullForm, gp->giveMaterialMode() ); answer.beSubMatrixOf(df, mask); } }
void RCM2Material :: checkForNewActiveCracks(IntArray &answer, GaussPoint *gp, const FloatArray &crackStrain, const FloatArray &princStressVector, FloatArray &crackStressVector, const FloatArray &princStrainVector) // // returns int_array flag showing if some crack // is newly activated or // closed crack is reopened // return 0 if no crack is activated or reactivated. // modifies crackStressVector for newly activated crack. // { double initStress, Le = 0.0; int i, j, upd, activationFlag = 0; RCM2MaterialStatus *status = ( RCM2MaterialStatus * ) this->giveStatus(gp); FloatArray localStress; FloatMatrix tempCrackDirs; IntArray crackMap; answer.resize(3); answer.zero(); status->giveCrackMap(crackMap); localStress = princStressVector; // // local stress is updated according to reached local crack strain // for ( i = 1; i <= 3; i++ ) { // loop over each possible crack plane // test previous status of each possible crack plane upd = 0; if ( ( crackMap.at(i) == 0 ) && ( this->giveStressStrainComponentIndOf(FullForm, gp->giveMaterialMode(), i) ) ) { if ( status->giveTempMaxCrackStrain(i) > 0. ) { // if (status->giveTempCrackStatus()->at(i) != pscm_NONE) { // // previously cracked direction // initStress = 0.; } else { // newer cracked, so we compute principal stresses // and compare them with reduced tension strength // as a criterion for crack initiation FloatArray crackPlaneNormal(3); status->giveTempCrackDirs(tempCrackDirs); for ( j = 1; j <= 3; j++ ) { crackPlaneNormal.at(j) = tempCrackDirs.at(j, i); } // Le = gp->giveElement()->giveCharacteristicLenght (gp, &crackPlaneNormal); Le = this->giveCharacteristicElementLenght(gp, crackPlaneNormal); initStress = this->computeStrength(gp, Le); upd = 1; } if ( localStress.at(i) > initStress ) { crackStressVector.at(i) = initStress; answer.at(i) = 1; activationFlag = 1; if ( upd ) { this->updateStatusForNewCrack(gp, i, Le); } } } // end of tested crack } // end of loop over are possible directions if ( activationFlag ) { return; } answer.resize(0); }
void RCM2Material :: updateCrackStatus(GaussPoint *gp, const FloatArray &crackStrain) // // updates gp records and MatStatus due to cracking. // // Updates MatStatus (respective it's temporary variables) to current // reached status during integrating incremental constitutive relations // Temporary variables are used, because we may integrate constitutive // realtions many times for different strainIncrement in order to // reach equilibrium state, so we don't want to change other variables // which describing previously reached equlibrium. After a new equilibrium // is reached, this->updateYourself is called which invokes matStatus-> // updateYourself(), which copies temporary variables to variables // describing equilibrium. // // { int i; double minCrackStrainsForFullyOpenCrack; RCM2MaterialStatus *status = ( RCM2MaterialStatus * ) this->giveStatus(gp); IntArray crackMap; status->giveCrackMap(crackMap); // check if material previously cracked // and compute possible crack planes // or if newer cracked, so we compute principal stresses // (for iso mat. coincide with princ strains) // and compare them with reduced tension strength // as a criterion for crack initiation // principalStrain = status->givePrincipalStrainVector(); // transform stresses to principal directions of strains // // local stress is updated according to reached local crack strain // for ( i = 1; i <= 3; i++ ) { // loop over each possible crack plane if ( ( crackMap.at(i) != 0 ) && ( this->giveStressStrainComponentIndOf(FullForm, gp->giveMaterialMode(), i) ) ) { if ( status->giveTempMaxCrackStrain(i) < crackStrain.at(i) ) { status->setTempMaxCrackStrain( i, crackStrain.at(i) ); } minCrackStrainsForFullyOpenCrack = this->giveMinCrackStrainsForFullyOpenCrack(gp, i); //if ((crackStrain.at(i) >= status->giveMinCrackStrainsForFullyOpenCrack(i)) && if ( ( crackStrain.at(i) >= minCrackStrainsForFullyOpenCrack ) && ( crackStrain.at(i) >= status->giveTempMaxCrackStrain(i) ) ) { // // fully open crack // status->setTempCrackStatus(i, pscm_OPEN); } else if ( crackStrain.at(i) >= status->giveTempMaxCrackStrain(i) ) { // // further softening of crack // status->setTempCrackStatus(i, pscm_SOFTENING); // status->giveTempReachedSofteningStress()->at(i) = localStress->at(i); } else if ( crackStrain.at(i) <= 0. ) { if ( status->giveTempCrackStatus(i) != pscm_NONE ) { // previously active crack becomes closed status->setTempCrackStatus(i, pscm_CLOSED); } } else { // // crack unloading or reloading // status->setTempCrackStatus(i, pscm_UNLOADING); } } // end for possible direction } // end loop over prin directions }
void RCM2Material :: giveRealPrincipalStressVector3d(FloatArray &answer, GaussPoint *gp, FloatArray &principalStrain, FloatMatrix &tempCrackDirs, TimeStep *atTime) // // returns real principal 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 // updates principal strain and stress of the receiver's status. // { int i, iter, ind; double maxErr; FloatArray crackStrainVector, reducedTotalStrainVector; FloatArray strainIncrement, crackStrainIterativeIncrement; FloatArray prevPrincipalStrain; FloatArray dSigma; FloatArray elastStrain, sigmaEl, sigmaCr(3); FloatArray fullDSigma; IntArray activatedCracks, crackMapping; FloatMatrix dcr, de, decr, fullDecr, crackDirs; RCM2MaterialStatus *status = ( RCM2MaterialStatus * ) this->giveStatus(gp); /* * if (status -> giveStressVector() == NULL) status->letStressVectorBe(new FloatArray(this->giveSizeOfReducedStressStrainVector(gp->giveMaterialMode()))); * if (status -> giveStrainVector() == NULL) status->letStrainVectorBe(new FloatArray(this->giveSizeOfReducedStressStrainVector(gp->giveMaterialMode()))); * // if (status -> givePlasticStrainVector() == NULL) status->letPlasticStrainVectorBe(new FloatArray(6)); * if (status -> giveStressIncrementVector() == NULL) status->letStressIncrementVectorBe(new FloatArray(this->giveSizeOfReducedStressStrainVector(gp->giveMaterialMode()))); * if (status -> giveStrainIncrementVector() == NULL) status->letStrainIncrementVectorBe(new FloatArray(this->giveSizeOfReducedStressStrainVector(gp->giveMaterialMode()))); * // if (status -> givePlasticStrainIncrementVector() == NULL) status->letPlasticStrainIncrementVectorBe(new FloatArray(6)); */ /* * // totalStressVector = gp -> giveStressVector()->GiveCopy(); * reducedTotalStrainVector = status -> giveStrainVector(); * reducedTotalStrainVector.add(fullStrainIncrement); * crossSection->giveFullCharacteristicVector(totalStrainVector, gp, reducedTotalStrainVector); * //delete reducedTotalStrainVector; * // plasticStrainVector = status -> givePlasticStrainVector()->GiveCopy(); * * * // already cracked - next directions are determined * // according to principal strain directions * status->giveTempCrackDirs(tempCrackDirs); * this->computePrincipalValDir (principalStrain, tempCrackDirs, * totalStrainVector, * principal_strain); * status->letTempCrackDirsBe (tempCrackDirs); */ status->giveCrackStrainVector(crackStrainVector); // local one status->giveCrackDirs(crackDirs); if ( principalStrain.containsOnlyZeroes() ) { // keep old principal values status->letTempCrackDirsBe(crackDirs); } else { this->sortPrincDirAndValCloseTo(& principalStrain, & tempCrackDirs, & crackDirs); status->letTempCrackDirsBe(tempCrackDirs); } // compute de in local system // for iso materials no transformation if stiffness required // // local strain increment status->givePrevPrincStrainVector(prevPrincipalStrain); strainIncrement.beDifferenceOf(principalStrain, prevPrincipalStrain); status->letPrincipalStrainVectorBe(principalStrain); this->giveNormalElasticStiffnessMatrix(de, FullForm, TangentStiffness, gp, atTime, tempCrackDirs); // // construct mapping matrix of active cracks // this mapping will dynamically change as // some crack can unlo or reload // this->updateActiveCrackMap(gp); status->giveCrackMap(crackMapping); // start iteration until stress computed from elastic increment // is equal to stress computed from cracking strain increment // we do this computation in reduced stress strain space dSigma.resize(0); for ( iter = 1; iter <= 20; iter++ ) { // // first check if already cracked // if ( status->giveNumberOfTempActiveCracks() ) { // active crack exist this->giveCrackedStiffnessMatrix(dcr, TangentStiffness, gp, atTime); fullDecr = de; fullDecr.add(dcr); decr.beSubMatrixOf(fullDecr, crackMapping); if ( dSigma.giveSize() == 0 ) { fullDSigma.beProductOf(de, strainIncrement); dSigma.beSubArrayOf(fullDSigma, crackMapping); } decr.solveForRhs(dSigma, crackStrainIterativeIncrement); for ( i = 1; i <= 3; i++ ) { if ( ( ind = crackMapping.at(i) ) ) { crackStrainVector.at(i) += crackStrainIterativeIncrement.at(ind); } } // check for crack closing, updates also cracking map this->checkIfClosedCracks(gp, crackStrainVector, crackMapping); // elastic strain component elastStrain.beDifferenceOf(principalStrain, crackStrainVector); sigmaEl.beProductOf(de, elastStrain); // Stress in cracks for ( i = 1; i <= 3; i++ ) { if ( crackMapping.at(i) ) { sigmaCr.at(i) = giveNormalCrackingStress(gp, crackStrainVector.at(i), i); } } // update status status->letCrackStrainVectorBe(crackStrainVector); } else { // // no active crack exist - elastic behaviour // elastStrain.beDifferenceOf(principalStrain, crackStrainVector); sigmaEl.beProductOf(de, elastStrain); sigmaCr.zero(); } // check for new cracks // and update crack map if necessary // when we update map, we need to add new crack at end // because sigmaCr is build this->checkForNewActiveCracks(activatedCracks, gp, crackStrainVector, sigmaEl, sigmaCr, principalStrain); if ( activatedCracks.giveSize() ) { // update crack map also this->updateActiveCrackMap(gp, & activatedCracks); status->giveCrackMap(crackMapping); // update crackMap } // // compute unbalanced stress // dSigma = sigmaEl - sigmaCr for active cracks fullDSigma = sigmaEl; fullDSigma.subtract(sigmaCr); dSigma.beSubArrayOf(fullDSigma, crackMapping); // find max error in dSigma // if max err < allovedErr -> stop iteration // allowed Err is computed relative to Ft; // check only for active cracks maxErr = 0.; for ( i = 1; i <= dSigma.giveSize(); i++ ) { if ( fabs( dSigma.at(i) ) > maxErr ) { maxErr = fabs( dSigma.at(i) ); } } if ( maxErr < rcm_STRESSRELERROR * this->give(pscm_Ft, gp) ) { status->letPrincipalStressVectorBe(sigmaEl); answer = sigmaEl; return; } } // loop // convergence not reached _error("GiveRealStressVector3d - convergence not reached"); }