void SolutionbasedShapeFunction :: computeCorrectionFactors(modeStruct &myMode, IntArray *Dofs, double *am, double *ap) { /* * *Compute c0, cp, cm, Bp, Bm, Ap and Am */ double A0p = 0.0, App = 0.0, A0m = 0.0, Amm = 0.0, Bp = 0.0, Bm = 0.0, c0 = 0.0, cp = 0.0, cm = 0.0; EngngModel *m = myMode.myEngngModel; Set *mySet = m->giveDomain(1)->giveSet(externalSet); IntArray BoundaryList = mySet->giveBoundaryList(); for ( int i = 0; i < BoundaryList.giveSize() / 2; i++ ) { int ElementID = BoundaryList(2 * i); int Boundary = BoundaryList(2 * i + 1); Element *thisElement = m->giveDomain(1)->giveElement(ElementID); FEInterpolation *geoInterpolation = thisElement->giveInterpolation(); IntArray bnodes, zNodes, pNodes, mNodes; FloatMatrix nodeValues; geoInterpolation->boundaryGiveNodes(bnodes, Boundary); nodeValues.resize( this->dofs.giveSize(), bnodes.giveSize() ); nodeValues.zero(); // Change to global ID for bnodes and identify the intersection of bnodes and the zero boundary splitBoundaryNodeIDs(myMode, * thisElement, bnodes, pNodes, mNodes, zNodes, nodeValues); std :: unique_ptr< IntegrationRule >iRule(geoInterpolation->giveBoundaryIntegrationRule(order, Boundary)); for ( GaussPoint *gp: *iRule ) { FloatArray *lcoords = gp->giveCoordinates(); FloatArray gcoords, normal, N; FloatArray Phi; double detJ = fabs( geoInterpolation->boundaryGiveTransformationJacobian( Boundary, * lcoords, FEIElementGeometryWrapper(thisElement) ) ) * gp->giveWeight(); geoInterpolation->boundaryEvalNormal( normal, Boundary, * lcoords, FEIElementGeometryWrapper(thisElement) ); geoInterpolation->boundaryEvalN( N, Boundary, * lcoords, FEIElementGeometryWrapper(thisElement) ); geoInterpolation->boundaryLocal2Global( gcoords, Boundary, * lcoords, FEIElementGeometryWrapper(thisElement) ); FloatArray pPhi, mPhi, zPhi; pPhi.resize( Dofs->giveSize() ); pPhi.zero(); mPhi.resize( Dofs->giveSize() ); mPhi.zero(); zPhi.resize( Dofs->giveSize() ); zPhi.zero(); // Build phi (analytical averaging, not projected onto the mesh) computeBaseFunctionValueAt(Phi, gcoords, * Dofs, * myMode.myEngngModel); // Build zPhi for this DofID for ( int l = 1; l <= zNodes.giveSize(); l++ ) { int nodeID = zNodes.at(l); for ( int m = 1; m <= this->dofs.giveSize(); m++ ) { zPhi.at(m) = zPhi.at(m) + N.at(nodeID) * nodeValues.at(m, nodeID); } } // Build pPhi for this DofID for ( int l = 1; l <= pNodes.giveSize(); l++ ) { int nodeID = pNodes.at(l); for ( int m = 1; m <= this->dofs.giveSize(); m++ ) { pPhi.at(m) = pPhi.at(m) + N.at(nodeID) * nodeValues.at(m, nodeID); } } // Build mPhi for this DofID for ( int l = 1; l <= mNodes.giveSize(); l++ ) { int nodeID = mNodes.at(l); for ( int m = 1; m <= this->dofs.giveSize(); m++ ) { mPhi.at(m) = mPhi.at(m) + N.at(nodeID) * nodeValues.at(m, nodeID); } } c0 = c0 + zPhi.dotProduct(normal, 3) * detJ; cp = cp + pPhi.dotProduct(normal, 3) * detJ; cm = cm + mPhi.dotProduct(normal, 3) * detJ; App = App + pPhi.dotProduct(pPhi, 3) * detJ; Amm = Amm + mPhi.dotProduct(mPhi, 3) * detJ; A0p = A0p + zPhi.dotProduct(pPhi, 3) * detJ; A0m = A0m + zPhi.dotProduct(mPhi, 3) * detJ; Bp = Bp + Phi.dotProduct(pPhi, 3) * detJ; Bm = Bm + Phi.dotProduct(mPhi, 3) * detJ; } } * am = -( A0m * cp * cp - Bm * cp * cp - A0p * cm * cp + App * c0 * cm + Bp * cm * cp ) / ( App * cm * cm + Amm * cp * cp ); * ap = -( A0p * cm * cm - Bp * cm * cm - A0m * cm * cp + Amm * c0 * cp + Bm * cm * cp ) / ( App * cm * cm + Amm * cp * cp ); }
void IntElLine2 :: computeNmatrixAt(GaussPoint *ip, FloatMatrix &answer) { // Returns the modified N-matrix which multiplied with u give the spatial jump. FloatArray N; answer.resize(2, 12); answer.zero(); if(linear) { interpLin.evalN( N, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); answer.at(1, 1) = answer.at(2, 2) = -N.at(1); answer.at(1, 3) = answer.at(2, 4) = -N.at(2); // answer.at(1, 5) = answer.at(2, 6) = -N.at(3); answer.at(1, 7) = answer.at(2, 8) = N.at(1); answer.at(1, 9) = answer.at(2, 10) = N.at(2); // answer.at(1, 11) = answer.at(2, 12) = N.at(3); } else { interp.evalN( N, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); answer.at(1, 1) = answer.at(2, 2) = -N.at(1); answer.at(1, 3) = answer.at(2, 4) = -N.at(2); answer.at(1, 5) = answer.at(2, 6) = -N.at(3); answer.at(1, 7) = answer.at(2, 8) = N.at(1); answer.at(1, 9) = answer.at(2, 10) = N.at(2); answer.at(1, 11) = answer.at(2, 12) = N.at(3); } }
void LineSurfaceTension :: computeTangent(FloatMatrix &answer, TimeStep *tStep) { #if 1 ///@todo Not sure if it's a good idea to use this tangent. answer.resize(4,4); answer.zero(); #else domainType dt = this->giveDomain()->giveDomainType(); int ndofs = this->computeNumberOfDofs(EID_MomentumBalance); Node *node1, *node2; double x1, x2, y1, y2, dx, dy, vx, vy, length, width, gamma_s; gamma_s = this->giveMaterial()->give('g',NULL); node1 = giveNode(1); node2 = giveNode(2); x1 = node1->giveCoordinate(1); x2 = node2->giveCoordinate(1); y1 = node1->giveCoordinate(2); y2 = node2->giveCoordinate(2); dx = x2-x1; dy = y2-y1; length = sqrt(dx*dx + dy*dy); vx = dx/length; vy = dy/length; FloatArray Ah(4); Ah.at(1) = -vx; Ah.at(2) = -vy; Ah.at(3) = vx; Ah.at(4) = vy; FloatMatrix NpTNp(4,4); NpTNp.zero(); NpTNp.at(1,1) = 1; NpTNp.at(2,2) = 1; NpTNp.at(3,3) = 1; NpTNp.at(4,4) = 1; NpTNp.at(1,3) = -1; NpTNp.at(2,4) = -1; NpTNp.at(3,1) = -1; NpTNp.at(4,2) = -1; answer.resize(ndofs,ndofs); answer.zero(); if (dt == _3dAxisymmMode) { OOFEM_WARNING("Not tested"); FloatArray Bh(4); Bh.zero(); Bh.at(1) = 1; Bh.at(3) = 1; // It was simpler to write this in index notation. // Also using 0-based, to reduce typing double rJinv = (x1+x2)/length; answer.zero(); for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) { answer(i,j) = M_PI*(Ah(i)*Bh(j) + Bh(i)*Ah(j)+ rJinv*(NpTNp(i,j) - Ah(i)*Ah(j))); } } else { width = 1; answer.beDyadicProductOf(Ah,Ah); answer.add(NpTNp); answer.times(width/length); } answer.times(gamma_s); #endif }
void SUPGTangentAssembler :: matrixFromElement(FloatMatrix &answer, Element &el, TimeStep *tStep) const { SUPGElement *element = static_cast< SUPGElement * >( &el ); IntArray vloc, ploc; FloatMatrix h; int size = element->computeNumberOfDofs(); element->giveLocalVelocityDofMap(vloc); element->giveLocalPressureDofMap(ploc); answer.resize(size, size); answer.zero(); element->computeAccelerationTerm_MB(h, tStep); answer.assemble(h, vloc); element->computeAdvectionDerivativeTerm_MB(h, tStep); h.times( alpha * tStep->giveTimeIncrement() ); answer.assemble(h, vloc); element->computeDiffusionDerivativeTerm_MB(h, rmode, tStep); h.times( alpha * tStep->giveTimeIncrement() ); answer.assemble(h, vloc); element->computePressureTerm_MB(h, tStep); answer.assemble(h, vloc, ploc); element->computeLSICStabilizationTerm_MB(h, tStep); h.times( alpha * tStep->giveTimeIncrement() * lscale / ( dscale * uscale * uscale ) ); answer.assemble(h, vloc); element->computeBCLhsTerm_MB(h, tStep); if ( h.isNotEmpty() ) { h.times( alpha * tStep->giveTimeIncrement() ); answer.assemble(h, vloc); } element->computeBCLhsPressureTerm_MB(h, tStep); if ( h.isNotEmpty() ) { answer.assemble(h, vloc, ploc); } // conservation eq part element->computeLinearAdvectionTerm_MC(h, tStep); h.times( alpha * tStep->giveTimeIncrement() * 1.0 / ( dscale * uscale ) ); answer.assemble(h, ploc, vloc); element->computeAdvectionDerivativeTerm_MC(h, tStep); h.times( alpha * tStep->giveTimeIncrement() ); answer.assemble(h, ploc, vloc); element->computeAccelerationTerm_MC(h, tStep); answer.assemble(h, ploc, vloc); element->computeBCLhsPressureTerm_MC(h, tStep); if ( h.isNotEmpty() ) { answer.assemble(h, ploc, vloc); } element->computeDiffusionDerivativeTerm_MC(h, tStep); h.times( alpha * tStep->giveTimeIncrement() ); answer.assemble(h, ploc, vloc); element->computePressureTerm_MC(h, tStep); answer.assemble(h, ploc); }
void ZZErrorEstimatorInterface :: ZZErrorEstimatorI_computeElementContributions(double &eNorm, double &sNorm, ZZErrorEstimator :: NormType norm, InternalStateType type, TimeStep *tStep) { int nDofMans; FEInterpolation *interpol = element->giveInterpolation(); const FloatArray *recoveredStress; FloatArray sig, lsig, diff, ldiff, n; FloatMatrix nodalRecoveredStreses; nDofMans = element->giveNumberOfDofManagers(); // assemble nodal recovered stresses for ( int i = 1; i <= element->giveNumberOfNodes(); i++ ) { element->giveDomain()->giveSmoother()->giveNodalVector( recoveredStress, element->giveDofManager(i)->giveNumber() ); if ( i == 1 ) { nodalRecoveredStreses.resize( nDofMans, recoveredStress->giveSize() ); } for ( int j = 1; j <= recoveredStress->giveSize(); j++ ) { nodalRecoveredStreses.at(i, j) = recoveredStress->at(j); } } /* Note: The recovered stresses should be in global coordinate system. This is important for shells, for example, to make * sure that forces and moments in the same directions are averaged. For elements where local and global coordina systems * are the same this does not matter. */ eNorm = sNorm = 0.0; // compute the e-norm and s-norm if ( norm == ZZErrorEstimator :: L2Norm ) { for ( GaussPoint *gp: *this->ZZErrorEstimatorI_giveIntegrationRule() ) { double dV = element->computeVolumeAround(gp); interpol->evalN( n, * gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(element) ); diff.beTProductOf(nodalRecoveredStreses, n); element->giveIPValue(sig, gp, type, tStep); /* the internal stress difference is in global coordinate system */ diff.subtract(sig); eNorm += diff.computeSquaredNorm() * dV; sNorm += sig.computeSquaredNorm() * dV; } } else if ( norm == ZZErrorEstimator :: EnergyNorm ) { FloatArray help, ldiff_reduced, lsig_reduced; FloatMatrix D, DInv; StructuralElement *selem = static_cast< StructuralElement * >(element); for ( GaussPoint *gp: *this->ZZErrorEstimatorI_giveIntegrationRule() ) { double dV = element->computeVolumeAround(gp); interpol->evalN( n, * gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(element) ); selem->computeConstitutiveMatrixAt(D, TangentStiffness, gp, tStep); DInv.beInverseOf(D); diff.beTProductOf(nodalRecoveredStreses, n); element->giveIPValue(sig, gp, type, tStep); // returns full value now diff.subtract(sig); /* the internal stress difference is in global coordinate system */ /* needs to be transformed into local system to compute associated energy */ this->ZZErrorEstimatorI_computeLocalStress(ldiff, diff); StructuralMaterial :: giveReducedSymVectorForm( ldiff_reduced, ldiff, gp->giveMaterialMode() ); help.beProductOf(DInv, ldiff_reduced); eNorm += ldiff_reduced.dotProduct(help) * dV; this->ZZErrorEstimatorI_computeLocalStress(lsig, sig); StructuralMaterial :: giveReducedSymVectorForm( lsig_reduced, lsig, gp->giveMaterialMode() ); help.beProductOf(DInv, lsig_reduced); sNorm += lsig_reduced.dotProduct(help) * dV; } } else { OOFEM_ERROR("unsupported norm type"); } eNorm = sqrt(eNorm); sNorm = sqrt(sNorm); }
void FiberedCrossSection :: give3dBeamStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) // // General strain fiber vector has one of the following forms: // 1) strainVector3d {eps_x,eps_y,eps_z,gamma_yz,gamma_zx,gamma_xy} // // returned strain or stress vector has the form: // 2) strainVectorShell {eps_x, gamma_xz, gamma_xy, \der{phi_x}{x}, kappa_y, kappa_z} // { FloatMatrix fiberMatrix; GaussPoint *fiberGp; double fiberThick, fiberWidth, fiberZCoord, fiberYCoord; double fiberZCoord2, fiberYCoord2, Ip = 0.0, A = 0.0, Ik, G = 0.0; // if (form != ReducedForm) error ("give3dShellMaterialStiffness : full form unsupported"); answer.resize(6, 6); answer.zero(); // perform integration over layers for ( int i = 1; i <= numberOfFibers; i++ ) { fiberGp = giveSlaveGaussPoint(gp, i - 1); this->giveFiberMaterialStiffnessMatrix(fiberMatrix, rMode, fiberGp, tStep); // // resolve current layer z-coordinate // fiberThick = this->fiberThicks.at(i); fiberWidth = this->fiberWidths.at(i); fiberZCoord = fiberZcoords.at(i); fiberYCoord = fiberYcoords.at(i); fiberYCoord2 = fiberYCoord * fiberYCoord; fiberZCoord2 = fiberZCoord * fiberZCoord; // // perform integration // // 1) membrane terms N, Qz, Qy answer.at(1, 1) += fiberMatrix.at(1, 1) * fiberWidth * fiberThick; answer.at(2, 2) += fiberMatrix.at(2, 2) * fiberWidth * fiberThick; answer.at(3, 3) += fiberMatrix.at(3, 3) * fiberWidth * fiberThick; // 2) bending terms mx, my, mz Ip += fiberWidth * fiberThick * fiberZCoord2 + fiberWidth * fiberThick * fiberYCoord2; A += fiberWidth * fiberThick; G = fiberMatrix.at(2, 2) * fiberWidth * fiberThick; answer.at(5, 5) += fiberMatrix.at(1, 1) * fiberWidth * fiberThick * fiberZCoord2; answer.at(6, 6) += fiberMatrix.at(1, 1) * fiberWidth * fiberThick * fiberYCoord2; } ///@todo This must be wrong, it will use the last evaluated G (from the last fiber), outside the loop. FIXME! G /= A; Ik = A * A * A * A / ( 40.0 * Ip ); answer.at(4, 4) = G * Ik; }
void LSpaceBB :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) // Returns the [6x24] strain-displacement matrix {B} of the receiver, eva- // luated at gp. // B matrix - 6 rows : epsilon-X, epsilon-Y, epsilon-Z, gamma-YZ, gamma-ZX, gamma-XY : { int i; FloatMatrix dnx, dnx0; FloatArray coord(3); answer.resize(6, 24); answer.zero(); coord.zero(); LSpace :: interpolation.evaldNdx( dnx, * gp->giveCoordinates(), FEIElementGeometryWrapper(this) ); LSpace :: interpolation.evaldNdx( dnx0, coord, FEIElementGeometryWrapper(this) ); // deviatoric part fully integrated, volumetric part in one point // here we follow BBar approach // // construct BB = B(gp) + Pv [B(0)-B(gp)] // where Pv is volumetric projection mtrx // B(gp) is original geometrical matrix evalueated at gp // B(0) is geometrical matrix evalueated at centroid // // assemble Pv [B(0)-B(gp)] for ( i = 1; i <= 8; i++ ) { answer.at(1, 3 * i - 2) = answer.at(2, 3 * i - 2) = answer.at(3, 3 * i - 2) = ( dnx0.at(i, 1) - dnx.at(i, 1) ) / 3.0; answer.at(1, 3 * i - 1) = answer.at(2, 3 * i - 1) = answer.at(3, 3 * i - 1) = ( dnx0.at(i, 2) - dnx.at(i, 2) ) / 3.0; answer.at(1, 3 * i - 0) = answer.at(2, 3 * i - 0) = answer.at(3, 3 * i - 0) = ( dnx0.at(i, 3) - dnx.at(i, 3) ) / 3.0; } // add B(gp) for ( i = 1; i <= 8; i++ ) { answer.at(1, 3 * i - 2) += dnx.at(i, 1); answer.at(2, 3 * i - 1) += dnx.at(i, 2); answer.at(3, 3 * i - 0) += dnx.at(i, 3); } for ( i = 1; i <= 8; i++ ) { answer.at(4, 3 * i - 1) += dnx.at(i, 3); answer.at(4, 3 * i - 0) += dnx.at(i, 2); answer.at(5, 3 * i - 2) += dnx.at(i, 3); answer.at(5, 3 * i - 0) += dnx.at(i, 1); answer.at(6, 3 * i - 2) += dnx.at(i, 2); answer.at(6, 3 * i - 1) += dnx.at(i, 1); } }
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 Structural3DElement :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) // Returns the [ 6 x (nno*3) ] strain-displacement matrix {B} of the receiver, eva- // luated at gp. // B matrix - 6 rows : epsilon-X, epsilon-Y, epsilon-Z, gamma-YZ, gamma-ZX, gamma-XY : { FEInterpolation *interp = this->giveInterpolation(); FloatMatrix dNdx; interp->evaldNdx( dNdx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); answer.resize(6, dNdx.giveNumberOfRows() * 3); answer.zero(); for ( int i = 1; i <= dNdx.giveNumberOfRows(); i++ ) { answer.at(1, 3 * i - 2) = dNdx.at(i, 1); answer.at(2, 3 * i - 1) = dNdx.at(i, 2); answer.at(3, 3 * i - 0) = dNdx.at(i, 3); answer.at(5, 3 * i - 2) = answer.at(4, 3 * i - 1) = dNdx.at(i, 3); answer.at(6, 3 * i - 2) = answer.at(4, 3 * i - 0) = dNdx.at(i, 2); answer.at(6, 3 * i - 1) = answer.at(5, 3 * i - 0) = dNdx.at(i, 1); } }
void PrescribedGradientBCWeak :: assembleGPContrib(SparseMtrx &answer, TimeStep *tStep, CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, TracSegArray &iEl, GaussPoint &iGP) { SpatialLocalizer *localizer = domain->giveSpatialLocalizer(); /////////////// // Gamma_plus FloatMatrix contrib; assembleTangentGPContributionNew(contrib, iEl, iGP, -1.0, iGP.giveGlobalCoordinates()); // Compute vector of traction unknowns FloatArray tracUnknowns; iEl.mFirstNode->giveUnknownVector(tracUnknowns, giveTracDofIDs(), VM_Total, tStep); IntArray trac_rows; iEl.giveTractionLocationArray(trac_rows, type, r_s); FloatArray dispElLocCoord, closestPoint; Element *dispEl = localizer->giveElementClosestToPoint(dispElLocCoord, closestPoint, iGP.giveGlobalCoordinates() ); IntArray disp_cols; dispEl->giveLocationArray(disp_cols, c_s); answer.assemble(trac_rows, disp_cols, contrib); FloatMatrix contribT; contribT.beTranspositionOf(contrib); answer.assemble(disp_cols, trac_rows, contribT); /////////////// // Gamma_minus contrib.clear(); FloatArray xMinus; this->giveMirroredPointOnGammaMinus(xMinus, iGP.giveGlobalCoordinates() ); assembleTangentGPContributionNew(contrib, iEl, iGP, 1.0, xMinus); // Compute vector of traction unknowns tracUnknowns.clear(); iEl.mFirstNode->giveUnknownVector(tracUnknowns, giveTracDofIDs(), VM_Total, tStep); trac_rows.clear(); iEl.giveTractionLocationArray(trac_rows, type, r_s); dispElLocCoord.clear(); closestPoint.clear(); dispEl = localizer->giveElementClosestToPoint(dispElLocCoord, closestPoint, xMinus ); disp_cols.clear(); dispEl->giveLocationArray(disp_cols, c_s); answer.assemble(trac_rows, disp_cols, contrib); contribT.clear(); contribT.beTranspositionOf(contrib); answer.assemble(disp_cols, trac_rows, contribT); // Assemble zeros on diagonal (required by PETSc solver) FloatMatrix KZero(1,1); KZero.zero(); for( int i : trac_rows) { answer.assemble(IntArray({i}), IntArray({i}), KZero); } }
void PrescribedGradientBCWeak :: computeField(FloatArray &sigma, TimeStep *tStep) { double Lx = mUC[0] - mLC[0]; double Ly = mUC[1] - mLC[1]; double dSize = Lx*Ly; // printf("dSize: %e\n", dSize); const int dim = domain->giveNumberOfSpatialDimensions(); FloatMatrix stressMatrix(dim, dim); for( auto *el: mpTracElNew ) { for ( GaussPoint *gp: *(el->mIntRule.get()) ) { // For now, assume piecewise constant approx FloatArray Ntrac = FloatArray { 1.0 }; // N-matrix FloatMatrix Nmat; Nmat.beNMatrixOf(Ntrac, dim); // Fetch global coordinate x const FloatArray &x = gp->giveGlobalCoordinates(); // Compute vector of traction unknowns FloatArray tracUnknowns; el->mFirstNode->giveUnknownVector(tracUnknowns, giveTracDofIDs(), VM_Total, tStep); FloatArray traction; traction.beProductOf(Nmat, tracUnknowns); FloatArray tmp; giveBoundaryCoordVector(tmp, x); FloatMatrix contrib; contrib.beDyadicProductOf(traction, tmp); double detJ = 0.5 * el->giveLength(); contrib.times( detJ * gp->giveWeight() ); for ( int m = 0; m < dim; m++ ) { for ( int n = 0; n < dim; n++ ) { stressMatrix(m, n) += contrib(m, n); } } } } if ( dim == 2 ) { sigma = { stressMatrix(0, 0), stressMatrix(1, 1), 0.0, 0.0, 0.0, 0.5*(stressMatrix(0, 1) + stressMatrix(1, 0)) }; } else { sigma.beVectorForm(stressMatrix); } sigma.times(1.0 / dSize); }
void MisesMatGrad :: giveInternalLength(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { answer.resize(1, 1); answer.at(1, 1) = L; }
void StructuralFE2Material :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { if ( useNumTangent ) { // Numerical tangent StructuralFE2MaterialStatus *status = static_cast<StructuralFE2MaterialStatus*>( this->giveStatus( gp ) ); double h = 1.0e-9; const FloatArray &epsRed = status->giveTempStrainVector(); FloatArray eps; StructuralMaterial::giveFullSymVectorForm(eps, epsRed, gp->giveMaterialMode() ); int dim = eps.giveSize(); answer.resize(dim, dim); answer.zero(); FloatArray sig, sigPert, epsPert; for(int i = 1; i <= dim; i++) { // Add a small perturbation to the strain epsPert = eps; epsPert.at(i) += h; giveRealStressVector_3d(sigPert, gp, epsPert, tStep); answer.setColumn(sigPert, i); } giveRealStressVector_3d(sig, gp, eps, tStep); for(int i = 1; i <= dim; i++) { for(int j = 1; j <= dim; j++) { answer.at(j,i) -= sig.at(j); answer.at(j,i) /= h; } } } else { StructuralFE2MaterialStatus *ms = static_cast< StructuralFE2MaterialStatus * >( this->giveStatus(gp) ); ms->computeTangent(tStep); const FloatMatrix &ans9 = ms->giveTangent(); // Compute the (minor) symmetrized tangent: answer.resize(6, 6); for ( int i = 0; i < 6; ++i ) { for ( int j = 0; j < 6; ++j ) { answer(i, j) = ans9(i, j); } } for ( int i = 0; i < 6; ++i ) { for ( int j = 6; j < 9; ++j ) { answer(i, j-3) += ans9(i, j); answer(j-3, i) += ans9(j, i); } } for ( int i = 6; i < 9; ++i ) { for ( int j = 6; j < 9; ++j ) { answer(j-3, i-3) += ans9(j, i); } } for ( int i = 0; i < 6; ++i ) { for ( int j = 3; j < 6; ++j ) { answer(j, i) *= 0.5; answer(i, j) *= 0.5; } } #if 0 // Numerical ATS for debugging FloatMatrix numericalATS(6, 6); FloatArray dsig; // Note! We need a copy of the temp strain, since the pertubations might change it. FloatArray tempStrain = ms->giveTempStrainVector(); FloatArray sig, strain, sigPert; giveRealStressVector_3d(sig, gp, tempStrain, tStep); double hh = 1e-6; for ( int k = 1; k <= 6; ++k ) { strain = tempStrain; strain.at(k) += hh; giveRealStressVector_3d(sigPert, gp, strain, tStep); dsig.beDifferenceOf(sigPert, sig); numericalATS.setColumn(dsig, k); } numericalATS.times(1. / hh); giveRealStressVector_3d(sig, gp, tempStrain, tStep); // Reset //answer.printYourself("Analytical deviatoric tangent"); //numericalATS.printYourself("Numerical deviatoric tangent"); numericalATS.subtract(answer); double norm = numericalATS.computeFrobeniusNorm(); if ( norm > answer.computeFrobeniusNorm() * 1e-3 && norm > 0.0 ) { OOFEM_ERROR("Error in deviatoric tangent"); } #endif } }
void TrabBone3D :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { double tempDam, beta, tempKappa, kappa; FloatArray tempEffectiveStress, tempTensor2, prodTensor, plasFlowDirec; FloatMatrix elasticity, compliance, SSaTensor, secondTerm, thirdTerm, tangentMatrix; TrabBone3DStatus *status = static_cast< TrabBone3DStatus * >( this->giveStatus(gp) ); if ( mode == ElasticStiffness ) { this->constructAnisoComplTensor(compliance); //this->constructAnisoStiffnessTensor(elasticity); elasticity.beInverseOf(compliance); answer = elasticity; } else if ( mode == SecantStiffness ) { if ( printflag ) { printf("secant\n"); } this->constructAnisoStiffnessTensor(elasticity); this->constructAnisoComplTensor(compliance); elasticity.beInverseOf(compliance); tempDam = status->giveTempDam(); answer = elasticity; answer.times(1.0 - tempDam); } else if ( mode == TangentStiffness ) { kappa = status->giveKappa(); tempKappa = status->giveTempKappa(); tempDam = status->giveTempDam(); if ( tempKappa > kappa ) { // plastic loading // Imports tempEffectiveStress = status->giveTempEffectiveStress(); plasFlowDirec = status->givePlasFlowDirec(); SSaTensor = status->giveSSaTensor(); beta = status->giveBeta(); // Construction of the dyadic product tensor prodTensor.beTProductOf(SSaTensor, plasFlowDirec); // Construction of the tangent stiffness third term thirdTerm.beDyadicProductOf(tempEffectiveStress, prodTensor); thirdTerm.times( -expDam * critDam * exp(-expDam * tempKappa) ); thirdTerm.times(1. / beta); // Construction of the tangent stiffness second term tempTensor2.beProductOf(SSaTensor, plasFlowDirec); secondTerm.beDyadicProductOf(tempTensor2, prodTensor); secondTerm.times(-( 1.0 - tempDam ) / beta); // Construction of the tangent stiffness tangentMatrix = SSaTensor; tangentMatrix.times(1.0 - tempDam); tangentMatrix.add(secondTerm); tangentMatrix.add(thirdTerm); answer = tangentMatrix; //answer.beTranspositionOf(tangentMatrix); } else { // elastic behavior with damage // Construction of the secant stiffness this->constructAnisoComplTensor(compliance); elasticity.beInverseOf(compliance); //this->constructAnisoStiffnessTensor(elasticity); answer = elasticity; answer.times(1.0 - tempDam); } double g = status->giveDensG(); if ( g <= 0. ) { double factor = gammaL0 * pow(rho, rL) + gammaP0 *pow(rho, rP) * ( tDens - 1 ) * pow(g, tDens - 2); // printf("densification"); tangentMatrix.resize(6, 6); tangentMatrix.zero(); tangentMatrix.at(1, 1) = tangentMatrix.at(1, 2) = tangentMatrix.at(1, 3) = 1; tangentMatrix.at(2, 1) = tangentMatrix.at(2, 2) = tangentMatrix.at(2, 3) = 1; tangentMatrix.at(3, 1) = tangentMatrix.at(3, 2) = tangentMatrix.at(3, 3) = 1; tangentMatrix.times(factor); answer.add(tangentMatrix); } } status->setSmtrx(answer); }
void LIBeam3dNL :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { int i, j, k; double s1, s2; FloatMatrix d, x, xt(12, 6), dxt, sn, sm, sxd, y; FloatArray n(3), m(3), xd(3), TotalStressVector; IntegrationRule *iRule = integrationRulesArray [ giveDefaultIntegrationRule() ]; GaussPoint *gp = iRule->getIntegrationPoint(0); answer.resize( this->computeNumberOfDofs(EID_MomentumBalance), this->computeNumberOfDofs(EID_MomentumBalance) ); answer.zero(); // linear part this->updateTempTriad(tStep); // update temp triad this->computeXMtrx(x, tStep); xt.zero(); for ( i = 1; i <= 12; i++ ) { for ( j = 1; j <= 3; j++ ) { for ( k = 1; k <= 3; k++ ) { // compute x*Tbar, taking into account sparsity of Tbar xt.at(i, j) += x.at(i, k) * tempTc.at(k, j); xt.at(i, j + 3) += x.at(i, k + 3) * tempTc.at(k, j); } } } this->computeConstitutiveMatrixAt(d, rMode, gp, tStep); dxt.beProductTOf(d, xt); answer.beProductOf(xt, dxt); answer.times(1. / this->l0); // geometric stiffness ks = ks1+ks2 // ks1 this->computeStressVector(TotalStressVector, gp, tStep); for ( i = 1; i <= 3; i++ ) { s1 = s2 = 0.0; for ( j = 1; j <= 3; j++ ) { s1 += tempTc.at(i, j) * TotalStressVector.at(j); s2 += tempTc.at(i, j) * TotalStressVector.at(j + 3); } n.at(i) = s1; m.at(i) = s2; } this->computeSMtrx(sn, n); this->computeSMtrx(sm, m); for ( i = 1; i <= 3; i++ ) { for ( j = 1; j <= 3; j++ ) { answer.at(i, j + 3) += sn.at(i, j); answer.at(i, j + 9) += sn.at(i, j); answer.at(i + 3, j + 3) += sm.at(i, j); answer.at(i + 3, j + 9) += sm.at(i, j); answer.at(i + 6, j + 3) -= sn.at(i, j); answer.at(i + 6, j + 9) -= sn.at(i, j); answer.at(i + 9, j + 3) -= sm.at(i, j); answer.at(i + 9, j + 9) -= sm.at(i, j); } } // ks2 this->computeXdVector(xd, tStep); this->computeSMtrx(sxd, xd); y.beProductOf(sxd, sn); y.times(0.5); for ( i = 1; i <= 3; i++ ) { for ( j = 1; j <= 3; j++ ) { answer.at(i + 3, j) -= sn.at(i, j); answer.at(i + 3, j + 3) += y.at(i, j); answer.at(i + 3, j + 6) += sn.at(i, j); answer.at(i + 3, j + 9) += y.at(i, j); answer.at(i + 9, j) -= sn.at(i, j); answer.at(i + 9, j + 3) += y.at(i, j); answer.at(i + 9, j + 6) += sn.at(i, j); answer.at(i + 9, j + 9) += y.at(i, j); } } }
void Structural3DElement :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) // Returns the [ 9 x (nno * 3) ] displacement gradient matrix {BH} of the receiver, // evaluated at gp. // BH matrix - 9 rows : du/dx, dv/dy, dw/dz, dv/dz, du/dz, du/dy, dw/dy, dw/dx, dv/dx { FEInterpolation *interp = this->giveInterpolation(); FloatMatrix dNdx; interp->evaldNdx( dNdx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); answer.resize(9, dNdx.giveNumberOfRows() * 3); answer.zero(); for ( int i = 1; i <= dNdx.giveNumberOfRows(); i++ ) { answer.at(1, 3 * i - 2) = dNdx.at(i, 1); // du/dx answer.at(2, 3 * i - 1) = dNdx.at(i, 2); // dv/dy answer.at(3, 3 * i - 0) = dNdx.at(i, 3); // dw/dz answer.at(4, 3 * i - 1) = dNdx.at(i, 3); // dv/dz answer.at(7, 3 * i - 0) = dNdx.at(i, 2); // dw/dy answer.at(5, 3 * i - 2) = dNdx.at(i, 3); // du/dz answer.at(8, 3 * i - 0) = dNdx.at(i, 1); // dw/dx answer.at(6, 3 * i - 2) = dNdx.at(i, 2); // du/dy answer.at(9, 3 * i - 1) = dNdx.at(i, 1); // dv/dx } }
void LIBeam3dNL :: computeNmatrixAt(GaussPoint *aGaussPoint, FloatMatrix &answer) // Returns the displacement interpolation matrix {N} of the receiver, eva- // luated at aGaussPoint. { double ksi, n1, n2; ksi = aGaussPoint->giveCoordinate(1); n1 = ( 1. - ksi ) * 0.5; n2 = ( 1. + ksi ) * 0.5; answer.resize(6, 12); answer.zero(); // u answer.at(1, 1) = n1; answer.at(1, 7) = n2; // v answer.at(2, 2) = n1; answer.at(2, 8) = n2; // w answer.at(3, 3) = n1; answer.at(3, 9) = n2; // fi_x answer.at(4, 4) = n1; answer.at(4, 10) = n2; // fi_y answer.at(5, 5) = n1; answer.at(5, 11) = n2; // fi_z answer.at(6, 6) = n1; answer.at(6, 12) = n2; }
void J2Mat :: computeReducedSSGradientMatrix(FloatMatrix &gradientMatrix, int isurf, GaussPoint *gp, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVars) { int i, j, size; int imask, jmask; FloatArray helpVector, backStress, df(6); IntArray mask; double f, f32, f12, ax, ay, az; StructuralMaterial :: giveInvertedVoigtVectorMask(mask, gp->giveMaterialMode() ); size = StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ); gradientMatrix.resize(size, size); gradientMatrix.zero(); if ( fullStressVector.giveSize() != 0 ) { /* kinematic hardening variables first */ if ( this->kinematicHardeningFlag ) { this->giveStressBackVector(backStress, gp, strainSpaceHardeningVars); helpVector = fullStressVector; helpVector.add(backStress); } else { helpVector = fullStressVector; } f = this->computeJ2InvariantAt(helpVector); f12 = pow(f, 1. / 2.); f32 = pow(f, 3. / 2.); ax = helpVector.at(1); ay = helpVector.at(2); az = helpVector.at(3); df.at(1) = ( 2. / 3. ) * ax - ( 1. / 3. ) * ay - ( 1. / 3. ) * az; df.at(2) = ( 2. / 3. ) * ay - ( 1. / 3. ) * ax - ( 1. / 3. ) * az; df.at(3) = ( 2. / 3. ) * az - ( 1. / 3. ) * ay - ( 1. / 3. ) * ax; df.at(4) = 2. * helpVector.at(4); df.at(5) = 2. * helpVector.at(5); df.at(6) = 2. * helpVector.at(6); for ( i = 1; i <= 3; i++ ) { if ( ( imask = mask.at(i) ) == 0 ) { continue; } for ( j = i; j <= 3; j++ ) { if ( ( jmask = mask.at(j) ) == 0 ) { continue; } if ( i == j ) { gradientMatrix.at(imask, jmask) = -( 1. / 4. ) * ( 1. / f32 ) * df.at(i) * df.at(j) + 0.5 * ( 1. / f12 ) * ( 4. / 6 ); } else { gradientMatrix.at(imask, jmask) = -( 1. / 4. ) * ( 1. / f32 ) * df.at(i) * df.at(j) + 0.5 * ( 1. / f12 ) * ( -2. / 6 ); gradientMatrix.at(jmask, imask) = -( 1. / 4. ) * ( 1. / f32 ) * df.at(i) * df.at(j) + 0.5 * ( 1. / f12 ) * ( -2. / 6 ); } } } for ( i = 1; i <= 3; i++ ) { if ( ( imask = mask.at(i) ) == 0 ) { continue; } for ( j = 4; j <= 6; j++ ) { if ( ( jmask = mask.at(j) ) == 0 ) { continue; } gradientMatrix.at(imask, jmask) = -( 1. / 4. ) * ( 1. / f32 ) * df.at(i) * df.at(j); gradientMatrix.at(jmask, imask) = -( 1. / 4. ) * ( 1. / f32 ) * df.at(i) * df.at(j); } } for ( i = 4; i <= 6; i++ ) { if ( ( imask = mask.at(i) ) == 0 ) { continue; } for ( j = i; j <= 6; j++ ) { if ( ( jmask = mask.at(j) ) == 0 ) { continue; } if ( i == j ) { gradientMatrix.at(imask, jmask) = -( 1. / 4. ) * ( 1. / f32 ) * df.at(i) * df.at(j) + 0.5 * ( 1. / f12 ) * 2.; } else { gradientMatrix.at(imask, jmask) = -( 1. / 4. ) * ( 1. / f32 ) * df.at(i) * df.at(j); gradientMatrix.at(jmask, imask) = -( 1. / 4. ) * ( 1. / f32 ) * df.at(i) * df.at(j); } } } } }
void PrescribedGradientBCNeumann :: integrateTangent(FloatMatrix &oTangent, Element *e, int iBndIndex) { FloatArray normal, n; FloatMatrix nMatrix, E_n; FloatMatrix contrib; Domain *domain = e->giveDomain(); XfemElementInterface *xfemElInt = dynamic_cast< XfemElementInterface * >( e ); FEInterpolation *interp = e->giveInterpolation(); // Geometry interpolation int nsd = e->giveDomain()->giveNumberOfSpatialDimensions(); // Interpolation order int order = interp->giveInterpolationOrder(); IntegrationRule *ir = NULL; IntArray edgeNodes; FEInterpolation2d *interp2d = dynamic_cast< FEInterpolation2d * >( interp ); if ( interp2d == NULL ) { OOFEM_ERROR("failed to cast to FEInterpolation2d.") } interp2d->computeLocalEdgeMapping(edgeNodes, iBndIndex); const FloatArray &xS = * ( e->giveDofManager( edgeNodes.at(1) )->giveCoordinates() ); const FloatArray &xE = * ( e->giveDofManager( edgeNodes.at( edgeNodes.giveSize() ) )->giveCoordinates() ); if ( xfemElInt != NULL && domain->hasXfemManager() ) { std :: vector< Line >segments; std :: vector< FloatArray >intersecPoints; xfemElInt->partitionEdgeSegment(iBndIndex, segments, intersecPoints); MaterialMode matMode = e->giveMaterialMode(); ir = new DiscontinuousSegmentIntegrationRule(1, e, segments, xS, xE); int numPointsPerSeg = 1; ir->SetUpPointsOnLine(numPointsPerSeg, matMode); } else { ir = interp->giveBoundaryIntegrationRule(order, iBndIndex); } oTangent.clear(); for ( GaussPoint *gp: *ir ) { FloatArray &lcoords = * gp->giveNaturalCoordinates(); FEIElementGeometryWrapper cellgeo(e); // Evaluate the normal; double detJ = interp->boundaryEvalNormal(normal, iBndIndex, lcoords, cellgeo); interp->boundaryEvalN(n, iBndIndex, lcoords, cellgeo); // If cracks cross the edge, special treatment is necessary. // Exploit the XfemElementInterface to minimize duplication of code. if ( xfemElInt != NULL && domain->hasXfemManager() ) { // Compute global coordinates of Gauss point FloatArray globalCoord; interp->boundaryLocal2Global(globalCoord, iBndIndex, lcoords, cellgeo); // Compute local coordinates on the element FloatArray locCoord; e->computeLocalCoordinates(locCoord, globalCoord); xfemElInt->XfemElementInterface_createEnrNmatrixAt(nMatrix, locCoord, * e, false); } else { // Evaluate the velocity/displacement coefficients nMatrix.beNMatrixOf(n, nsd); } if ( nsd == 3 ) { OOFEM_ERROR("not implemented for nsd == 3.") } else if ( nsd == 2 ) { E_n.resize(4, 2); E_n.at(1, 1) = normal.at(1); E_n.at(1, 2) = 0.0; E_n.at(2, 1) = 0.0; E_n.at(2, 2) = normal.at(2); E_n.at(3, 1) = normal.at(2); E_n.at(3, 2) = 0.0; E_n.at(4, 1) = 0.0; E_n.at(4, 2) = normal.at(1); } else { E_n.clear(); } contrib.beProductOf(E_n, nMatrix); oTangent.add(detJ * gp->giveWeight(), contrib); } delete ir; }
void InterfaceElement3dTrLin :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) // // Returns linear part of geometrical equations of the receiver at gp. // Returns the linear part of the B matrix // { FloatArray n; this->interpolation.evalN( n, * gp->giveCoordinates(), FEIElementGeometryWrapper(this) ); answer.resize(3, 18); answer.zero(); answer.at(1, 10) = answer.at(2, 11) = answer.at(3, 12) = n.at(1); answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = -n.at(1); answer.at(1, 13) = answer.at(2, 14) = answer.at(3, 15) = n.at(2); answer.at(1, 4) = answer.at(2, 5) = answer.at(3, 6) = -n.at(2); answer.at(1, 16) = answer.at(2, 17) = answer.at(3, 18) = n.at(3); answer.at(1, 7) = answer.at(2, 8) = answer.at(3, 9) = -n.at(3); }
void Lattice2d :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) // Returns the strain matrix of the receiver. { double l = this->giveLength(); double x1, x2, y1, y2, xp, yp; //Coordinates of the nodes x1 = this->giveNode(1)->giveCoordinate(1); y1 = this->giveNode(1)->giveCoordinate(2); x2 = this->giveNode(2)->giveCoordinate(1); y2 = this->giveNode(2)->giveCoordinate(2); xp = this->gpCoords.at(1); yp = this->gpCoords.at(2); double ecc; double areaHelp = 0.5 * ( x1 * y2 + x2 * yp + xp * y1 - ( xp * y2 + yp * x1 + x2 * y1 ) ); ecc = 2 * areaHelp / l; // Assemble Bmatrix (used to compute strains and rotations answer.resize(3, 6); answer.zero(); answer.at(1, 1) = -1.; answer.at(1, 2) = 0.; answer.at(1, 3) = ecc; answer.at(1, 4) = 1.; answer.at(1, 5) = 0.; answer.at(1, 6) = -ecc; answer.at(2, 1) = 0.; answer.at(2, 2) = -1.; answer.at(2, 3) = -l / 2.; answer.at(2, 4) = 0.; answer.at(2, 5) = 1.; answer.at(2, 6) = -l / 2.; answer.at(3, 1) = 0.; answer.at(3, 2) = 0.; answer.at(3, 3) = -this->width / sqrt(12.); answer.at(3, 4) = 0.; answer.at(3, 5) = 0.; answer.at(3, 6) = this->width / sqrt(12.); answer.times(1. / l); }
void PlasticMaterial :: computeConsistentModuli(FloatMatrix &answer, GaussPoint *gp, FloatMatrix &elasticModuliInverse, FloatMatrix &hardeningModuliInverse, double Gamma, const FloatArray &fullStressVector, const FloatArray &fullStressSpaceHardeningVars) { /* returns consistent moduli in reduced form. * Note: elasticModuli and hardeningModuli will be inverted * * stressVector in full form */ FloatMatrix gradientMatrix; FloatMatrix helpInverse; int isize, size; isize = elasticModuliInverse.giveNumberOfRows(); if ( this->hasHardening() ) { size = isize + hardeningModuliInverse.giveNumberOfRows(); } else { size = isize; } // ask gradientMatrix this->computeReducedGradientMatrix(gradientMatrix, gp, fullStressVector, fullStressSpaceHardeningVars); // assemble consistent moduli helpInverse.resize(size, size); for ( int i = 1; i <= isize; i++ ) { for ( int j = 1; j <= isize; j++ ) { helpInverse.at(i, j) = elasticModuliInverse.at(i, j) + Gamma *gradientMatrix.at(i, j); } for ( int j = isize + 1; j <= size; j++ ) { helpInverse.at(i, j) = Gamma * gradientMatrix.at(i, j); } } for ( int i = isize + 1; i <= size; i++ ) { for ( int j = 1; j <= isize; j++ ) { helpInverse.at(i, j) = Gamma * gradientMatrix.at(i, j); } for ( int j = isize + 1; j <= size; j++ ) { helpInverse.at(i, j) = hardeningModuliInverse.at(i - isize, j - isize) + Gamma *gradientMatrix.at(i, j); } } answer.beInverseOf(helpInverse); }
void TrabBoneNL3D :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { TrabBoneNL3DStatus *nlStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(gp) ); double tempDam, beta, nlKappa; FloatArray tempEffectiveStress, tempTensor2, prodTensor, plasFlowDirec; FloatMatrix elasticity, compliance, SSaTensor, secondTerm, thirdTerm, tangentMatrix; if ( mode == ElasticStiffness ) { this->constructAnisoComplTensor(compliance); elasticity.beInverseOf(compliance); answer = elasticity; } else if ( mode == SecantStiffness ) { this->constructAnisoComplTensor(compliance); elasticity.beInverseOf(compliance); tempDam = nlStatus->giveTempDam(); answer = elasticity; answer.times(1.0 - tempDam); } else if ( mode == TangentStiffness ) { double kappa = nlStatus->giveKappa(); double tempKappa = nlStatus->giveTempKappa(); double dKappa = tempKappa - kappa; if ( dKappa < 10.e-9 ) { dKappa = 0; } if ( dKappa > 0.0 ) { // Imports tempEffectiveStress = nlStatus->giveTempEffectiveStress(); this->computeCumPlastStrain(nlKappa, gp, tStep); tempDam = nlStatus->giveTempDam(); double dam = nlStatus->giveDam(); plasFlowDirec = nlStatus->givePlasFlowDirec(); SSaTensor = nlStatus->giveSSaTensor(); beta = nlStatus->giveBeta(); // Construction of the dyadic product tensor prodTensor.beTProductOf(SSaTensor, plasFlowDirec); // Construction of the tangent stiffness third term if ( tempDam - dam > 0 ) { thirdTerm.beDyadicProductOf(tempEffectiveStress, prodTensor); thirdTerm.times(-expDam * critDam * exp(-expDam * nlKappa) * ( 1.0 - mParam ) / beta); } else { thirdTerm.resize(6, 6); } // Construction of the tangent stiffness second term tempTensor2.beProductOf(SSaTensor, plasFlowDirec); secondTerm.beDyadicProductOf(tempTensor2, prodTensor); secondTerm.times(-( 1.0 - tempDam ) / beta); // Construction of the tangent stiffness tangentMatrix = SSaTensor; tangentMatrix.times(1.0 - tempDam); tangentMatrix.add(secondTerm); tangentMatrix.add(thirdTerm); answer = tangentMatrix; } else { // Import of state variables tempDam = nlStatus->giveTempDam(); // Construction of the tangent stiffness this->constructAnisoComplTensor(compliance); elasticity.beInverseOf(compliance); answer = elasticity; answer.times(1.0 - tempDam); } } nlStatus->setSmtrx(answer); }
void QTRSpace :: computeBmatrixAt(GaussPoint *aGaussPoint, FloatMatrix &answer, int li, int ui) // Returns the [6x30] strain-displacement matrix {B} of the receiver, eva- // luated at aGaussPoint. // B matrix - 6 rows : epsilon-X, epsilon-Y, epsilon-Z, gamma-YZ, gamma-ZX, gamma-XY : { FloatMatrix dnx; this->interpolation.evaldNdx(dnx, * aGaussPoint->giveCoordinates(), FEIElementGeometryWrapper(this)); answer.resize(6, 30); answer.zero(); for ( int i = 1; i <= 10; i++ ) { answer.at(1, 3 * i - 2) = dnx.at(1, i); answer.at(2, 3 * i - 1) = dnx.at(2, i); answer.at(3, 3 * i - 0) = dnx.at(3, i); answer.at(4, 3 * i - 1) = dnx.at(3, i); answer.at(4, 3 * i - 0) = dnx.at(2, i); answer.at(5, 3 * i - 2) = dnx.at(3, i); answer.at(5, 3 * i - 0) = dnx.at(1, i); answer.at(6, 3 * i - 2) = dnx.at(2, i); answer.at(6, 3 * i - 1) = dnx.at(1, i); } }
void Quad1MindlinShell3D :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) { FloatArray n, ns; FloatMatrix dn, dns; const FloatArray &localCoords = gp->giveNaturalCoordinates(); this->interp.evaldNdx( dn, localCoords, FEIVertexListGeometryWrapper(lnodes) ); this->interp.evalN( n, localCoords, FEIVoidCellGeometry() ); answer.resize(8, 4 * 5); answer.zero(); // enforce one-point reduced integration if requested if ( this->reducedIntegrationFlag ) { FloatArray lc(2); lc.zero(); // set to element center coordinates this->interp.evaldNdx( dns, lc, FEIVertexListGeometryWrapper(lnodes) ); this->interp.evalN( ns, lc, FEIVoidCellGeometry() ); } else { dns = dn; ns = n; } // Note: This is just 5 dofs (sixth column is all zero, torsional stiffness handled separately.) for ( int i = 0; i < 4; ++i ) { ///@todo Check the rows for both parts here, to be consistent with _3dShell material definition // Part related to the membrane (columns represent coefficients for D_u, D_v) answer(0, 0 + i * 5) = dn(i, 0);//eps_x = du/dx answer(1, 1 + i * 5) = dn(i, 1);//eps_y = dv/dy answer(2, 0 + i * 5) = dn(i, 1);//gamma_xy = du/dy+dv/dx answer(2, 1 + i * 5) = dn(i, 0); // Part related to the plate (columns represent the dofs D_w, R_u, R_v) ///@todo Check sign here answer(3 + 0, 2 + 2 + i * 5) = dn(i, 0);// kappa_x = d(fi_y)/dx answer(3 + 1, 2 + 1 + i * 5) =-dn(i, 1);// kappa_y = -d(fi_x)/dy answer(3 + 2, 2 + 2 + i * 5) = dn(i, 1);// kappa_xy=d(fi_y)/dy-d(fi_x)/dx answer(3 + 2, 2 + 1 + i * 5) =-dn(i, 0); // shear strains answer(3 + 3, 2 + 0 + i * 5) = dns(i, 0);// gamma_xz = fi_y+dw/dx answer(3 + 3, 2 + 2 + i * 5) = ns(i); answer(3 + 4, 2 + 0 + i * 5) = dns(i, 1);// gamma_yz = -fi_x+dw/dy answer(3 + 4, 2 + 1 + i * 5) = -ns(i); } #if 0 // Experimental MITC4 support. // Based on "Short communication A four-node plate bending element based on mindling/reissner plate theory and a mixed interpolation" // KJ Bathe, E Dvorkin double x1, x2, x3, x4; double y1, y2, y3, y4; double Ax, Bx, Cx, Ay, By, Cy; double r = localCoords[0]; double s = localCoords[1]; x1 = lnodes[0][0]; x2 = lnodes[1][0]; x3 = lnodes[2][0]; x4 = lnodes[3][0]; y1 = lnodes[0][1]; y2 = lnodes[1][1]; y3 = lnodes[2][1]; y4 = lnodes[3][1]; Ax = x1 - x2 - x3 + x4; Bx = x1 - x2 + x3 - x4; Cx = x1 + x2 - x3 - x4; Ay = y1 - y2 - y3 + y4; By = y1 - y2 + y3 - y4; Cy = y1 + y2 - y3 - y4; FloatMatrix jac; this->interp.giveJacobianMatrixAt(jac, localCoords, FEIVertexListGeometryWrapper(lnodes) ); double detJ = jac.giveDeterminant(); double rz = sqrt( sqr(Cx + r*Bx) + sqr(Cy + r*By)) / ( 16 * detJ ); double sz = sqrt( sqr(Ax + s*Bx) + sqr(Ay + s*By)) / ( 16 * detJ ); // TODO: Not sure about this part (the reference is not explicit about these angles. / Mikael // Not sure about the transpose either. OOFEM_WARNING("The MITC4 implementation isn't verified yet. Highly experimental"); FloatArray dxdr = {jac(0,0), jac(0,1)}; dxdr.normalize(); FloatArray dxds = {jac(1,0), jac(1,1)}; dxds.normalize(); double c_b = dxdr(0); //cos(beta); double s_b = dxdr(1); //sin(beta); double c_a = dxds(0); //cos(alpha); double s_a = dxds(1); //sin(alpha); // gamma_xz = "fi_y+dw/dx" in standard formulation answer(6, 2 + 5*0) = rz * s_b * ( (1+s)) - sz * s_a * ( (1+r)); answer(6, 2 + 5*1) = rz * s_b * (-(1+s)) - sz * s_a * ( (1-r)); answer(6, 2 + 5*2) = rz * s_b * (-(1-s)) - sz * s_a * (-(1-r)); answer(6, 2 + 5*3) = rz * s_b * ( (1-s)) - sz * s_a * (-(1+r)); answer(6, 3 + 5*0) = rz * s_b * (y2-y1) * 0.5 * (1+s) - sz * s_a * (y4-y1) * 0.5 * (1+r); // tx1 answer(6, 4 + 5*0) = rz * s_b * (x1-x2) * 0.5 * (1+s) - sz * s_a * (x1-x4) * 0.5 * (1+r); // ty1 answer(6, 3 + 5*1) = rz * s_b * (y2-y1) * 0.5 * (1+s) - sz * s_a * (y3-x2) * 0.5 * (1+r); // tx2 answer(6, 4 + 5*1) = rz * s_b * (x1-x2) * 0.5 * (1+s) - sz * s_a * (x2-x3) * 0.5 * (1+r); // ty2 answer(6, 3 + 5*2) = rz * s_b * (y3-y4) * 0.5 * (1-s) - sz * s_a * (y3-y2) * 0.5 * (1-r); // tx3 answer(6, 4 + 5*2) = rz * s_b * (x4-x3) * 0.5 * (1-s) - sz * s_a * (x2-x3) * 0.5 * (1-r); // ty3 answer(6, 3 + 5*3) = rz * s_b * (y3-y4) * 0.5 * (1-s) - sz * s_a * (y4-y1) * 0.5 * (1-r); // tx4 answer(6, 4 + 5*3) = rz * s_b * (x4-x3) * 0.5 * (1-s) - sz * s_a * (x1-x4) * 0.5 * (1-r); // ty4 // gamma_yz = -fi_x+dw/dy in standard formulation answer(7, 2 + 5*0) = - rz * c_b * ( (1+s)) + sz * c_a * ( (1+r)); answer(7, 2 + 5*1) = - rz * c_b * (-(1+s)) + sz * c_a * ( (1-r)); answer(7, 2 + 5*2) = - rz * c_b * (-(1-s)) + sz * c_a * (-(1-r)); answer(7, 2 + 5*3) = - rz * c_b * ( (1-s)) + sz * c_a * (-(1+r)); answer(7, 3 + 5*0) = - rz * c_b * (y2-y1) * 0.5 * (1+s) + sz * c_a * (y4-y1) * 0.5 * (1+r); // tx1 answer(7, 4 + 5*0) = - rz * c_b * (x1-x2) * 0.5 * (1+s) + sz * c_a * (x1-x4) * 0.5 * (1+r); // ty1 answer(7, 3 + 5*1) = - rz * c_b * (y2-y1) * 0.5 * (1+s) + sz * c_a * (y3-x2) * 0.5 * (1+r); // tx2 answer(7, 4 + 5*1) = - rz * c_b * (x1-x2) * 0.5 * (1+s) + sz * c_a * (x2-x3) * 0.5 * (1+r); // ty2 answer(7, 3 + 5*2) = - rz * c_b * (y3-y4) * 0.5 * (1-s) + sz * c_a * (y3-y2) * 0.5 * (1-r); // tx3 answer(7, 4 + 5*2) = - rz * c_b * (x4-x3) * 0.5 * (1-s) + sz * c_a * (x2-x3) * 0.5 * (1-r); // ty3 answer(7, 3 + 5*3) = - rz * c_b * (y3-y4) * 0.5 * (1-s) + sz * c_a * (y4-y1) * 0.5 * (1-r); // tx4 answer(7, 4 + 5*3) = - rz * c_b * (x4-x3) * 0.5 * (1-s) + sz * c_a * (x1-x4) * 0.5 * (1-r); // ty4 #endif }
void QTRSpace :: computeBHmatrixAt(GaussPoint *aGaussPoint, FloatMatrix &answer) { FloatMatrix dnx; this->interpolation.evaldNdx(dnx, * aGaussPoint->giveCoordinates(), FEIElementGeometryWrapper(this)); answer.resize(9, 30); answer.zero(); for ( int i = 1; i <= dnx.giveNumberOfRows(); i++ ) { answer.at(1, 3 * i - 2) = dnx.at(i, 1); // du/dx answer.at(2, 3 * i - 1) = dnx.at(i, 2); // dv/dy answer.at(3, 3 * i - 0) = dnx.at(i, 3); // dw/dz answer.at(4, 3 * i - 1) = dnx.at(i, 3); // dv/dz answer.at(7, 3 * i - 0) = dnx.at(i, 2); // dw/dy answer.at(5, 3 * i - 2) = dnx.at(i, 3); // du/dz answer.at(8, 3 * i - 0) = dnx.at(i, 1); // dw/dx answer.at(6, 3 * i - 2) = dnx.at(i, 2); // du/dy answer.at(9, 3 * i - 1) = dnx.at(i, 1); // dv/dx } }
NM_Status InverseIteration :: solve(SparseMtrx &a, SparseMtrx &b, FloatArray &_eigv, FloatMatrix &_r, double rtol, int nroot) { FILE *outStream; if ( a.giveNumberOfColumns() != b.giveNumberOfColumns() ) { OOFEM_ERROR("matrices size mismatch"); } SparseLinearSystemNM *solver = GiveClassFactory().createSparseLinSolver(ST_Direct, domain, engngModel); int nn = a.giveNumberOfColumns(); int nc = min(2 * nroot, nroot + 8); nc = min(nc, nn); //// control of diagonal zeroes in mass matrix, to be avoided //int i; //for (i = 1; i <= nn; i++) { // if (b.at(i, i) == 0) { // b.at(i, i) = 1.0e-12; // } //} FloatArray w(nc), ww(nc), t; std :: vector< FloatArray > z(nc, nn), zz(nc, nn), x(nc, nn); outStream = domain->giveEngngModel()->giveOutputStream(); /* initial setting */ #if 0 ww.add(1.0); for ( int j = 0; j < nc; j++ ) { z[j].add(1.0); } #else { FloatArray ad(nn), bd(nn); for (int i = 1; i <= nn; i++) { ad.at(i) = fabs(a.at(i, i)); bd.at(i) = fabs(b.at(i, i)); } IntArray order; order.enumerate(nn); std::sort(order.begin(), order.end(), [&ad, &bd](int a, int b) { return bd.at(a) * ad.at(b) > bd.at(b) * ad.at(a); }); for (int i = 0; i < nc; i++) { x[i].at(order[i]) = 1.0; b.times(x[i], z[i]); ww.at(i + 1) = z[i].dotProduct(x[i]); } } #endif int it; for ( it = 0; it < nitem; it++ ) { /* copy zz=z */ for ( int j = 0; j < nc; j++ ) { zz[j] = z[j]; } /* solve matrix equation K.X = M.X */ for ( int j = 0; j < nc; j++ ) { solver->solve(a, z[j], x[j]); } /* evaluation of Rayleigh quotients */ for ( int j = 0; j < nc; j++ ) { w.at(j + 1) = zz[j].dotProduct(x[j]); } for ( int j = 0; j < nc; j++ ) { b.times(x[j], z[j]); } for ( int j = 0; j < nc; j++ ) { w.at(j + 1) /= z[j].dotProduct(x[j]); } /* check convergence */ int ac = 0; for ( int j = 1; j <= nc; j++ ) { if ( fabs( ww.at(j) - w.at(j) ) <= fabs( w.at(j) * rtol ) ) { ac++; } ww.at(j) = w.at(j); } //printf ("\n iteration %d %d",it,ac); //w.printYourself(); /* Gramm-Schmidt ortogonalization */ for ( int j = 0; j < nc; j++ ) { if ( j != 0 ) { b.times(x[j], t); } for ( int ii = 0; ii < j; ii++ ) { x[j].add( -x[ii].dotProduct(t), x[ii] ); } b.times(x[j], t); x[j].times( 1.0 / sqrt( x[j].dotProduct(t) ) ); } if ( ac > nroot ) { break; } /* compute new approximation of Z */ for ( int j = 0; j < nc; j++ ) { b.times(x[j], z[j]); } } // copy results IntArray order; order.enumerate(w.giveSize()); std :: sort(order.begin(), order.end(), [&w](int a, int b) { return w.at(a) < w.at(b); }); _eigv.resize(nroot); _r.resize(nn, nroot); for ( int i = 1; i <= nroot; i++ ) { _eigv.at(i) = w.at(order.at(i)); _r.setColumn(x[order.at(i) - 1], i); } if ( it < nitem ) { fprintf(outStream, "InverseIteration :: convergence reached in %d iterations\n", it); } else { fprintf(outStream, "InverseIteration :: convergence not reached after %d iterations\n", it); } return NM_Success; }
void FEI2dLineLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { // Not meaningful to return anything. answer.resize(0,0); }
void GradDpElement :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { NLStructuralElement *elem = this->giveNLStructuralElement(); StructuralCrossSection *cs = elem->giveStructuralCrossSection(); FloatArray answerU, answerK; double localCumulatedStrain = 0.; FloatMatrix stiffKappa, B; FloatArray Nk, aux, dKappa, stress; FloatMatrix lStiff; FloatMatrix Bk; FloatArray gKappa, L_gKappa; //set displacement and nonlocal location array this->setDisplacementLocationArray(); this->setNonlocalLocationArray(); this->computeNonlocalDegreesOfFreedom(dKappa, tStep); int nlGeo = elem->giveGeometryMode(); for ( auto &gp: *elem->giveIntegrationRule(0) ) { GradDpMaterialExtensionInterface *dpmat = dynamic_cast< GradDpMaterialExtensionInterface * >( cs->giveMaterialInterface(GradDpMaterialExtensionInterfaceType, gp) ); if ( !dpmat ) { OOFEM_ERROR("Material doesn't implement the required DpGrad interface!"); } double dV = elem->computeVolumeAround(gp); if ( nlGeo == 0 || elem->domain->giveEngngModel()->giveFormulation() == AL ) { elem->computeBmatrixAt(gp, B); } else if ( nlGeo == 1 ) { elem->computeBHmatrixAt(gp, B); } this->computeStressVectorAndLocalCumulatedStrain(stress, localCumulatedStrain, gp, tStep); answerU.plusProduct(B, stress, dV); // Gradient part: this->computeNkappaMatrixAt(gp, Nk); this->computeBkappaMatrixAt(gp, Bk); dpmat->givePDGradMatrix_kk(lStiff, TangentStiffness, gp, tStep); double kappa = Nk.dotProduct(dKappa); gKappa.beProductOf(Bk, dKappa); answerK.add(-dV * localCumulatedStrain, Nk); answerK.add(kappa * dV, Nk); if ( dpmat->giveAveragingType() == 0 || dpmat->giveAveragingType() == 1 ) { double l = lStiff.at(1, 1); answerK.plusProduct(Bk, gKappa, l * l * dV); } else if ( dpmat->giveAveragingType() == 2 ) { L_gKappa.beProductOf(lStiff, gKappa); answerK.plusProduct(Bk, L_gKappa, dV); } } //this->computeStiffnessMatrix_kk(stiffKappa, TangentStiffness, tStep); //answerK.beProductOf(stiffKappa, dKappa); answerK.add(aux); answer.resize(totalSize); answer.zero(); answer.assemble(answerU, locU); answer.assemble(answerK, locK); }
void MPSDamMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &totalStrain, TimeStep *tStep) { if (this->E < 0.) { // initialize dummy elastic modulus E this->E = 1. / MPSMaterial :: computeCreepFunction(28.01, 28., gp, tStep); } MPSDamMaterialStatus *status = static_cast< MPSDamMaterialStatus * >( this->giveStatus(gp) ); MaterialMode mode = gp->giveMaterialMode(); FloatArray principalStress; FloatMatrix principalDir; StressVector tempEffectiveStress(mode); StressVector tempNominalStress(mode); double f, sigma1, kappa, tempKappa = 0.0, omega = 0.0; // effective stress computed by the viscoelastic MPS material MPSMaterial :: giveRealStressVector(tempEffectiveStress, gp, totalStrain, tStep); if ( !this->isActivated(tStep) ) { FloatArray help; help.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); help.zero(); status->letTempStrainVectorBe(help); status->letTempStressVectorBe(help); status->letTempViscoelasticStressVectorBe(help); #ifdef supplementary_info status->setResidualTensileStrength(0.); status->setCrackWidth(0.); status->setTempKappa(0.); status->setTempDamage(0.); #endif return; } tempEffectiveStress.computePrincipalValDir(principalStress, principalDir); sigma1 = 0.; if ( principalStress.at(1) > 0.0 ) { sigma1 = principalStress.at(1); } kappa = sigma1 / this->E; f = kappa - status->giveKappa(); if ( f <= 0.0 ) { // damage does not grow tempKappa = status->giveKappa(); omega = status->giveDamage(); #ifdef supplementary_info double residualStrength = 0.; double e0; if ( ( this->timeDepFracturing ) && ( this->givee0(gp) == 0. ) ) { this->initDamagedFib(gp, tStep); } e0 = this->givee0(gp); if ( omega == 0. ) { residualStrength = E * e0; // undamaged material } else { double gf, ef, wf = 0., Le; gf = this->givegf(gp); Le = status->giveCharLength(); if ( softType == ST_Exponential_Cohesive_Crack ) { // exponential softening wf = gf / this->E / e0; // wf is the crack opening } else if ( softType == ST_Linear_Cohesive_Crack ) { // linear softening law wf = 2. * gf / this->E / e0; // wf is the crack opening } else { OOFEM_ERROR("Gf unsupported for softening type softType = %d", softType); } ef = wf / Le; //ef is the fracturing strain if ( this->softType == ST_Linear_Cohesive_Crack ) { residualStrength = E * e0 * ( ef - tempKappa ) / ( ef - e0 ); } else if ( this->softType == ST_Exponential_Cohesive_Crack ) { residualStrength = E * e0 * exp(-1. * ( tempKappa - e0 ) / ef); } else { OOFEM_ERROR("Unknown softening type for cohesive crack model."); } } if ( status ) { status->setResidualTensileStrength(residualStrength); } #endif } else { // damage grows tempKappa = kappa; FloatArray crackPlaneNormal(3); for ( int i = 1; i <= principalStress.giveSize(); i++ ) { crackPlaneNormal.at(i) = principalDir.at(i, 1); } this->initDamaged(tempKappa, crackPlaneNormal, gp, tStep); this->computeDamage(omega, tempKappa, gp); } answer.zero(); if ( omega > 0. ) { tempNominalStress = tempEffectiveStress; if ( this->isotropic ) { // convert effective stress to nominal stress tempNominalStress.times(1. - omega); answer.add(tempNominalStress); } else { // stress transformation matrix FloatMatrix Tstress; // compute principal nominal stresses by multiplying effective stresses by damage for ( int i = 1; i <= principalStress.giveSize(); i++ ) { if ( principalStress.at(i) > 0. ) { // convert principal effective stress to nominal stress principalStress.at(i) *= ( 1. - omega ); } } if ( mode == _PlaneStress ) { principalStress.resizeWithValues(3); givePlaneStressVectorTranformationMtrx(Tstress, principalDir, true); } else { principalStress.resizeWithValues(6); giveStressVectorTranformationMtrx(Tstress, principalDir, true); } principalStress.rotatedWith(Tstress, 'n'); if ( mode == _PlaneStress ) { // plane stress answer.add(principalStress); } else if ( this->giveSizeOfVoigtSymVector(mode) != this->giveSizeOfVoigtSymVector(_3dMat) ) { // mode = _PlaneStrain or axial symmetry StressVector redFormStress(mode); redFormStress.convertFromFullForm(principalStress, mode); answer.add(redFormStress); } else { // 3D answer.add(principalStress); } } } else { answer.add(tempEffectiveStress); } #ifdef supplementary_info if ( ( omega == 0. ) || ( sigma1 <= 0 ) ) { status->setCrackWidth(0.); } else { FloatArray principalStrains; this->computePrincipalValues(principalStrains, totalStrain, principal_strain); double crackWidth; //case when the strain localizes into narrow band and after a while the stresses relax double strainWithoutTemperShrink = principalStrains.at(1); strainWithoutTemperShrink -= status->giveTempThermalStrain(); strainWithoutTemperShrink -= status->giveTempDryingShrinkageStrain(); strainWithoutTemperShrink -= status->giveTempAutogenousShrinkageStrain(); crackWidth = status->giveCharLength() * omega * strainWithoutTemperShrink; status->setCrackWidth(crackWidth); } #endif // update gp status->letTempStrainVectorBe(totalStrain); status->letTempStressVectorBe(answer); status->letTempViscoelasticStressVectorBe(tempEffectiveStress); status->setTempKappa(tempKappa); status->setTempDamage(omega); }