int StructuralInterfaceMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { StructuralInterfaceMaterialStatus *status = static_cast< StructuralInterfaceMaterialStatus * >( this->giveStatus(gp) ); if ( type == IST_InterfaceJump ) { answer = status->giveJump(); answer.resizeWithValues(3); // In case some model is not storing all components. return 1; } else if ( type == IST_InterfaceTraction ) { answer = status->giveTraction(); answer.resizeWithValues(3); return 1; } else if ( type == IST_InterfaceFirstPKTraction ) { answer = status->giveFirstPKTraction(); answer = status->giveTempFirstPKTraction(); answer.resizeWithValues(3); return 1; } else if ( type == IST_DeformationGradientTensor ) { answer.beVectorForm( status->giveF() ); return 1; } else if ( type == IST_InterfaceNormal ) { answer = status->giveNormal(); return 1; } else { return Material :: giveIPValue(answer, gp, type, tStep); } }
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 AbaqusUserMaterial :: giveFirstPKStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &vF, 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 stress(9); // PK1 FloatArray strainIncrement; // compute Green-Lagrange strain FloatArray strain; FloatArray vS; FloatMatrix F, E; F.beMatrixForm(vF); E.beTProductOf(F, F); E.at(1, 1) -= 1.0; E.at(2, 2) -= 1.0; E.at(3, 3) -= 1.0; E.times(0.5); strain.beSymVectorFormOfStrain(E); strainIncrement.beDifferenceOf(strain, ms->giveStrainVector()); FloatArray state = ms->giveStateVector(); FloatMatrix jacobian(9, 9); // dPdF 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() ); ///@todo Large deformations? /* 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); /* 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); dfgrd0.beMatrixForm( ms->giveFVector() ); dfgrd1.beMatrixForm(vF); int noel = gp->giveElement()->giveNumber(); // Element number. int npt = 0; // Integration point number. // We intentionally ignore the layer number since that is handled by the layered cross-section in OOFEM. int layer = 0; // Layer number (for composite shells and layered solids).. int kspt = 0; // Section point number within the current layer. int kstep = tStep->giveMetaStepNumber(); // 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(); OOFEM_LOG_DEBUG("AbaqusUserMaterial :: giveRealStressVector - 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(); strain.changeComponentOrder(); strainIncrement.changeComponentOrder(); jacobian.changeComponentOrder(); if ( mStressInterpretation == 0 ) { FloatMatrix P, cauchyStress; P.beMatrixForm(stress); FloatArray vP; vP.beVectorForm(P); cauchyStress.beProductTOf(P, F); cauchyStress.times( 1.0 / F.giveDeterminant() ); FloatArray vCauchyStress; vCauchyStress.beSymVectorForm(cauchyStress); ms->letTempStrainVectorBe(strain); ms->letTempStressVectorBe(vCauchyStress); ms->letTempStateVectorBe(state); ms->letTempTangentBe(jacobian); ms->letTempPVectorBe(vP); ms->letTempFVectorBe(vF); answer = vP; } else { FloatArray vP; FloatMatrix P, sigma, F_inv; F_inv.beInverseOf(F); sigma.beMatrixForm(stress); P.beProductOf(F, sigma); vP.beVectorForm(P); answer = vP; // Convert from sigma to S FloatMatrix S; S.beProductOf(F_inv, P); vS.beSymVectorForm(S); // @todo Should convert from dsigmadE to dSdE here // L2=detF*matmul( matmul ( inv(op_a_V9(F,F), cm-op_a_V9(ident,Tau)-op_b_V9(Tau,ident) ), inv(op_a_V9(Ft,Ft))) ms->letTempStrainVectorBe(strain); ms->letTempStressVectorBe(vS); ms->letTempStateVectorBe(state); ms->letTempTangentBe(jacobian); ms->letTempPVectorBe(vP); ms->letTempFVectorBe(vF); } OOFEM_LOG_DEBUG("AbaqusUserMaterial :: giveRealStressVector_3d - Calling subroutine was successful"); }
void MisesMat :: giveFirstPKStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &totalDefGradOOFEM, TimeStep *tStep) { MisesMatStatus *status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); double kappa, dKappa, yieldValue, mi; FloatMatrix F, oldF, invOldF; FloatArray s; F.beMatrixForm(totalDefGradOOFEM); //(method assumes full 3D) kappa = status->giveCumulativePlasticStrain(); oldF.beMatrixForm( status->giveFVector() ); invOldF.beInverseOf(oldF); //relative deformation radient FloatMatrix f; f.beProductOf(F, invOldF); //compute elastic predictor FloatMatrix trialLeftCauchyGreen, help; f.times( 1./cbrt(f.giveDeterminant()) ); help.beProductOf(f, status->giveTempLeftCauchyGreen()); trialLeftCauchyGreen.beProductTOf(help, f); FloatMatrix E; E.beTProductOf(F, F); E.at(1, 1) -= 1.0; E.at(2, 2) -= 1.0; E.at(3, 3) -= 1.0; E.times(0.5); FloatArray e; e.beSymVectorFormOfStrain(E); FloatArray leftCauchyGreen; FloatArray leftCauchyGreenDev; double leftCauchyGreenVol; leftCauchyGreen.beSymVectorFormOfStrain(trialLeftCauchyGreen); leftCauchyGreenVol = computeDeviatoricVolumetricSplit(leftCauchyGreenDev, leftCauchyGreen); FloatArray trialStressDev; applyDeviatoricElasticStiffness(trialStressDev, leftCauchyGreenDev, G / 2.); s = trialStressDev; //check for plastic loading double trialS = computeStressNorm(trialStressDev); double sigmaY = sig0 + H * kappa; //yieldValue = sqrt(3./2.)*trialS-sigmaY; yieldValue = trialS - sqrt(2. / 3.) * sigmaY; //store deviatoric trial stress(reused by algorithmic stiffness) status->letTrialStressDevBe(trialStressDev); //the return-mapping algorithm double J = F.giveDeterminant(); mi = leftCauchyGreenVol * G; if ( yieldValue > 0 ) { //dKappa =sqrt(3./2.)* yieldValue/(H + 3.*mi); //kappa = kappa + dKappa; //trialStressDev.times(1-sqrt(6.)*mi*dKappa/trialS); dKappa = ( yieldValue / ( 2 * mi ) ) / ( 1 + H / ( 3 * mi ) ); FloatArray n = trialStressDev; n.times(2 * mi * dKappa / trialS); ////return map s.beDifferenceOf(trialStressDev, n); kappa += sqrt(2. / 3.) * dKappa; //update of intermediate configuration trialLeftCauchyGreen.beMatrixForm(s); trialLeftCauchyGreen.times(1.0 / G); trialLeftCauchyGreen.at(1, 1) += leftCauchyGreenVol; trialLeftCauchyGreen.at(2, 2) += leftCauchyGreenVol; trialLeftCauchyGreen.at(2, 2) += leftCauchyGreenVol; trialLeftCauchyGreen.times(J * J); } //addition of the elastic mean stress FloatMatrix kirchhoffStress; kirchhoffStress.beMatrixForm(s); kirchhoffStress.at(1, 1) += 1. / 2. * K * ( J * J - 1 ); kirchhoffStress.at(2, 2) += 1. / 2. * K * ( J * J - 1 ); kirchhoffStress.at(3, 3) += 1. / 2. * K * ( J * J - 1 ); FloatMatrix iF, Ep(3, 3), S; FloatArray vF, vS, ep; //transform Kirchhoff stress into Second Piola - Kirchhoff stress iF.beInverseOf(F); help.beProductOf(iF, kirchhoffStress); S.beProductTOf(help, iF); this->computeGLPlasticStrain(F, Ep, trialLeftCauchyGreen, J); ep.beSymVectorFormOfStrain(Ep); vS.beSymVectorForm(S); vF.beVectorForm(F); answer.beVectorForm(kirchhoffStress); status->setTrialStressVol(mi); status->letTempLeftCauchyGreenBe(trialLeftCauchyGreen); status->setTempCumulativePlasticStrain(kappa); status->letTempStressVectorBe(answer); status->letTempStrainVectorBe(e); status->letTempPlasticStrainBe(ep); status->letTempPVectorBe(answer); status->letTempFVectorBe(vF); }