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); }