void FreeWarping :: computeResultAtCenterOfGravity(TimeStep *tStep) { int noCS = this->giveDomain(1)->giveNumberOfCrossSectionModels(); //number of warping Crosssections SolutionAtCG.resize(noCS); Element *closestElement; FloatArray lcoords, closest, lcg; SpatialLocalizer *sp = this->giveDomain(1)->giveSpatialLocalizer(); sp->init(); lcoords.resize(2); closest.resize(2); lcg.resize(2); for ( int j = 1; j <= noCS; ++j ) { lcg.at(1) = CG.at(j, 1); lcg.at(2) = CG.at(j, 2); closestElement = sp->giveElementClosestToPoint(lcoords, closest, lcg, 0); StructuralElement *sE = dynamic_cast< StructuralElement * >(closestElement); FloatArray u, r, b; FloatMatrix N; sE->computeNmatrixAt(lcoords, N); sE->computeVectorOf(VM_Total, tStep, u); u.resizeWithValues(3); r.beProductOf(N, u); SolutionAtCG.at(j) = r.at(1); } }
void GradDpElement :: computeStiffnessMatrix_kk(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { StructuralElement *elem = this->giveStructuralElement(); double dV; FloatMatrix lStiff; FloatArray Nk; FloatMatrix Bk, LBk; StructuralCrossSection *cs = elem->giveStructuralCrossSection(); answer.clear(); 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!"); } this->computeNkappaMatrixAt(gp, Nk); this->computeBkappaMatrixAt(gp, Bk); dV = elem->computeVolumeAround(gp); dpmat->givePDGradMatrix_kk(lStiff, rMode, gp, tStep); answer.plusProductUnsym(Nk, Nk, dV); if ( dpmat->giveAveragingType() == 0 || dpmat->giveAveragingType() == 1 ) { double l = lStiff.at(1, 1); answer.plusProductUnsym(Bk, Bk, l * l * dV); } else if ( dpmat->giveAveragingType() == 2 ) { LBk.beProductOf(lStiff, Bk); answer.plusProductUnsym(Bk, LBk, dV); } } }
// computes Btransposed*eta for the given Gauss point // (where eta is the derivative of cum. plastic strain wrt final strain) void RankineMatNl :: giveRemoteNonlocalStiffnessContribution(GaussPoint *gp, IntArray &rloc, const UnknownNumberingScheme &s, FloatArray &rcontrib, TimeStep *atTime) { RankineMatNlStatus *status = ( RankineMatNlStatus * ) this->giveStatus(gp); StructuralElement *elem = ( StructuralElement * )( gp->giveElement() ); elem->giveLocationArray(rloc, EID_MomentumBalance, s); FloatMatrix b; elem->computeBmatrixAt(gp, b); int ncols = b.giveNumberOfColumns(); rcontrib.resize(ncols); double kappa = status->giveCumulativePlasticStrain(); double tempKappa = status->giveTempCumulativePlasticStrain(); if ( tempKappa <= kappa ) { rcontrib.zero(); return; } int i, j; double sum; int nsize = 3; FloatArray eta(3); computeEta(eta, status); for ( i = 1; i <= ncols; i++ ) { sum = 0.; for ( j = 1; j <= nsize; j++ ) { sum += eta.at(j) * b.at(j, i); } rcontrib.at(i) = sum; } }
void TrabBoneNL3D :: giveRemoteNonlocalStiffnessContribution(GaussPoint *gp, IntArray &rloc, const UnknownNumberingScheme &s, FloatArray &rcontrib, TimeStep *tStep) { TrabBoneNL3DStatus *nlStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(gp) ); StructuralElement *elem = static_cast< StructuralElement * >( gp->giveElement() ); FloatMatrix b; elem->giveLocationArray(rloc, s); elem->computeBmatrixAt(gp, b); double kappa = nlStatus->giveKappa(); double tempKappa = nlStatus->giveTempKappa(); double dKappa = tempKappa - kappa; if ( dKappa < 10.e-9 ) { dKappa = 0; } if ( dKappa > 0.0 ) { FloatArray remoteNu, prodTensor; const FloatArray &plasFlowDirec = nlStatus->givePlasFlowDirec(); const FloatMatrix &SSaTensor = nlStatus->giveSSaTensor(); double beta = nlStatus->giveBeta(); prodTensor.beTProductOf(SSaTensor, plasFlowDirec); remoteNu = 1 / beta * prodTensor; rcontrib.beTProductOf(b, remoteNu); } else { rcontrib.resize(b.giveNumberOfColumns()); rcontrib.zero(); } }
int MisesMatNl :: giveLocalNonlocalStiffnessContribution(GaussPoint *gp, IntArray &loc, const UnknownNumberingScheme &s, FloatArray &lcontrib, TimeStep *atTime) { int nrows, nsize, i, j; double sum, nlKappa, damage, tempDamage, dDamF; MisesMatNlStatus *status = ( MisesMatNlStatus * ) this->giveStatus(gp); StructuralElement *elem = ( StructuralElement * )( gp->giveElement() ); FloatMatrix b; FloatArray stress; this->computeCumPlasticStrain(nlKappa, gp, atTime); damage = status->giveDamage(); tempDamage = status->giveTempDamage(); if ( ( tempDamage - damage ) > 0 ) { elem->giveLocationArray(loc, EID_MomentumBalance, s); status->giveTempEffectiveStress(stress); elem->computeBmatrixAt(gp, b); dDamF = computeDamageParamPrime(nlKappa); nrows = b.giveNumberOfColumns(); nsize = stress.giveSize(); lcontrib.resize(nrows); for ( i = 1; i <= nrows; i++ ) { sum = 0.0; for ( j = 1; j <= nsize; j++ ) { sum += b.at(j, i) * stress.at(j); } lcontrib.at(i) = sum * mm * dDamF; } } return 1; }
void MisesMatNl :: giveRemoteNonlocalStiffnessContribution(GaussPoint *gp, IntArray &rloc, const UnknownNumberingScheme &s, FloatArray &rcontrib, TimeStep *tStep) { double kappa, tempKappa; MisesMatNlStatus *status = static_cast< MisesMatNlStatus * >( this->giveStatus(gp) ); StructuralElement *elem = static_cast< StructuralElement * >( gp->giveElement() ); FloatMatrix b; LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); double E = lmat->give('E', gp); elem->giveLocationArray(rloc, s); elem->computeBmatrixAt(gp, b); kappa = status->giveCumulativePlasticStrain(); tempKappa = status->giveTempCumulativePlasticStrain(); rcontrib.clear(); if ( ( tempKappa - kappa ) > 0 ) { const FloatArray &stress = status->giveTempEffectiveStress(); if ( gp->giveMaterialMode() == _1dMat ) { double coeff = sgn( stress.at(1) ) * E / ( E + H ); rcontrib.plusProduct(b, stress, coeff); return; } } rcontrib.resize(b.giveNumberOfColumns()); rcontrib.zero(); }
void SimpleCrossSection :: giveTemperatureVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) { Element *elem = gp->giveElement(); answer.clear(); //sum up all prescribed temperatures over an element StructuralElement *selem = dynamic_cast< StructuralElement * >(elem); selem->computeResultingIPTemperatureAt(answer, tStep, gp, VM_Total); /* add external source, if provided */ FieldManager *fm = this->domain->giveEngngModel()->giveContext()->giveFieldManager(); FM_FieldPtr tf; if ( ( tf = fm->giveField(FT_Temperature) ) ) { // temperature field registered FloatArray gcoords, et2; int err; elem->computeGlobalCoordinates( gcoords, gp->giveNaturalCoordinates() ); if ( ( err = tf->evaluateAt(et2, gcoords, VM_Total, tStep) ) ) { OOFEM_ERROR("tf->evaluateAt failed, element %d, error code %d", elem->giveNumber(), err); } if ( et2.isNotEmpty() ) { if ( answer.isEmpty() ) { answer = et2; } else { answer.at(1) += et2.at(1); } } } }
void FiberedCrossSection :: giveGeneralizedStress_Beam3d(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) { double fiberThick, fiberWidth, fiberZCoord, fiberYCoord; FloatArray fiberStrain, reducedFiberStress; StructuralElement *element = static_cast< StructuralElement * >( gp->giveElement() ); FiberedCrossSectionInterface *interface; if ( ( interface = static_cast< FiberedCrossSectionInterface * >( element->giveInterface(FiberedCrossSectionInterfaceType) ) ) == NULL ) { OOFEM_ERROR("element with no fiber support encountered"); } answer.resize(6); answer.zero(); for ( int i = 1; i <= numberOfFibers; i++ ) { GaussPoint *fiberGp = this->giveSlaveGaussPoint(gp, i - 1); StructuralMaterial *fiberMat = static_cast< StructuralMaterial * >( domain->giveMaterial( fiberMaterials.at(i) ) ); // the question is whether this function should exist ? // if yes the element details will be hidden. // good idea also should be existence of element::GiveBmatrixOfLayer // and computing strains here - but first idea looks better // but treating of geometric non-linearities may become more complicated // another approach - use several functions with assumed kinematic constraints // resolve current layer z-coordinate fiberThick = this->fiberThicks.at(i); fiberWidth = this->fiberWidths.at(i); fiberYCoord = fiberGp->giveNaturalCoordinate(1); fiberZCoord = fiberGp->giveNaturalCoordinate(2); interface->FiberedCrossSectionInterface_computeStrainVectorInFiber(fiberStrain, strain, fiberGp, tStep); fiberMat->giveRealStressVector_Fiber(reducedFiberStress, fiberGp, fiberStrain, tStep); // perform integration // 1) membrane terms N, Qz, Qy answer.at(1) += reducedFiberStress.at(1) * fiberWidth * fiberThick; answer.at(2) += reducedFiberStress.at(2) * fiberWidth * fiberThick; answer.at(3) += reducedFiberStress.at(3) * fiberWidth * fiberThick; // 2) bending terms mx, my, mxy answer.at(4) += ( reducedFiberStress.at(2) * fiberWidth * fiberThick * fiberYCoord - reducedFiberStress.at(3) * fiberWidth * fiberThick * fiberZCoord ); answer.at(5) += reducedFiberStress.at(1) * fiberWidth * fiberThick * fiberZCoord; answer.at(6) -= reducedFiberStress.at(1) * fiberWidth * fiberThick * fiberYCoord; } // now we must update master gp ///@ todo simply chosen the first fiber material as master material /JB StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * > ( domain->giveMaterial( fiberMaterials.at(1) )->giveStatus(gp) ); status->letTempStrainVectorBe(strain); status->letTempStressVectorBe(answer); }
void TrabBoneNL3D :: giveRemoteNonlocalStiffnessContribution(GaussPoint *gp, IntArray &rloc, const UnknownNumberingScheme &s, FloatArray &rcontrib, TimeStep *tStep) { TrabBoneNL3DStatus *nlStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(gp) ); StructuralElement *elem = static_cast< StructuralElement * >( gp->giveElement() ); int ncols, nsize; double sum, beta; FloatArray remoteNu, plasFlowDirec, prodTensor; FloatMatrix b, SSaTensor; elem->giveLocationArray(rloc, s); elem->computeBmatrixAt(gp, b); ncols = b.giveNumberOfColumns(); rcontrib.resize(ncols); double kappa = nlStatus->giveKappa(); double tempKappa = nlStatus->giveTempKappa(); double dKappa = tempKappa - kappa; if ( dKappa < 10.e-9 ) { dKappa = 0; } if ( dKappa > 0.0 ) { plasFlowDirec = nlStatus->givePlasFlowDirec(); SSaTensor = nlStatus->giveSSaTensor(); beta = nlStatus->giveBeta(); prodTensor.beTProductOf(SSaTensor, plasFlowDirec); remoteNu = 1 / beta * prodTensor; nsize = remoteNu.giveSize(); for ( int i = 1; i <= ncols; i++ ) { sum = 0.0; for ( int j = 1; j <= nsize; j++ ) { sum += remoteNu.at(j) * b.at(j, i); } rcontrib.at(i) = sum; } } else { for ( int i = 1; i <= ncols; i++ ) { rcontrib.at(i) = 0.; } } }
void GradDpElement :: computeNonlocalDegreesOfFreedom(FloatArray &answer, TimeStep *tStep) { ///@todo Just use this instead! (should work, but I don't have any tests right now) #if 0 this->giveStructuralElement()->computeVectorOf({G_0}, VM_Total, tStep, answer); #else StructuralElement *elem = this->giveStructuralElement(); FloatArray u; answer.resize(nlSize); elem->computeVectorOf(VM_Total, tStep, u); u.resizeWithValues(totalSize); for ( int i = 1; i <= nlSize; i++ ) { answer.at(i) = u.at( locK.at(i) ); } #endif }
int TrabBoneNL3D :: giveLocalNonlocalStiffnessContribution(GaussPoint *gp, IntArray &loc, const UnknownNumberingScheme &s, FloatArray &lcontrib, TimeStep *tStep) { TrabBoneNL3DStatus *nlStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(gp) ); StructuralElement *elem = static_cast< StructuralElement * >( gp->giveElement() ); int nrows, nsize; double sum, nlKappa, dDamFunc, dam, tempDam; FloatArray localNu; FloatMatrix b; this->computeCumPlastStrain(nlKappa, gp, tStep); dam = nlStatus->giveDam(); tempDam = nlStatus->giveTempDam(); if ( ( tempDam - dam ) > 0.0 ) { elem->giveLocationArray(loc, s); localNu = nlStatus->giveTempEffectiveStress(); elem->giveLocationArray(loc, EModelDefaultEquationNumbering() ); elem->computeBmatrixAt(gp, b); dDamFunc = expDam * critDam * exp(-expDam * nlKappa); nrows = b.giveNumberOfColumns(); nsize = localNu.giveSize(); lcontrib.resize(nrows); for ( int i = 1; i <= nrows; i++ ) { sum = 0.0; for ( int j = 1; j <= nsize; j++ ) { sum += b.at(j, i) * localNu.at(j); } lcontrib.at(i) = mParam * dDamFunc * sum; } return 1; } else { loc.clear(); return 0; } }
void MisesMatNl :: giveRemoteNonlocalStiffnessContribution(GaussPoint *gp, IntArray &rloc, const UnknownNumberingScheme &s, FloatArray &rcontrib, TimeStep *atTime) { int ncols, nsize, i, j; double sum, kappa, tempKappa; MisesMatNlStatus *status = ( MisesMatNlStatus * ) this->giveStatus(gp); StructuralElement *elem = ( StructuralElement * )( gp->giveElement() ); FloatMatrix b; FloatArray stress; LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); double E = lmat->give('E', gp); elem->giveLocationArray(rloc, EID_MomentumBalance, s); elem->computeBmatrixAt(gp, b); ncols = b.giveNumberOfColumns(); rcontrib.resize(ncols); kappa = status->giveCumulativePlasticStrain(); tempKappa = status->giveTempCumulativePlasticStrain(); if ( ( tempKappa - kappa ) > 0 ) { status->giveTempEffectiveStress(stress); if ( gp->giveMaterialMode() == _1dMat ) { nsize = stress.giveSize(); double coeff = sgn( stress.at(1) ) * E / ( E + H ); for ( i = 1; i <= ncols; i++ ) { sum = 0.; for ( j = 1; j <= nsize; j++ ) { sum += stress.at(j) * coeff * b.at(j, i); } rcontrib.at(i) = sum; } } } else { rcontrib.zero(); } }
// computes m*gprime*Btransposed*sigmaeff for the given Gauss point // and returns 0 of damage is not growing, 1 if it is growing // (if damage is not growing, the contribution is not considered at all) int RankineMatNl :: giveLocalNonlocalStiffnessContribution(GaussPoint *gp, IntArray &loc, const UnknownNumberingScheme &s, FloatArray &lcontrib, TimeStep *atTime) { int nrows, nsize, i, j; double sum, nlKappa, damage, tempDamage; RankineMatNlStatus *status = ( RankineMatNlStatus * ) this->giveStatus(gp); StructuralElement *elem = ( StructuralElement * )( gp->giveElement() ); FloatMatrix b; FloatArray stress; damage = status->giveDamage(); tempDamage = status->giveTempDamage(); if ( tempDamage <= damage ) { return 0; // no contribution if damage is not growing } elem->giveLocationArray(loc, EID_MomentumBalance, s); status->giveTempEffectiveStress(stress); elem->computeBmatrixAt(gp, b); this->computeCumPlasticStrain(nlKappa, gp, atTime); double factor = computeDamageParamPrime(nlKappa); factor *= mm; // this factor is m*gprime nrows = b.giveNumberOfColumns(); nsize = stress.giveSize(); lcontrib.resize(nrows); // compute the product Btransposed*stress and multiply by factor for ( i = 1; i <= nrows; i++ ) { sum = 0.0; for ( j = 1; j <= nsize; j++ ) { sum += b.at(j, i) * stress.at(j); } lcontrib.at(i) = sum * factor; } return 1; // contribution will be considered }
int MisesMatNl :: giveLocalNonlocalStiffnessContribution(GaussPoint *gp, IntArray &loc, const UnknownNumberingScheme &s, FloatArray &lcontrib, TimeStep *tStep) { double nlKappa, damage, tempDamage, dDamF; MisesMatNlStatus *status = static_cast< MisesMatNlStatus * >( this->giveStatus(gp) ); StructuralElement *elem = static_cast< StructuralElement * >( gp->giveElement() ); FloatMatrix b; this->computeCumPlasticStrain(nlKappa, gp, tStep); damage = status->giveDamage(); tempDamage = status->giveTempDamage(); if ( ( tempDamage - damage ) > 0 ) { const FloatArray &stress = status->giveTempEffectiveStress(); elem->giveLocationArray(loc, s); elem->computeBmatrixAt(gp, b); dDamF = computeDamageParamPrime(nlKappa); lcontrib.clear(); lcontrib.plusProduct(b, stress, mm * dDamF); } return 1; }
MorphoFilter<T>::MorphoFilter(const StructuralElement& element) : NonLinearFilter<T>(&(element.getKernel()[0]), element.getWidth(), element.getHeight(), element.getDepth()) {}
void LSPrimaryVariableMapper :: mapPrimaryVariables(FloatArray &oU, Domain &iOldDom, Domain &iNewDom, ValueModeType iMode, TimeStep &iTStep) { EngngModel *engngMod = iNewDom.giveEngngModel(); EModelDefaultEquationNumbering num; const int dim = iNewDom.giveNumberOfSpatialDimensions(); int numElNew = iNewDom.giveNumberOfElements(); // Count dofs int numDofsNew = engngMod->giveNumberOfDomainEquations( 1, num ); oU.resize(numDofsNew); oU.zero(); FloatArray du(numDofsNew); du.zero(); FloatArray res(numDofsNew); std :: unique_ptr< SparseMtrx > K; std :: unique_ptr< SparseLinearSystemNM > solver; solver.reset( classFactory.createSparseLinSolver(ST_Petsc, & iOldDom, engngMod) ); if (!solver) { solver.reset( classFactory.createSparseLinSolver(ST_Direct, & iOldDom, engngMod) ); } K.reset( classFactory.createSparseMtrx(solver->giveRecommendedMatrix(true)) ); K->buildInternalStructure( engngMod, iNewDom.giveNumber(), num ); int maxIter = 1; for ( int iter = 0; iter < maxIter; iter++ ) { K->zero(); res.zero(); // Contribution from elements for ( int elIndex = 1; elIndex <= numElNew; elIndex++ ) { StructuralElement *elNew = dynamic_cast< StructuralElement * >( iNewDom.giveElement(elIndex) ); if ( elNew == NULL ) { OOFEM_ERROR("Failed to cast Element new to StructuralElement."); } /////////////////////////////////// // Compute residual // Count element dofs int numElNodes = elNew->giveNumberOfDofManagers(); int numElDofs = 0; for ( int i = 1; i <= numElNodes; i++ ) { numElDofs += elNew->giveDofManager(i)->giveNumberOfDofs(); } FloatArray elRes(numElDofs); elRes.zero(); IntArray elDofsGlob; elNew->giveLocationArray( elDofsGlob, num ); // Loop over Gauss points for ( int intRuleInd = 0; intRuleInd < elNew->giveNumberOfIntegrationRules(); intRuleInd++ ) { for ( GaussPoint *gp: *elNew->giveIntegrationRule(intRuleInd) ) { // New N-matrix FloatMatrix NNew; elNew->computeNmatrixAt(gp->giveNaturalCoordinates(), NNew); ////////////// // Global coordinates of GP const FloatArray &localCoord = gp->giveNaturalCoordinates(); FloatArray globalCoord; elNew->computeGlobalCoordinates(globalCoord, localCoord); ////////////// // Localize element and point in the old domain FloatArray localCoordOld(dim), pointCoordOld(dim); StructuralElement *elOld = dynamic_cast< StructuralElement * >( iOldDom.giveSpatialLocalizer()->giveElementClosestToPoint(localCoordOld, pointCoordOld, globalCoord, 0) ); if ( elOld == NULL ) { OOFEM_ERROR("Failed to cast Element old to StructuralElement."); } // Compute N-Matrix for the old element FloatMatrix NOld; elOld->computeNmatrixAt(localCoordOld, NOld); // Fetch nodal displacements for the new element FloatArray nodeDispNew( elDofsGlob.giveSize() ); int dofsPassed = 1; for ( int elNode: elNew->giveDofManArray() ) { // DofManager *dMan = iNewDom.giveNode(elNode); DofManager *dMan = iNewDom.giveDofManager(elNode); for ( Dof *dof: *dMan ) { if ( elDofsGlob.at(dofsPassed) != 0 ) { nodeDispNew.at(dofsPassed) = oU.at( elDofsGlob.at(dofsPassed) ); } else { if ( dof->hasBc(& iTStep) ) { nodeDispNew.at(dofsPassed) = dof->giveBcValue(iMode, & iTStep); } } dofsPassed++; } } FloatArray newDisp; newDisp.beProductOf(NNew, nodeDispNew); // Fetch nodal displacements for the old element FloatArray nodeDispOld; dofsPassed = 1; IntArray elDofsGlobOld; elOld->giveLocationArray( elDofsGlobOld, num ); // elOld->computeVectorOf(iMode, &(iTStep), nodeDisp); int numElNodesOld = elOld->giveNumberOfDofManagers(); for(int nodeIndOld = 1; nodeIndOld <= numElNodesOld; nodeIndOld++) { DofManager *dManOld = elOld->giveDofManager(nodeIndOld); for ( Dof *dof: *dManOld ) { if ( elDofsGlobOld.at(dofsPassed) != 0 ) { FloatArray dofUnknowns; if(dof->giveEqn() > 0) { dof->giveUnknowns(dofUnknowns, iMode, &iTStep); #ifdef DEBUG if(!dofUnknowns.isFinite()) { OOFEM_ERROR("!dofUnknowns.isFinite()") } if(dofUnknowns.giveSize() < 1) { OOFEM_ERROR("dofUnknowns.giveSize() < 1") } #endif nodeDispOld.push_back(dofUnknowns.at(1)); } else { // TODO: Why does this case occur? nodeDispOld.push_back(0.0); } } else { if ( dof->hasBc(& iTStep) ) { // printf("hasBC.\n"); #ifdef DEBUG if(!std::isfinite(dof->giveBcValue(iMode, & iTStep))) { OOFEM_ERROR("!std::isfinite(dof->giveBcValue(iMode, & iTStep))") } #endif nodeDispOld.push_back( dof->giveBcValue(iMode, & iTStep) ); } else { // printf("Unhandled case in LSPrimaryVariableMapper :: mapPrimaryVariables().\n"); nodeDispOld.push_back( 0.0 ); } } dofsPassed++; } }
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 HOMExportModule :: doOutput(TimeStep *tStep, bool forcedOutput) { if ( !( testTimeStepOutput(tStep) || forcedOutput ) ) { return; } Domain *d = emodel->giveDomain(1); int nelem = d->giveNumberOfElements(); double dV, VolTot = 0.; FloatArray vecState, vecFlow, sumFlow(3); FloatArray internalSource, capacity; FloatArray answerArr, answerArr1; FloatMatrix answerMtrx; IntArray Mask; FloatMatrix baseGCS; sumFlow.zero(); domainType domType = d->giveDomainType(); if ( domType == _HeatTransferMode || domType == _HeatMass1Mode ) { #ifdef __TM_MODULE double sumState = 0.; TransportElement *transpElem; for ( int ielem = 1; ielem <= nelem; ielem++ ) { Element *elem = d->giveElement(ielem); if ( this->matnum.giveSize() == 0 || this->matnum.contains( elem->giveMaterial()->giveNumber() ) ) { for ( GaussPoint *gp: *elem->giveDefaultIntegrationRulePtr() ) { dV = elem->computeVolumeAround(gp); VolTot += dV; elem->giveIPValue(vecState, gp, IST_Temperature, tStep); elem->giveIPValue(vecFlow, gp, IST_TemperatureFlow, tStep); sumState += vecState.at(1) * dV; vecFlow.resize(3); vecFlow.times(dV); sumFlow += vecFlow; } } } sumState *= ( 1. / VolTot * this->scale ); fprintf(this->stream, "%e % e ", tStep->giveTargetTime(), sumState); sumFlow.times(1. / VolTot * this->scale); fprintf( this->stream, "% e % e % e ", sumFlow.at(1), sumFlow.at(2), sumFlow.at(3) ); //add total heat for each material - accumulated energy due to material capacity (J for heat) and internal source (J for heat) internalSource.resize( d->giveNumberOfCrossSectionModels() ); capacity.resize( d->giveNumberOfCrossSectionModels() ); for ( int ielem = 1; ielem <= nelem; ielem++ ) { transpElem = static_cast< TransportElement * >( d->giveElement(ielem) ); transpElem->computeInternalSourceRhsVectorAt(answerArr, tStep, VM_Total); internalSource.at( transpElem->giveCrossSection()->giveNumber() ) += answerArr.sum(); transpElem->giveCharacteristicMatrix(answerMtrx, CapacityMatrix, tStep); transpElem->computeVectorOf(VM_Incremental, tStep, answerArr); answerArr1.beProductOf(answerMtrx, answerArr); capacity.at( transpElem->giveCrossSection()->giveNumber() ) -= answerArr1.sum(); } internalSource.times( tStep->giveTimeIncrement() ); internalSourceEnergy.add(internalSource); capacityEnergy.add(capacity); for ( int i = 1; i <= internalSourceEnergy.giveSize(); i++ ) { fprintf( this->stream, "% e ", internalSourceEnergy.at(i) ); } fprintf(this->stream, " "); for ( int i = 1; i <= capacityEnergy.giveSize(); i++ ) { fprintf( this->stream, "% e ", capacityEnergy.at(i) ); } fprintf(this->stream, "\n"); #endif } else { //structural analysis #ifdef __SM_MODULE StructuralElement *structElem; //int nnodes = d->giveNumberOfDofManagers(); FloatArray VecStrain, VecStress, VecEigStrain, VecEigStrainReduced, tempStrain(6), tempStress(6), tempEigStrain(6), SumStrain(6), SumStress(6), SumEigStrain(6), tempFloatAr, damage; double sumDamage = 0.; //stress and strain vectors are always in global c.s. SumStrain.zero(); //xx, yy, zz, yz, zx, xy SumStress.zero(); SumEigStrain.zero(); for ( int ielem = 1; ielem <= nelem; ielem++ ) { Element *elem = d->giveElement(ielem); tempStrain.zero(); tempStress.zero(); tempEigStrain.zero(); if ( this->matnum.giveSize() == 0 || this->matnum.contains( elem->giveMaterial()->giveNumber() ) ) { for ( GaussPoint *gp: *elem->giveDefaultIntegrationRulePtr() ) { structElem = static_cast< StructuralElement * >(elem); // structElem->computeResultingIPEigenstrainAt(VecEigStrain, tStep, gp, VM_Incremental); structElem->computeResultingIPEigenstrainAt(VecEigStrainReduced, tStep, gp, VM_Total); if ( VecEigStrainReduced.giveSize() == 0 ) { VecEigStrain.resize(0); } else { ( ( StructuralMaterial * ) structElem->giveMaterial() )->giveFullSymVectorForm( VecEigStrain, VecEigStrainReduced, gp->giveMaterialMode() ); } dV = elem->computeVolumeAround(gp); elem->giveIPValue(VecStrain, gp, IST_StrainTensor, tStep); elem->giveIPValue(VecStress, gp, IST_StressTensor, tStep); elem->giveIPValue(damage, gp, IST_DamageTensor, tStep); //truss element has strains and stresses in the first array so transform them to global coordinates ///@todo Should this be the job of giveIPValue to ensure that vectors are given in global c.s.? if ( dynamic_cast< Truss3d * >(elem) ) { MaterialMode mmode = _3dMat; tempStress.at(1) = VecStress.at(1); tempStrain.at(1) = VecStrain.at(1); if ( VecEigStrain.giveSize() ) { tempEigStrain.at(1) = VecEigStrain.at(1); } StressVector stressVector1(tempStress, mmode); //convert from array StressVector stressVector2(mmode); StrainVector strainVector1(tempStrain, mmode); //convert from array StrainVector strainVector2(mmode); StrainVector strainEigVector1(tempEigStrain, mmode); //convert from array StrainVector strainEigVector2(mmode); elem->giveLocalCoordinateSystem(baseGCS); stressVector1.transformTo(stressVector2, baseGCS, 0); strainVector1.transformTo(strainVector2, baseGCS, 0); strainEigVector1.transformTo(strainEigVector2, baseGCS, 0); stressVector2.convertToFullForm(VecStress); strainVector2.convertToFullForm(VecStrain); strainEigVector2.convertToFullForm(VecEigStrain); } VolTot += dV; VecStrain.times(dV); VecStress.times(dV); VecEigStrain.times(dV); if ( damage.giveSize() ) { //only for models with damage sumDamage += damage.at(1) * dV; } SumStrain.add(VecStrain); SumEigStrain.add(VecEigStrain); SumStress.add(VecStress); //VecStrain.printYourself(); //VecEigStrain.printYourself(); //SumStrain.printYourself(); } } } //averaging SumStrain.times(1. / VolTot * this->scale); SumEigStrain.times(1. / VolTot * this->scale); SumStress.times(1. / VolTot * this->scale); sumDamage *= ( 1. / VolTot ); //SumStrain.printYourself(); //SumEigStrain.printYourself(); //SumStress.printYourself(); fprintf( this->stream, "%f ", tStep->giveTargetTime() ); for ( double s: SumStrain ) { //strain fprintf( this->stream, "%06.5e ", s ); } fprintf(this->stream, " "); for ( double s: SumStress ) { //stress fprintf( this->stream, "%06.5e ", s ); } fprintf(this->stream, " "); for ( double s: SumEigStrain ) { //eigenstrain fprintf( this->stream, "%06.5e ", s ); } fprintf(this->stream, "Vol %06.5e ", VolTot); fprintf(this->stream, "AvrDamage %06.5e ", sumDamage); fprintf(this->stream, "\n"); #endif } fflush(this->stream); }
void OrthotropicLinearElasticMaterial :: giveTensorRotationMatrix(FloatMatrix &answer, GaussPoint *gp) // // returns [3,3] rotation matrix from local principal axes of material // to local axes used at gp (element) level // { int elementCsFlag; FloatMatrix elementCs; StructuralElement *element = static_cast< StructuralElement * >( gp->giveElement() ); if ( gp->giveMaterialMode() == _1dMat ) { //do not rotate 1D materials on trusses and beams answer.resize(3, 3); answer.beUnitMatrix(); return; } elementCsFlag = element->giveLocalCoordinateSystem(elementCs); // // in localCoordinateSystem the directional cosines are stored columwise (exception) // in elementCs rowwise. // if ( this->cs_type == localCS ) { // // in localCoordinateSystem are stored directional cosines // if ( elementCsFlag ) { answer.beProductOf(elementCs, * this->localCoordinateSystem); } else { answer = * this->localCoordinateSystem; } } else if ( this->cs_type == shellCS ) { FloatArray elementNormal, helpx, helpy; localCoordinateSystem = new FloatMatrix(3, 3); element->computeMidPlaneNormal(elementNormal, gp); helpx.beVectorProductOf(* ( this->helpPlaneNormal ), elementNormal); // test if localCoordinateSystem is uniquely // defined by elementNormal and helpPlaneNormal if ( helpx.computeNorm() < ZERO_LENGTH ) { OOFEM_ERROR("element normal parallel to plane normal encountered"); } helpy.beVectorProductOf(elementNormal, helpx); for ( int i = 1; i < 4; i++ ) { localCoordinateSystem->at(i, 1) = helpx.at(i); localCoordinateSystem->at(i, 2) = helpy.at(i); localCoordinateSystem->at(i, 3) = elementNormal.at(i); } // // possible rotation about local z-axis should be considered in future // /* * // * // GiveZRotationMtrx assembles rotMtrx from cs rotated from curent about rotAngle * // to current cs * // * zRotMtrx = GiveZRotationMtrx (rotAngle); // rotAngle supplied by user * rotatedLocalCoordinateSystem = localCoordinateSystem->Times (zRotMtrx); * delete localCoordinateSystem; * localCoordinateSystem = rotatedLocalCoordinateSystem; */ if ( elementCsFlag ) { answer.beProductOf(elementCs, * this->localCoordinateSystem); } else { answer = * this->localCoordinateSystem; } delete localCoordinateSystem; localCoordinateSystem = NULL; } else { OOFEM_ERROR("internal error no cs defined"); } // t at (i,j) contains cosine of angle between elementAxis(i) and localMaterialAxis(j). }
void XFEMStatic :: terminate(TimeStep *tStep) { this->doStepOutput(tStep); this->printReactionForces(tStep, 1); // update load vectors before storing context fflush( this->giveOutputStream() ); this->updateLoadVectors(tStep); this->saveStepContext(tStep); // Propagate fronts for ( auto &domain: domainList ) { XfemManager *xMan = domain->giveXfemManager(); xMan->propagateFronts(); } // Update element subdivisions if necessary // (e.g. if a crack has moved and cut a new element) for ( int domInd = 1; domInd <= this->giveNumberOfDomains(); domInd++ ) { Domain *domain = this->giveDomain(domInd); // create a new set containing all elements Set elemSet(0, domain); elemSet.addAllElements(); if ( domain->giveXfemManager()->hasPropagatingFronts() || mForceRemap ) { // If domain cloning is performed, there is no need to // set values from the dof map. mSetValsFromDofMap = false; // Take copy of the domain to allow mapping of state variables // to the new Gauss points. Domain *dNew = domain->Clone(); bool deallocateOld = false; setDomain(1, dNew, deallocateOld); forceEquationNumbering(); // Map primary variables LSPrimaryVariableMapper primMapper; FloatArray u; primMapper.mapPrimaryVariables(u, * domain, * dNew, VM_Total, * tStep); if ( totalDisplacement.giveSize() == u.giveSize() ) { FloatArray diff; diff.beDifferenceOf(totalDisplacement, u); printf( "diff norm: %e\n", diff.computeNorm() ); } totalDisplacement = u; primMapper.mapPrimaryVariables(incrementOfDisplacement, * domain, * dNew, VM_Incremental, * tStep); int numEl = dNew->giveNumberOfElements(); for ( int i = 1; i <= numEl; i++ ) { //////////////////////////////////////////////////////// // Map state variables for regular Gauss points StructuralElement *el = dynamic_cast< StructuralElement * >( dNew->giveElement(i) ); el->createMaterialStatus(); el->mapStateVariables(* domain, * tStep); //////////////////////////////////////////////////////// // Map state variables for cohesive zone if applicable XfemStructuralElementInterface *xFemEl = dynamic_cast< XfemStructuralElementInterface * >(el); if ( xFemEl != NULL ) { if ( xFemEl->mpCZMat != NULL ) { size_t numCzRules = xFemEl->mpCZIntegrationRules.size(); for ( size_t czIndex = 0; czIndex < numCzRules; czIndex++ ) { if ( xFemEl->mpCZIntegrationRules [ czIndex ] != NULL ) { for ( GaussPoint *gp: *xFemEl->mpCZIntegrationRules [ czIndex ] ) { MaterialStatus *ms = xFemEl->mpCZMat->giveStatus(gp); if ( ms == NULL ) { OOFEM_ERROR("Failed to fetch material status."); } MaterialStatusMapperInterface *interface = dynamic_cast< MaterialStatusMapperInterface * > ( xFemEl->mpCZMat->giveStatus(gp) ); if ( interface == NULL ) { OOFEM_ERROR("Failed to fetch MaterialStatusMapperInterface."); } MaterialStatus *matStat = dynamic_cast< MaterialStatus * >( xFemEl->mpCZMat->giveStatus(gp) ); StructuralInterfaceMaterialStatus *siMatStat = dynamic_cast< StructuralInterfaceMaterialStatus * >(matStat); if ( siMatStat == NULL ) { OOFEM_ERROR("Failed to cast to StructuralInterfaceMaterialStatus."); } interface->MSMI_map_cz(* gp, * domain, elemSet, * tStep, * siMatStat); } } } } } } delete domain; domain = this->giveDomain(1); // Set domain pointer to various components ... this->nMethod->setDomain(domain); int numExpModules = this->exportModuleManager->giveNumberOfModules(); for ( int i = 1; i <= numExpModules; i++ ) { // ... by diving deep into the hierarchies ... :-/ VTKXMLExportModule *vtkxmlMod = dynamic_cast< VTKXMLExportModule * >( this->exportModuleManager->giveModule(i) ); if ( vtkxmlMod != NULL ) { vtkxmlMod->giveSmoother()->setDomain(domain); vtkxmlMod->givePrimVarSmoother()->setDomain(domain); } } this->setUpdateStructureFlag(true); } // if( domain->giveXfemManager()->hasPropagatingFronts() ) //#endif } // Fracture/failure mechanics evaluation for ( auto &domain: domainList ) { if ( domain->hasFractureManager() ) { // Will most likely fail if numDom > 1 FractureManager *fracMan = domain->giveFractureManager(); fracMan->evaluateYourself(tStep); fracMan->updateXFEM(tStep); // Update XFEM structure based on the fracture manager this->setUpdateStructureFlag( fracMan->giveUpdateFlag() ); // if the internal structure need to be updated } } }
void SimpleInterfaceMaterial :: giveStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) // // Returns characteristic material stiffness matrix of the receiver // { MaterialMode mMode = gp->giveElement()->giveMaterialMode(); FloatArray strainVector; StructuralElement *el = static_cast< StructuralElement * >( gp->giveElement() ); double normalStrain; el->computeStrainVector(strainVector, gp, tStep); normalStrain = strainVector.at(1); answer.zero(); switch ( mMode ) { case _1dInterface: answer.resize(1, 1); if ( rMode == SecantStiffness || rMode == TangentStiffness ) { if ( normalStrain + normalClearance <= 0 ) { answer.at(1, 1) = this->kn; //in compression and after the clearance gap closed } else { answer.at(1, 1) = this->kn * this->stiffCoeff; } } else { if ( rMode == ElasticStiffness ) { answer.at(1, 1) = this->kn; } else { OOFEM_ERROR("unknown MatResponseMode (%s)", __MatResponseModeToString(rMode) ); } } return; case _2dInterface: answer.resize(2, 2); if ( rMode == SecantStiffness || rMode == TangentStiffness ) { if ( normalStrain + normalClearance <= 0. ) { answer.at(1, 1) = answer.at(2, 2) = this->kn; //in compression and after the clearance gap closed } else { answer.at(1, 1) = answer.at(2, 2) = this->kn * this->stiffCoeff; } } else { if ( rMode == ElasticStiffness ) { answer.at(1, 1) = answer.at(2, 2) = this->kn; } else { OOFEM_ERROR("unknown MatResponseMode (%s)", __MatResponseModeToString(rMode) ); } } return; case _3dInterface: answer.resize(3, 3); if ( rMode == SecantStiffness || rMode == TangentStiffness ) { if ( normalStrain + normalClearance <= 0. ) { answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = this->kn; //in compression and after the clearance gap closed } else { answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = this->kn * this->stiffCoeff; } } else { if ( rMode == ElasticStiffness ) { answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = this->kn; } else { OOFEM_ERROR("unknown MatResponseMode (%s)", __MatResponseModeToString(rMode) ); } } return; default: StructuralMaterial :: giveStiffnessMatrix(answer, rMode, gp, tStep); } }
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); }
void LSPrimaryVariableMapper :: mapPrimaryVariables(FloatArray &oU, Domain &iOldDom, Domain &iNewDom, ValueModeType iMode, TimeStep &iTStep) { EngngModel *engngMod = iNewDom.giveEngngModel(); EModelDefaultEquationNumbering num; const int dim = iNewDom.giveNumberOfSpatialDimensions(); int numElNew = iNewDom.giveNumberOfElements(); // Count dofs int numDofsNew = engngMod->giveNumberOfDomainEquations( 1, num ); oU.resize(numDofsNew); oU.zero(); FloatArray du(numDofsNew); du.zero(); FloatArray res(numDofsNew); #ifdef __PETSC_MODULE PetscSparseMtrx *K = dynamic_cast<PetscSparseMtrx*>( classFactory.createSparseMtrx(SMT_PetscMtrx) ); SparseLinearSystemNM *solver = classFactory.createSparseLinSolver(ST_Petsc, & iOldDom, engngMod); #else SparseMtrx *K = classFactory.createSparseMtrx(SMT_Skyline); SparseLinearSystemNM *solver = classFactory.createSparseLinSolver(ST_Direct, & iOldDom, engngMod); #endif K->buildInternalStructure( engngMod, 1, num ); int maxIter = 1; for ( int iter = 0; iter < maxIter; iter++ ) { K->zero(); res.zero(); // Contribution from elements for ( int elIndex = 1; elIndex <= numElNew; elIndex++ ) { StructuralElement *elNew = dynamic_cast< StructuralElement * >( iNewDom.giveElement(elIndex) ); if ( elNew == NULL ) { OOFEM_ERROR("Failed to cast Element new to StructuralElement."); } /////////////////////////////////// // Compute residual // Count element dofs int numElNodes = elNew->giveNumberOfDofManagers(); int numElDofs = 0; for ( int i = 1; i <= numElNodes; i++ ) { numElDofs += elNew->giveDofManager(i)->giveNumberOfDofs(); } FloatArray elRes(numElDofs); elRes.zero(); IntArray elDofsGlob; elNew->giveLocationArray( elDofsGlob, num ); // Loop over Gauss points for ( int intRuleInd = 0; intRuleInd < elNew->giveNumberOfIntegrationRules(); intRuleInd++ ) { IntegrationRule *iRule = elNew->giveIntegrationRule(intRuleInd); for ( GaussPoint *gp: *iRule ) { // New N-matrix FloatMatrix NNew; elNew->computeNmatrixAt(* ( gp->giveNaturalCoordinates() ), NNew); ////////////// // Global coordinates of GP const int nDofMan = elNew->giveNumberOfDofManagers(); FloatArray Nc; FEInterpolation *interp = elNew->giveInterpolation(); const FloatArray &localCoord = * ( gp->giveNaturalCoordinates() ); interp->evalN( Nc, localCoord, FEIElementGeometryWrapper(elNew) ); const IntArray &elNodes = elNew->giveDofManArray(); FloatArray globalCoord(dim); globalCoord.zero(); for ( int i = 1; i <= nDofMan; i++ ) { DofManager *dMan = elNew->giveDofManager(i); for ( int j = 1; j <= dim; j++ ) { globalCoord.at(j) += Nc.at(i) * dMan->giveCoordinate(j); } } ////////////// // Localize element and point in the old domain FloatArray localCoordOld(dim), pointCoordOld(dim); StructuralElement *elOld = dynamic_cast< StructuralElement * >( iOldDom.giveSpatialLocalizer()->giveElementClosestToPoint(localCoordOld, pointCoordOld, globalCoord, 0) ); if ( elOld == NULL ) { OOFEM_ERROR("Failed to cast Element old to StructuralElement."); } // Compute N-Matrix for the old element FloatMatrix NOld; elOld->computeNmatrixAt(localCoordOld, NOld); // Fetch nodal displacements for the new element FloatArray nodeDispNew( elDofsGlob.giveSize() ); int dofsPassed = 1; for ( int i = 1; i <= elNodes.giveSize(); i++ ) { DofManager *dMan = elNew->giveDofManager(i); for ( Dof *dof: *dMan ) { if ( elDofsGlob.at(dofsPassed) != 0 ) { nodeDispNew.at(dofsPassed) = oU.at( elDofsGlob.at(dofsPassed) ); } else { if ( dof->hasBc(& iTStep) ) { nodeDispNew.at(dofsPassed) = dof->giveBcValue(iMode, & iTStep); } } dofsPassed++; } } FloatArray newDisp; newDisp.beProductOf(NNew, nodeDispNew); // Fetch nodal displacements for the old element FloatArray nodeDispOld; dofsPassed = 1; IntArray elDofsGlobOld; elOld->giveLocationArray( elDofsGlobOld, num ); // elOld->computeVectorOf(iMode, &(iTStep), nodeDisp); int numElNodesOld = elOld->giveNumberOfDofManagers(); for(int nodeIndOld = 1; nodeIndOld <= numElNodesOld; nodeIndOld++) { DofManager *dManOld = elOld->giveDofManager(nodeIndOld); for ( Dof *dof: *dManOld ) { if ( elDofsGlobOld.at(dofsPassed) != 0 ) { FloatArray dofUnknowns; dof->giveUnknowns(dofUnknowns, iMode, &iTStep); #ifdef DEBUG if(!dofUnknowns.isFinite()) { OOFEM_ERROR("!dofUnknowns.isFinite()") } if(dofUnknowns.giveSize() < 1) { OOFEM_ERROR("dofUnknowns.giveSize() < 1") } #endif nodeDispOld.push_back(dofUnknowns.at(1)); } else { if ( dof->hasBc(& iTStep) ) { // printf("hasBC.\n"); #ifdef DEBUG if(!std::isfinite(dof->giveBcValue(iMode, & iTStep))) { OOFEM_ERROR("!std::isfinite(dof->giveBcValue(iMode, & iTStep))") } #endif nodeDispOld.push_back( dof->giveBcValue(iMode, & iTStep) ); } else { // printf("Unhandled case in LSPrimaryVariableMapper :: mapPrimaryVariables().\n"); nodeDispOld.push_back( 0.0 ); } } dofsPassed++; } } FloatArray oldDisp; oldDisp.beProductOf(NOld, nodeDispOld); FloatArray temp, du; #ifdef DEBUG if(!oldDisp.isFinite()) { OOFEM_ERROR("!oldDisp.isFinite()") } if(!newDisp.isFinite()) { OOFEM_ERROR("!newDisp.isFinite()") } #endif du.beDifferenceOf(oldDisp, newDisp); temp.beTProductOf(NNew, du); double dV = elNew->computeVolumeAround(gp); elRes.add(dV, temp); } }