void FE2FluidMaterial :: giveDeviatoricPressureStiffness(FloatArray &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { FE2FluidMaterialStatus *ms = static_cast<FE2FluidMaterialStatus*> (this->giveStatus(gp)); ms->computeTangents(tStep); if ( mode == TangentStiffness ) { answer = ms->giveDeviatoricPressureTangent(); #ifdef DEBUG_TANGENT // Numerical ATS for debugging FloatArray strain(3); strain.zero(); FloatArray sig, sigh; double epspvol, pressure = 0.0; double h = 1.00; // Linear problem, size of this doesn't matter. computeDeviatoricStressVector (sig, epspvol, gp, strain, pressure, tStep); computeDeviatoricStressVector (sigh, epspvol, gp, strain, pressure+h, tStep); FloatArray dsigh; dsigh.beDifferenceOf(sigh,sig); dsigh.times(1/h); printf("Analytical deviatoric pressure tangent = "); answer.printYourself(); printf("Numerical deviatoric pressure tangent = "); dsigh.printYourself(); dsigh.subtract(answer); double norm = dsigh.computeNorm(); if (norm > answer.computeNorm()*DEBUG_ERR && norm > 0.0) { OOFEM_ERROR("Error in deviatoric pressure tangent"); } #endif } else { OOFEM_ERROR("Mode not implemented"); } }
void NLStructuralElement :: computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) { // Computes the deformation gradient in the Voigt format at the Gauss point gp of // the receiver at time step tStep. // Order of components: 11, 22, 33, 23, 13, 12, 32, 31, 21 in the 3D. // Obtain the current displacement vector of the element and subtract initial displacements (if present) FloatArray u; this->computeVectorOf({D_u, D_v, D_w}, VM_Total, tStep, u); // solution vector if ( initialDisplacements ) { u.subtract(* initialDisplacements); } // Displacement gradient H = du/dX FloatMatrix B; this->computeBHmatrixAt(gp, B); answer.beProductOf(B, u); // Deformation gradient F = H + I MaterialMode matMode = gp->giveMaterialMode(); if ( matMode == _3dMat || matMode == _PlaneStrain ) { answer.at(1) += 1.0; answer.at(2) += 1.0; answer.at(3) += 1.0; } else if ( matMode == _PlaneStress ) { answer.at(1) += 1.0; answer.at(2) += 1.0; } else if ( matMode == _1dMat ) { answer.at(1) += 1.0; } else { OOFEM_ERROR("MaterialMode is not supported yet (%s)", __MaterialModeToString(matMode) ); } }
void B3SolidMaterial :: giveShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) { FloatArray prevAnswer; if ( this->shMode == B3_NoShrinkage ) { answer.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); answer.zero(); return; } if ( ( mode != VM_Total ) && ( mode != VM_Incremental ) ) { OOFEM_ERROR("unsupported mode"); } if ( this->shMode == B3_AverageShrinkage ) { this->computeTotalAverageShrinkageStrainVector(answer, gp, tStep); if ( ( mode == VM_Incremental ) && ( !tStep->isTheFirstStep() ) ) { this->computeTotalAverageShrinkageStrainVector( prevAnswer, gp, tStep->givePreviousStep() ); answer.subtract(prevAnswer); } } else { this->computePointShrinkageStrainVector(answer, gp, tStep); } }
double LineSurfaceTension :: SpatialLocalizerI_giveDistanceFromParametricCenter(const FloatArray &coords) { FloatArray c; c = *this->giveNode(1)->giveCoordinates(); c.add(*this->giveNode(2)->giveCoordinates()); c.times(0.5); c.subtract(coords); return c.computeNorm(); }
void PrimaryField :: initialize(ValueModeType mode, TimeStep *tStep, FloatArray &answer, const UnknownNumberingScheme &s) { if ( mode == VM_Total ) { answer = * ( this->giveSolutionVector(tStep) ); } else if ( mode == VM_Incremental ) { int indxm1 = this->resolveIndx(tStep, -1); answer = * ( this->giveSolutionVector(tStep) ); answer.subtract( * this->giveSolutionVector(indxm1) ); } else { OOFEM_ERROR("unsupported mode %s", __ValueModeTypeToString(mode)); } }
void Beam3d :: giveEndForcesVector(FloatArray &answer, TimeStep *tStep) { // computes exact global end-forces vector FloatArray loadEndForces; this->giveInternalForcesVector(answer, tStep); // add exact end forces due to nonnodal loading this->computeForceLoadVector(loadEndForces, tStep, VM_Total); if ( loadEndForces.giveSize() ) { answer.subtract(loadEndForces); } }
void Beam2d :: giveEndForcesVector(FloatArray &answer, TimeStep *tStep) { // stress equivalent vector in nodes (vector of internal forces) FloatArray load; this->giveInternalForcesVector(answer, tStep, false); // subtract exact end forces due to nonnodal loading this->computeLocalForceLoadVector(load, tStep, VM_Total); if ( load.isNotEmpty() ) { answer.subtract(load); } }
void PrimaryField :: initialize(ValueModeType mode, TimeStep *atTime, FloatArray &answer) { int neq = emodel->giveNumberOfEquations(this->ut); answer.resize(neq); answer.zero(); if ( mode == VM_Total ) { answer = * ( this->giveSolutionVector(atTime) ); } else if ( mode == VM_Incremental ) { int indxm1 = this->resolveIndx(atTime, -1); answer = * ( this->giveSolutionVector(atTime) ); answer.subtract( *this->giveSolutionVector(indxm1) ); } else { _error2( "giveUnknownValue: unsupported mode %s", __ValueModeTypeToString(mode) ); } }
void TransportGradientPeriodic :: computeField(FloatArray &flux, TimeStep *tStep) { DofIDEquationNumbering pnum(true, grad_ids); EngngModel *emodel = this->giveDomain()->giveEngngModel(); FloatArray tmp; int npeq = grad_ids.giveSize(); // sigma = residual (since we use the slave dofs) = f_ext - f_int flux.resize(npeq); flux.zero(); emodel->assembleVector(flux, tStep, InternalForceAssembler(), VM_Total, pnum, this->domain); tmp.resize(npeq); tmp.zero(); emodel->assembleVector(tmp, tStep, ExternalForceAssembler(), VM_Total, pnum, this->domain); flux.subtract(tmp); // Divide by the RVE-volume flux.times(1.0 / ( this->domainSize(this->giveDomain(), this->set) + this->domainSize(this->giveDomain(), this->masterSet) )); }
void StructuralEngngModel :: computeReaction(FloatArray &answer, TimeStep *tStep, int di) { FloatArray contribution; answer.resize( this->giveNumberOfDomainEquations( di, EModelDefaultPrescribedEquationNumbering() ) ); answer.zero(); // Add internal forces this->assembleVector( answer, tStep, LastEquilibratedInternalForcesVector, VM_Total, EModelDefaultPrescribedEquationNumbering(), this->giveDomain(di) ); // Subtract external loading ///@todo All engineering models should be using this (for consistency) //this->assembleVector( answer, tStep, ExternalForcesVector, VM_Total, // EModelDefaultPrescribedEquationNumbering(), this->giveDomain(di) ); ///@todo This method is overloaded in some functions, it needs to be generalized. this->computeExternalLoadReactionContribution(contribution, tStep, di); answer.subtract(contribution); this->updateSharedDofManagers(answer, EModelDefaultPrescribedEquationNumbering(), ReactionExchangeTag); }
void CCTPlate3d :: giveLocalCoordinates(FloatArray &answer, FloatArray &global) // Returns global coordinates given in global vector // transformed into local coordinate system of the // receiver { FloatArray offset; // test the parametr if ( global.giveSize() != 3 ) { _error("giveLocalCoordinate : cannot transform coordinates - size mismatch"); exit(1); } // first ensure that receiver's GtoLRotationMatrix[3,3] is defined if ( GtoLRotationMatrix == NULL ) { this->computeGtoLRotationMatrix(); } offset = global; offset.subtract(*this->giveNode(1)->giveCoordinates()); answer.beProductOf(* GtoLRotationMatrix, offset); }
void StructuralEngngModel :: computeReaction(FloatArray &answer, TimeStep *tStep, int di) { int numRestrDofs = 0; FloatArray contribution; FloatArray EquivForces; numRestrDofs = this->giveNumberOfPrescribedDomainEquations(di, EID_MomentumBalance); answer.resize(numRestrDofs); answer.zero(); // Internal forces contribution this->computeInternalForceReactionContribution(contribution, tStep, di); answer.add(contribution); // External loading contribution this->computeExternalLoadReactionContribution(contribution, tStep, di); answer.subtract(contribution); #ifdef __PARALLEL_MODE this->updateSharedPrescribedDofManagers( answer, ReactionExchangeTag ); #endif }
void StructuralInterfaceElement :: computeSpatialJump(FloatArray &answer, IntegrationPoint *ip, TimeStep *tStep) { // Computes the spatial jump vector at the Gauss point (ip) of // the receiver, at time step (tStep). jump = N*u FloatMatrix N; FloatArray u; if ( !this->isActivated(tStep) ) { answer.resize(3); answer.zero(); return; } this->computeNmatrixAt(ip, N); this->computeVectorOf(VM_Total, tStep, u); // subtract initial displacements, if defined if ( initialDisplacements ) { u.subtract(* initialDisplacements); } answer.beProductOf(N, u); }
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"); }
void SimpleInterfaceMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, //const FloatArray &totalStrain,// @todo temporary -should not be here /JB const FloatArray &strainVector, 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 // { SimpleInterfaceMaterialStatus *status = static_cast< SimpleInterfaceMaterialStatus * >( this->giveStatus(gp) ); //this->initGpForNewStep(gp); this->initTempStatus(gp); FloatArray shearStrain(2), shearStress; //, strainVector; StructuralElement *el = static_cast< StructuralElement * >( gp->giveElement() ); //el->computeStrainVector(strainVector, gp, tStep); FloatArray tempShearStressShift = status->giveTempShearStressShift(); const double normalStrain = strainVector.at(1); double normalStress, maxShearStress, dp; double shift = -this->kn * this->stiffCoeff * normalClearance; MaterialMode mMode = el->giveMaterialMode(); //answer.resize(giveSizeOfReducedStressStrainVector(mMode)); answer.zero(); if ( normalStrain + normalClearance <= 0. ) { normalStress = this->kn * ( normalStrain + normalClearance ) + shift; //in compression and after the clearance gap closed maxShearStress = fabs(normalStress) * this->frictCoeff; } else { normalStress = this->kn * this->stiffCoeff * ( normalStrain + normalClearance ) + shift; maxShearStress = 0.; } switch ( mMode ) { case _1dInterface: answer.resize(1); break; case _2dInterface: answer.resize(2); shearStrain.at(1) = strainVector.at(2); shearStress.beScaled(this->kn, shearStrain); shearStress.subtract(tempShearStressShift); dp = shearStress.dotProduct(shearStress, 1); if ( dp > maxShearStress * maxShearStress ) { shearStress.times( maxShearStress / sqrt(dp) ); } tempShearStressShift.beScaled(this->kn, shearStrain); tempShearStressShift.subtract(shearStress); answer.at(2) = shearStress.at(1); break; case _3dInterface: case _3dMat: //JB answer.resize(3); shearStrain.at(1) = strainVector.at(2); shearStrain.at(2) = strainVector.at(3); shearStress.beScaled(this->kn, shearStrain); shearStress.subtract(tempShearStressShift); dp = shearStress.dotProduct(shearStress, 2); if ( dp > maxShearStress * maxShearStress ) { shearStress.times( maxShearStress / sqrt(dp) ); } tempShearStressShift.beScaled(this->kn, shearStrain); tempShearStressShift.subtract(shearStress); answer.at(2) = shearStress.at(1); answer.at(3) = shearStress.at(2); break; default: OOFEM_ERROR("Unsupported interface mode"); } double lim = 1.e+50; answer.at(1) = min(normalStress, lim); //threshold on maximum answer.at(1) = max(answer.at(1), -lim); //threshold on minimum //answer.at(1) = normalStress > lim ? lim : normalStress < -lim ? -lim : normalStress; // update gp status->setTempShearStressShift(tempShearStressShift); status->letTempStrainVectorBe(strainVector); status->letTempStressVectorBe(answer); }
int FEI3dHexaLin :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) { double x1, x2, x3, x4, x5, x6, x7, x8, a1, a2, a3, a4, a5, a6, a7, a8; double y1, y2, y3, y4, y5, y6, y7, y8, b1, b2, b3, b4, b5, b6, b7, b8; double z1, z2, z3, z4, z5, z6, z7, z8, c1, c2, c3, c4, c5, c6, c7, c8; double xp, yp, zp, u, v, w; FloatMatrix p(3, 3); FloatArray r(3), delta; int nite = 0; x1 = cellgeo.giveVertexCoordinates(1)->at(1); x2 = cellgeo.giveVertexCoordinates(2)->at(1); x3 = cellgeo.giveVertexCoordinates(3)->at(1); x4 = cellgeo.giveVertexCoordinates(4)->at(1); x5 = cellgeo.giveVertexCoordinates(5)->at(1); x6 = cellgeo.giveVertexCoordinates(6)->at(1); x7 = cellgeo.giveVertexCoordinates(7)->at(1); x8 = cellgeo.giveVertexCoordinates(8)->at(1); y1 = cellgeo.giveVertexCoordinates(1)->at(2); y2 = cellgeo.giveVertexCoordinates(2)->at(2); y3 = cellgeo.giveVertexCoordinates(3)->at(2); y4 = cellgeo.giveVertexCoordinates(4)->at(2); y5 = cellgeo.giveVertexCoordinates(5)->at(2); y6 = cellgeo.giveVertexCoordinates(6)->at(2); y7 = cellgeo.giveVertexCoordinates(7)->at(2); y8 = cellgeo.giveVertexCoordinates(8)->at(2); z1 = cellgeo.giveVertexCoordinates(1)->at(3); z2 = cellgeo.giveVertexCoordinates(2)->at(3); z3 = cellgeo.giveVertexCoordinates(3)->at(3); z4 = cellgeo.giveVertexCoordinates(4)->at(3); z5 = cellgeo.giveVertexCoordinates(5)->at(3); z6 = cellgeo.giveVertexCoordinates(6)->at(3); z7 = cellgeo.giveVertexCoordinates(7)->at(3); z8 = cellgeo.giveVertexCoordinates(8)->at(3); xp = coords.at(1); yp = coords.at(2); zp = coords.at(3); a1 = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8; a2 = -x1 - x2 + x3 + x4 - x5 - x6 + x7 + x8; a3 = -x1 + x2 + x3 - x4 - x5 + x6 + x7 - x8; a4 = x1 + x2 + x3 + x4 - x5 - x6 - x7 - x8; a5 = x1 - x2 + x3 - x4 + x5 - x6 + x7 - x8; a6 = -x1 - x2 + x3 + x4 + x5 + x6 - x7 - x8; a7 = -x1 + x2 + x3 - x4 + x5 - x6 - x7 + x8; a8 = x1 - x2 + x3 - x4 - x5 + x6 - x7 + x8; b1 = y1 + y2 + y3 + y4 + y5 + y6 + y7 + y8; b2 = -y1 - y2 + y3 + y4 - y5 - y6 + y7 + y8; b3 = -y1 + y2 + y3 - y4 - y5 + y6 + y7 - y8; b4 = y1 + y2 + y3 + y4 - y5 - y6 - y7 - y8; b5 = y1 - y2 + y3 - y4 + y5 - y6 + y7 - y8; b6 = -y1 - y2 + y3 + y4 + y5 + y6 - y7 - y8; b7 = -y1 + y2 + y3 - y4 + y5 - y6 - y7 + y8; b8 = y1 - y2 + y3 - y4 - y5 + y6 - y7 + y8; c1 = z1 + z2 + z3 + z4 + z5 + z6 + z7 + z8; c2 = -z1 - z2 + z3 + z4 - z5 - z6 + z7 + z8; c3 = -z1 + z2 + z3 - z4 - z5 + z6 + z7 - z8; c4 = z1 + z2 + z3 + z4 - z5 - z6 - z7 - z8; c5 = z1 - z2 + z3 - z4 + z5 - z6 + z7 - z8; c6 = -z1 - z2 + z3 + z4 + z5 + z6 - z7 - z8; c7 = -z1 + z2 + z3 - z4 + z5 - z6 - z7 + z8; c8 = z1 - z2 + z3 - z4 - z5 + z6 - z7 + z8; // setup initial guess answer.resize(3); answer.zero(); // apply Newton-Raphson to solve the problem do { if ( ( ++nite ) > 10 ) { // fprintf(stderr, "FEI3dHexaLin :: global2local: no convergence after 10 iterations"); answer.zero(); return false; } u = answer.at(1); v = answer.at(2); w = answer.at(3); // compute the residual r.at(1) = a1 + u * a2 + v * a3 + w * a4 + u * v * a5 + u * w * a6 + v * w * a7 + u * v * w * a8 - 8.0 * xp; r.at(2) = b1 + u * b2 + v * b3 + w * b4 + u * v * b5 + u * w * b6 + v * w * b7 + u * v * w * b8 - 8.0 * yp; r.at(3) = c1 + u * c2 + v * c3 + w * c4 + u * v * c5 + u * w * c6 + v * w * c7 + u * v * w * c8 - 8.0 * zp; // check for convergence if ( r.computeSquaredNorm() < 1.e-20 ) { break; // sqrt(1.e-20) = 1.e-10 } p.at(1, 1) = a2 + v * a5 + w * a6 + v * w * a8; p.at(1, 2) = a3 + u * a5 + w * a7 + u * w * a8; p.at(1, 3) = a4 + u * a6 + v * a7 + u * v * a8; p.at(2, 1) = b2 + v * b5 + w * b6 + v * w * b8; p.at(2, 2) = b3 + u * b5 + w * b7 + u * w * b8; p.at(2, 3) = b4 + u * b6 + v * b7 + u * v * b8; p.at(3, 1) = c2 + v * c5 + w * c6 + v * w * c8; p.at(3, 2) = c3 + u * c5 + w * c7 + u * w * c8; p.at(3, 3) = c4 + u * c6 + v * c7 + u * v * c8; // solve for corrections p.solveForRhs(r, delta); // update guess answer.subtract(delta); } while ( 1 ); // test if inside bool inside = true; for ( int i = 1; i <= 3; i++ ) { if ( answer.at(i) < ( -1. - POINT_TOL ) ) { answer.at(i) = -1.; inside = false; } else if ( answer.at(i) > ( 1. + POINT_TOL ) ) { answer.at(i) = 1.; inside = false; } } return inside; }
void FE2FluidMaterial :: giveStiffnessMatrices(FloatMatrix &dsdd, FloatArray &dsdp, FloatArray &dedd, double &dedp, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { FE2FluidMaterialStatus *ms = static_cast< FE2FluidMaterialStatus * >( this->giveStatus(gp) ); ms->computeTangents(tStep); if ( mode == TangentStiffness ) { dsdd = ms->giveDeviatoricTangent(); dsdp = ms->giveDeviatoricPressureTangent(); dedd = ms->giveVolumetricDeviatoricTangent(); dedp = ms->giveVolumetricPressureTangent(); #if 0 // Numerical ATS for debugging FloatMatrix numericalATS(6, 6); FloatArray dsig; FloatArray tempStrain(6); tempStrain.zero(); FloatArray sig, strain, sigPert; double epspvol; computeDeviatoricStressVector(sig, epspvol, gp, tempStrain, 0., tStep); double h = 0.001; // Linear problem, size of this doesn't matter. for ( int k = 1; k <= 6; ++k ) { strain = tempStrain; strain.at(k) += h; double tmp = strain.at(1) + strain.at(2) + strain.at(3); strain.at(1) -= tmp/3.0; strain.at(2) -= tmp/3.0; strain.at(3) -= tmp/3.0; strain.printYourself(); computeDeviatoricStressVector(sigPert, epspvol, gp, strain, 0., tStep); sigPert.printYourself(); dsig.beDifferenceOf(sigPert, sig); numericalATS.setColumn(dsig, k); } numericalATS.times(1. / h); printf("Analytical deviatoric tangent = "); dsdd.printYourself(); printf("Numerical deviatoric tangent = "); numericalATS.printYourself(); numericalATS.subtract(dsdd); double norm = numericalATS.computeFrobeniusNorm(); if ( norm > dsdd.computeFrobeniusNorm() * DEBUG_ERR && norm > 0.0 ) { OOFEM_ERROR("Error in deviatoric tangent"); } #endif #if 0 // Numerical ATS for debugging FloatArray strain(3); strain.zero(); FloatArray sig, sigh; double epspvol, pressure = 0.0; double h = 1.00; // Linear problem, size of this doesn't matter. computeDeviatoricStressVector(sig, epspvol, gp, strain, pressure, tStep); computeDeviatoricStressVector(sigh, epspvol, gp, strain, pressure + h, tStep); FloatArray dsigh; dsigh.beDifferenceOf(sigh, sig); dsigh.times(1 / h); printf("Analytical deviatoric pressure tangent = "); dsdp.printYourself(); printf("Numerical deviatoric pressure tangent = "); dsigh.printYourself(); dsigh.subtract(dsdp); double norm = dsigh.computeNorm(); if ( norm > dsdp.computeNorm() * DEBUG_ERR && norm > 0.0 ) { OOFEM_ERROR("Error in deviatoric pressure tangent"); } #endif #if 0 // Numerical ATS for debugging FloatArray tempStrain(3); tempStrain.zero(); FloatArray sig, strain; double epspvol, epspvol11, epspvol22, epspvol12, pressure = 0.0; double h = 1.0; // Linear problem, size of this doesn't matter. computeDeviatoricStressVector(sig, epspvol, gp, tempStrain, pressure, tStep); strain = tempStrain; strain.at(1) += h; computeDeviatoricStressVector(sig, epspvol11, gp, strain, pressure, tStep); strain = tempStrain; strain.at(2) += h; computeDeviatoricStressVector(sig, epspvol22, gp, strain, pressure, tStep); strain = tempStrain; strain.at(3) += h; computeDeviatoricStressVector(sig, epspvol12, gp, strain, pressure, tStep); FloatArray dvol(3); dvol.at(1) = ( epspvol11 - epspvol ) / h; dvol.at(2) = ( epspvol22 - epspvol ) / h; dvol.at(3) = ( epspvol12 - epspvol ) / h; dvol.at(1) += 1.0; dvol.at(2) += 1.0; printf("Analytical volumetric deviatoric tangent = "); dedd.printYourself(); printf("Numerical volumetric deviatoric tangent = "); dvol.printYourself(); dvol.subtract(dedd); double norm = dvol.computeNorm(); if ( norm > dedd.computeNorm() * DEBUG_ERR && norm > 0.0 ) { OOFEM_ERROR("Error in volumetric deviatoric tangent"); } #endif #if 0 // Numerical ATS for debugging FloatArray strain(3); strain.zero(); FloatArray sig; double epspvol, epspvolh, pressure = 0.0; double h = 1.0; // Linear problem, size of this doesn't matter. computeDeviatoricStressVector(sig, epspvol, gp, strain, pressure, tStep); computeDeviatoricStressVector(sig, epspvolh, gp, strain, pressure + h, tStep); double dvol = -( epspvolh - epspvol ) / h; printf("Analytical volumetric pressure tangent = %e\n", dedp); printf("Numerical volumetric pressure tangent = %e\n", dvol); double norm = fabs(dvol - dedp); if ( norm > fabs(dedp) * DEBUG_ERR && norm > 0.0 ) { OOFEM_ERROR("Error in volumetric pressure tangent"); } #endif } else { OOFEM_ERROR("Mode not implemented"); } }
void AbaqusUserMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) { AbaqusUserMaterialStatus *ms = static_cast< AbaqusUserMaterialStatus * >( this->giveStatus(gp) ); /* User-defined material name, left justified. Some internal material models are given names starting with * the “ABQ_” character string. To avoid conflict, you should not use “ABQ_” as the leading string for * CMNAME. */ //char cmname[80]; // Sizes of the tensors. int ndi = 3; int nshr = 3; int ntens = ndi + nshr; FloatArray strain = ms->giveStrainVector(); FloatArray stress = ms->giveStressVector(); // adding the initial stress stress.add(initialStress); FloatArray strainIncrement; strainIncrement.beDifferenceOf(reducedStrain, strain); FloatArray state = ms->giveStateVector(); FloatMatrix jacobian(ntens, ntens); int numProperties = this->properties.giveSize(); // Temperature and increment double temp = 0.0, dtemp = 0.0; // Times and increment double dtime = tStep->giveTimeIncrement(); ///@todo Check this. I'm just guessing. Maybe intrinsic time instead? double time [ 2 ] = { tStep->giveTargetTime() - dtime, tStep->giveTargetTime() }; double pnewdt = 1.0; ///@todo Right default value? umat routines may change this (although we ignore it) /* Specific elastic strain energy, plastic dissipation, and “creep” dissipation, respectively. These are passed * in as the values at the start of the increment and should be updated to the corresponding specific energy * values at the end of the increment. They have no effect on the solution, except that they are used for * energy output. */ double sse, spd, scd; // Outputs only in a fully coupled thermal-stress analysis: double rpl = 0.0; // Volumetric heat generation per unit time at the end of the increment caused by mechanical working of the material. FloatArray ddsddt(ntens); // Variation of the stress increments with respect to the temperature. FloatArray drplde(ntens); // Variation of RPL with respect to the strain increments. double drpldt = 0.0; // Variation of RPL with respect to the temperature. /* An array containing the coordinates of this point. These are the current coordinates if geometric * nonlinearity is accounted for during the step (see “Procedures: overview,” Section 6.1.1); otherwise, * the array contains the original coordinates of the point */ FloatArray coords; gp->giveElement()->computeGlobalCoordinates( coords, gp->giveNaturalCoordinates() ); /* Rotation increment matrix. This matrix represents the increment of rigid body rotation of the basis * system in which the components of stress (STRESS) and strain (STRAN) are stored. It is provided so * that vector- or tensor-valued state variables can be rotated appropriately in this subroutine: stress and * strain components are already rotated by this amount before UMAT is called. This matrix is passed in * as a unit matrix for small-displacement analysis and for large-displacement analysis if the basis system * for the material point rotates with the material (as in a shell element or when a local orientation is used).*/ FloatMatrix drot(3, 3); drot.beUnitMatrix(); /* Characteristic element length, which is a typical length of a line across an element for a first-order * element; it is half of the same typical length for a second-order element. For beams and trusses it is a * characteristic length along the element axis. For membranes and shells it is a characteristic length in * the reference surface. For axisymmetric elements it is a characteristic length in the * plane only. * For cohesive elements it is equal to the constitutive thickness.*/ double celent = 0.0; /// @todo Include the characteristic element length /* Array containing the deformation gradient at the beginning of the increment. See the discussion * regarding the availability of the deformation gradient for various element types. */ FloatMatrix dfgrd0(3, 3); dfgrd0.beUnitMatrix(); /* Array containing the deformation gradient at the end of the increment. The components of this array * are set to zero if nonlinear geometric effects are not included in the step definition associated with * this increment. See the discussion regarding the availability of the deformation gradient for various * element types. */ FloatMatrix dfgrd1(3, 3); dfgrd1.beUnitMatrix(); int noel = gp->giveElement()->giveNumber(); // Element number. int npt = 0; // Integration point number. int layer = 0; // Layer number (for composite shells and layered solids).. int kspt = 0; // Section point number within the current layer. int kstep = 0; // Step number. int kinc = 0; // Increment number. ///@todo No idea about these parameters double predef; double dpred; // Change to Abaqus's component order stress.changeComponentOrder(); strain.changeComponentOrder(); strainIncrement.changeComponentOrder(); // printf("stress oofem: "); stress.printYourself(); OOFEM_LOG_DEBUG("AbaqusUserMaterial :: giveRealStressVector_3d - Calling subroutine"); this->umat(stress.givePointer(), // STRESS state.givePointer(), // STATEV jacobian.givePointer(), // DDSDDE & sse, // SSE & spd, // SPD & scd, // SCD & rpl, // RPL ddsddt.givePointer(), // DDSDDT drplde.givePointer(), // DRPLDE & drpldt, // DRPLDT strain.givePointer(), // STRAN strainIncrement.givePointer(), // DSTRAN time, // TIME & dtime, // DTIME & temp, // TEMP & dtemp, // DTEMP & predef, // PREDEF & dpred, // DPRED this->cmname, // CMNAME & ndi, // NDI & nshr, // NSHR & ntens, // NTENS & numState, // NSTATV properties.givePointer(), // PROPS & numProperties, // NPROPS coords.givePointer(), // COORDS drot.givePointer(), // DROT & pnewdt, // PNEWDT & celent, // CELENT dfgrd0.givePointer(), // DFGRD0 dfgrd1.givePointer(), // DFGRD1 & noel, // NOEL & npt, // NPT & layer, // LAYER & kspt, // KSPT & kstep, // KSTEP & kinc); // KINC // Change to OOFEM's component order stress.changeComponentOrder(); // subtracking the initial stress stress.subtract(initialStress); strain.changeComponentOrder(); strainIncrement.changeComponentOrder(); jacobian.changeComponentOrder(); ms->letTempStrainVectorBe(reducedStrain); ms->letTempStressVectorBe(stress); ms->letTempStateVectorBe(state); ms->letTempTangentBe(jacobian); answer = stress; OOFEM_LOG_DEBUG("AbaqusUserMaterial :: giveRealStressVector - Calling subroutine was successful"); }
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); }