void ParallelContext :: accumulate(const FloatArray &local, FloatArray &global) { #ifdef __PARALLEL_MODE if ( emodel->isParallel() ) { int size = local.giveSize(); global.resize(size); ///@todo Why aren't we using the C++ MPI functions? MPI_Allreduce( const_cast<double*>(local.givePointer()), global.givePointer(), size, MPI_DOUBLE, MPI_SUM, this->emodel->giveParallelComm() ); } else { #endif global = local; #ifdef __PARALLEL_MODE } #endif }
void PetscSparseMtrx :: times(const FloatArray &x, FloatArray &answer) const { if ( this->giveNumberOfColumns() != x.giveSize() ) { OOFEM_ERROR("Dimension mismatch"); } #ifdef __PARALLEL_MODE if ( emodel->isParallel() ) { OOFEM_ERROR("PetscSparseMtrx :: times - Not implemented"); } #endif Vec globX, globY; VecCreateSeqWithArray(PETSC_COMM_SELF, 1, x.giveSize(), x.givePointer(), & globX); VecCreate(PETSC_COMM_SELF, & globY); VecSetType(globY, VECSEQ); VecSetSizes(globY, PETSC_DECIDE, this->nRows); MatMult(this->mtrx, globX, globY); double *ptr; VecGetArray(globY, & ptr); answer.resize(this->nRows); for ( int i = 0; i < this->nRows; i++ ) { answer(i) = ptr [ i ]; } VecRestoreArray(globY, & ptr); VecDestroy(&globX); VecDestroy(&globY); }
void AbaqusUserElement :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, FloatArray &U, FloatMatrix &DU, int useUpdatedGpRecord) { if ( useUpdatedGpRecord ) { this->rhs.copyColumn(answer, 1); } else { this->lFlags.at(1) = 1; // 1 based access this->lFlags.at(3) = 1; // 1 based access this->lFlags.at(4) = 0; // 1 based access int nprops = props.giveSize(); int njprops = jprops.giveSize(); FloatMatrix loc_rhs(this->ndofel, this->nrhs); FloatMatrix loc_amatrx(this->ndofel, this->ndofel); FloatArray loc_svars = this->giveStateVector(); //this->getSvars(); double period = 0., pnewdt = 0.; double dtime = tStep->giveTimeIncrement(); double time[] = {tStep->giveTargetTime() - dtime, tStep->giveTargetTime()}; this->uel( loc_rhs.givePointer(), loc_amatrx.givePointer(), loc_svars.givePointer(), energy.givePointer(), & ndofel, & nrhs, & numSvars, props.givePointer(), & nprops, coords.givePointer(), & mcrd, & this->numberOfDofMans, U.givePointer(), DU.givePointer(), V.givePointer(), A.givePointer(), & jtype, time, & dtime, & kstep, & kinc, & ( this->number ), params, & ndLoad, jdltype, adlmag.givePointer(), predef.givePointer(), & npredef, lFlags.givePointer(), & mlvarx, ddlmag.givePointer(), & mdLoad, & pnewdt, jprops.givePointer(), & njprops, & period); //FloatArray vout; //vout.resize(12); //for (int i = 1; i <= 3; i++) //{ // vout.at(i) = rhs.at(i, 1); // vout.at(i+6) = rhs.at(i+3, 1); //} //answer = vout; //this->rhs.copyColumn(answer, 1); //answer.negated(); loc_rhs.negated(); //really needed??? loc_rhs.copyColumn(answer, 1); letTempRhsBe(loc_rhs); letTempTangentBe(loc_amatrx); letTempSvarsBe(loc_svars); } }
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 AbaqusUserMaterial :: giveRealStressVector(FloatArray &answer, MatResponseForm form, 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]; MaterialMode mMode = gp->giveMaterialMode(); // Sizes of the tensors. int ndi; int nshr; ///@todo Check how to deal with large deformations. ///@todo Check order of entries in the Voigt notation (which order does Abaqus use? convert to that). if ( mMode == _3dMat ) { ndi = 3; nshr = 3; } else if ( mMode == _PlaneStress ) { ndi = 2; nshr = 1; } else if ( mMode == _PlaneStrain ) { ndi = 3; nshr = 1; } /*else if ( mMode == _3dMat_F ) { * ndi = 3; * nshr = 6; * } */ else if ( mMode == _1dMat ) { ndi = 1; nshr = 0; } else { ndi = nshr = 0; OOFEM_ERROR2( "AbaqusUserMaterial :: giveRealStressVector : unsupported material mode (%s)", __MaterialModeToString(mMode) ); } int ntens = ndi + nshr; FloatArray stress(ntens); FloatArray strain = ms->giveStrainVector(); 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->giveCoordinates() ); ///@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); 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.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; 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 ms->letTempStrainVectorBe(reducedStrain); ms->letTempStressVectorBe(stress); ms->letTempStateVectorBe(state); ms->letTempTangentBe(jacobian); answer = stress; OOFEM_LOG_DEBUG("AbaqusUserMaterial :: giveRealStressVector - Calling subroutine was successful"); }
void DSSMatrix :: solve(FloatArray &b, FloatArray &x) { x.resize( b.giveSize() ); _dss->Solve( x.givePointer(), b.givePointer() ); }