void MixedGradientPressureWeakPeriodic :: computeStress(FloatArray &sigmaDev, FloatArray &tractions, double rve_size) { FloatMatrix mMatrix; FloatArray normal, coords, t; int nsd = domain->giveNumberOfSpatialDimensions(); Set *set = this->giveDomain()->giveSet(this->set); const IntArray &boundaries = set->giveBoundaryList(); // Reminder: sigma = int t * n dA, where t = sum( C_i * n t_i ). // This loop will construct sigma in matrix form. FloatMatrix sigma; for ( int pos = 1; pos <= boundaries.giveSize() / 2; ++pos ) { Element *el = this->giveDomain()->giveElement( boundaries.at(pos * 2 - 1) ); int boundary = boundaries.at(pos * 2); FEInterpolation *interp = el->giveInterpolation(); // Geometry interpolation. The displacements or velocities must have the same interpolation scheme (on the boundary at least). int maxorder = this->order + interp->giveInterpolationOrder() * 3; std :: unique_ptr< IntegrationRule >ir( interp->giveBoundaryIntegrationRule(maxorder, boundary) ); for ( GaussPoint *gp: *ir ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); FEIElementGeometryWrapper cellgeo(el); double detJ = interp->boundaryEvalNormal(normal, boundary, lcoords, cellgeo); // Compute v_m = d_dev . x interp->boundaryLocal2Global(coords, boundary, lcoords, cellgeo); this->constructMMatrix(mMatrix, coords, normal); t.beProductOf(mMatrix, tractions); sigma.plusDyadUnsym(t, coords, detJ * gp->giveWeight()); } } sigma.times(1. / rve_size); double pressure = 0.; for ( int i = 1; i <= nsd; i++ ) { pressure += sigma.at(i, i); } pressure /= 3; // Not 100% sure about this for 2D cases. if ( nsd == 3 ) { sigmaDev.resize(6); sigmaDev.at(1) = sigma.at(1, 1) - pressure; sigmaDev.at(2) = sigma.at(2, 2) - pressure; sigmaDev.at(3) = sigma.at(3, 3) - pressure; sigmaDev.at(4) = 0.5 * ( sigma.at(2, 3) + sigma.at(3, 2) ); sigmaDev.at(5) = 0.5 * ( sigma.at(1, 3) + sigma.at(3, 1) ); sigmaDev.at(6) = 0.5 * ( sigma.at(1, 2) + sigma.at(2, 1) ); } else if ( nsd == 2 ) { sigmaDev.resize(3); sigmaDev.at(1) = sigma.at(1, 1) - pressure; sigmaDev.at(2) = sigma.at(2, 2) - pressure; sigmaDev.at(3) = 0.5 * ( sigma.at(1, 2) + sigma.at(2, 1) ); } else { sigmaDev.resize(1); sigmaDev.at(1) = sigma.at(1, 1) - pressure; } }
void MixedGradientPressureWeakPeriodic :: integrateTractionXTangent(FloatMatrix &answer, Element *el, int boundary) { // Computes the integral: int dt . dx_m dA FloatMatrix mMatrix; FloatArray normal, coords, vM_vol; FEInterpolation *interp = el->giveInterpolation(); // Geometry interpolation. The displacements or velocities must have the same interpolation scheme (on the boundary at least). int maxorder = this->order + interp->giveInterpolationOrder() * 3; std :: unique_ptr< IntegrationRule >ir( interp->giveBoundaryIntegrationRule(maxorder, boundary) ); FloatArray tmpAnswer; for ( GaussPoint *gp: *ir ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); FEIElementGeometryWrapper cellgeo(el); double detJ = interp->boundaryEvalNormal(normal, boundary, lcoords, cellgeo); interp->boundaryLocal2Global(coords, boundary, lcoords, cellgeo); vM_vol.beScaled(1.0/3.0, coords); this->constructMMatrix(mMatrix, coords, normal); tmpAnswer.plusProduct(mMatrix, vM_vol, detJ * gp->giveWeight()); } answer.resize(tmpAnswer.giveSize(), 1); answer.setColumn(tmpAnswer, 1); }
void MixedGradientPressureWeakPeriodic :: integrateTractionDev(FloatArray &answer, Element *el, int boundary, const FloatMatrix &ddev) { // Computes the integral: int dt . dx dA FloatMatrix mMatrix; FloatArray normal, coords, vM_dev; FEInterpolation *interp = el->giveInterpolation(); // Geometry interpolation. The displacements or velocities must have the same interpolation scheme (on the boundary at least). int maxorder = this->order + interp->giveInterpolationOrder() * 3; std :: unique_ptr< IntegrationRule >ir( interp->giveBoundaryIntegrationRule(maxorder, boundary) ); answer.clear(); for ( GaussPoint *gp: *ir ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); FEIElementGeometryWrapper cellgeo(el); double detJ = interp->boundaryEvalNormal(normal, boundary, lcoords, cellgeo); // Compute v_m = d_dev . x interp->boundaryLocal2Global(coords, boundary, lcoords, cellgeo); vM_dev.beProductOf(ddev, coords); this->constructMMatrix(mMatrix, coords, normal); answer.plusProduct(mMatrix, vM_dev, detJ * gp->giveWeight()); } }
int DofManValueField :: evaluateAt(FloatArray &answer, const FloatArray &coords, ValueModeType mode, TimeStep *tStep) { int result = 0; // assume ok FloatArray lc, n; // request element containing target point Element *elem = this->domain->giveSpatialLocalizer()->giveElementContainingPoint(coords); if ( elem ) { // ok element containing target point found FEInterpolation *interp = elem->giveInterpolation(); if ( interp ) { // map target point to element local coordinates if ( interp->global2local( lc, coords, FEIElementGeometryWrapper(elem) ) ) { // evaluate interpolation functions at target point interp->evalN( n, lc, FEIElementGeometryWrapper(elem) ); // loop over element nodes for ( int i = 1; i <= n.giveSize(); i++ ) { // multiply nodal value by value of corresponding shape function and add this to answer answer.add( n.at(i), this->dmanvallist[elem->giveDofManagerNumber(i)-1] ); } } else { // mapping from global to local coordinates failed result = 1; // failed } } else { // element without interpolation result = 1; // failed } } else { // no element containing given point found result = 1; // failed } return result; }
void AxisymElement :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) // // Returns the [ 6 x (nno*2) ] strain-displacement matrix {B} of the receiver, // evaluated at gp. // (epsilon_x,epsilon_y,...,Gamma_xy) = B . r // r = ( u1,v1,u2,v2,u3,v3,u4,v4) { FEInterpolation *interp = this->giveInterpolation(); FloatArray N; interp->evalN( N, gp->giveNaturalCoordinates(), *this->giveCellGeometryWrapper() ); double r = 0.0; for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) { double x = this->giveNode(i)->giveCoordinate(1); r += x * N.at(i); } FloatMatrix dNdx; interp->evaldNdx( dNdx, gp->giveNaturalCoordinates(), *this->giveCellGeometryWrapper() ); answer.resize(6, dNdx.giveNumberOfRows() * 2); answer.zero(); for ( int i = 1; i <= dNdx.giveNumberOfRows(); i++ ) { answer.at(1, i * 2 - 1) = dNdx.at(i, 1); answer.at(2, i * 2 - 0) = dNdx.at(i, 2); answer.at(3, i * 2 - 1) = N.at(i) / r; answer.at(6, 2 * i - 1) = dNdx.at(i, 2); answer.at(6, 2 * i - 0) = dNdx.at(i, 1); } }
void Space3dStructuralElementEvaluator :: computeBMatrixAt(FloatMatrix &answer, GaussPoint *gp) { FloatMatrix d; Element *element = this->giveElement(); FEInterpolation *interp = element->giveInterpolation(); // this uses FEInterpolation::nodes2coords - quite inefficient in this case (large num of dofmans) interp->evaldNdx( d, gp->giveNaturalCoordinates(), FEIIGAElementGeometryWrapper( element, gp->giveIntegrationRule()->giveKnotSpan() ) ); answer.resize(6, d.giveNumberOfRows() * 3); answer.zero(); for ( int i = 1; i <= d.giveNumberOfRows(); i++ ) { answer.at(1, i * 3 - 2) = d.at(i, 1); answer.at(2, i * 3 - 1) = d.at(i, 2); answer.at(3, i * 3 - 0) = d.at(i, 3); answer.at(4, 3 * i - 1) = d.at(i, 3); answer.at(4, 3 * i - 0) = d.at(i, 2); answer.at(5, 3 * i - 2) = d.at(i, 3); answer.at(5, 3 * i - 0) = d.at(i, 1); answer.at(6, 3 * i - 2) = d.at(i, 2); answer.at(6, 3 * i - 1) = d.at(i, 1); } }
bool EnrichmentItem :: tipIsTouchingEI(const TipInfo &iTipInfo) { double tol = 1.0e-9; SpatialLocalizer *localizer = giveDomain()->giveSpatialLocalizer(); Element *tipEl = localizer->giveElementContainingPoint(iTipInfo.mGlobalCoord); if ( tipEl != NULL ) { // Check if the candidate tip is located on the current crack FloatArray N; FloatArray locCoord; tipEl->computeLocalCoordinates(locCoord, iTipInfo.mGlobalCoord); FEInterpolation *interp = tipEl->giveInterpolation(); interp->evalN( N, locCoord, FEIElementGeometryWrapper(tipEl) ); double normalSignDist; evalLevelSetNormal( normalSignDist, iTipInfo.mGlobalCoord, N, tipEl->giveDofManArray() ); double tangSignDist; evalLevelSetTangential( tangSignDist, iTipInfo.mGlobalCoord, N, tipEl->giveDofManArray() ); if ( fabs(normalSignDist) < tol && tangSignDist > tol ) { return true; } } return false; }
void PlaneStressStructuralElementEvaluator :: computeNMatrixAt(FloatMatrix &answer, GaussPoint *gp) { FloatArray N; FEInterpolation *interp = gp->giveElement()->giveInterpolation(); interp->evalN( N, gp->giveNaturalCoordinates(), FEIIGAElementGeometryWrapper( gp->giveElement(), gp->giveIntegrationRule()->giveKnotSpan() ) ); answer.beNMatrixOf(N, 2); }
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 MatlabExportModule :: doOutputHomogenizeDofIDs(TimeStep *tStep, FILE *FID) { std :: vector <FloatArray*> HomQuantities; double Vol = 0.0; // Initialize vector of arrays constaining homogenized quantities HomQuantities.resize(internalVarsToExport.giveSize()); for (int j=0; j<internalVarsToExport.giveSize(); j++) { HomQuantities.at(j) = new FloatArray; } int nelem = this->elList.giveSize(); for (int i = 1; i<=nelem; i++) { Element *e = this->emodel->giveDomain(1)->giveElement(elList.at(i)); FEInterpolation *Interpolation = e->giveInterpolation(); Vol = Vol + e->computeVolumeAreaOrLength(); for ( GaussPoint *gp: *e->giveDefaultIntegrationRulePtr() ) { for (int j=0; j<internalVarsToExport.giveSize(); j++) { FloatArray elementValues; e->giveIPValue(elementValues, gp, (InternalStateType) internalVarsToExport(j), tStep); double detJ=fabs(Interpolation->giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e))); elementValues.times(gp->giveWeight()*detJ); if (HomQuantities.at(j)->giveSize() == 0) { HomQuantities.at(j)->resize(elementValues.giveSize()); HomQuantities.at(j)->zero(); }; HomQuantities.at(j)->add(elementValues); } } } if (noscaling) Vol=1.0; for ( std :: size_t i = 0; i < HomQuantities.size(); i ++) { FloatArray *thisIS; thisIS = HomQuantities.at(i); thisIS->times(1.0/Vol); fprintf(FID, "\tspecials.%s = [", __InternalStateTypeToString ( InternalStateType (internalVarsToExport(i)) ) ); for (int j = 0; j<thisIS->giveSize(); j++) { fprintf(FID, "%e", thisIS->at(j+1)); if (j!=(thisIS->giveSize()-1) ) { fprintf(FID, ", "); } } fprintf(FID, "];\n"); delete HomQuantities.at(i); } }
/* 3D Space Elements */ void Space3dStructuralElementEvaluator :: computeNMatrixAt(FloatMatrix &answer, GaussPoint *gp) { FloatArray N; Element *element = this->giveElement(); FEInterpolation *interp = element->giveInterpolation(); interp->evalN( N, gp->giveNaturalCoordinates(), FEIIGAElementGeometryWrapper( element, gp->giveIntegrationRule()->giveKnotSpan() ) ); answer.beNMatrixOf(N, 3); }
void PrescribedMean :: computeDomainSize() { if (domainSize > 0.0) return; if (elementEdges) { IntArray setList = ((GeneralBoundaryCondition *)this)->giveDomain()->giveSet(set)->giveBoundaryList(); elements.resize(setList.giveSize() / 2); sides.resize(setList.giveSize() / 2); for (int i=1; i<=setList.giveSize(); i=i+2) { elements.at(i/2+1) = setList.at(i); sides.at(i/2+1) = setList.at(i+1); } } else { IntArray setList = ((GeneralBoundaryCondition *)this)->giveDomain()->giveSet(set)->giveElementList(); elements = setList; } domainSize = 0.0; for ( int i=1; i<=elements.giveSize(); i++ ) { int elementID = elements.at(i); Element *thisElement = this->giveDomain()->giveElement(elementID); FEInterpolation *interpolator = thisElement->giveInterpolation(DofIDItem(dofid)); IntegrationRule *iRule; if (elementEdges) { iRule = interpolator->giveBoundaryIntegrationRule(3, sides.at(i)); } else { iRule = interpolator->giveIntegrationRule(3); } for ( GaussPoint * gp: * iRule ) { FloatArray lcoords = gp->giveNaturalCoordinates(); double detJ; if (elementEdges) { detJ = fabs ( interpolator->boundaryGiveTransformationJacobian(sides.at(i), lcoords, FEIElementGeometryWrapper(thisElement)) ); } else { detJ = fabs ( interpolator->giveTransformationJacobian(lcoords, FEIElementGeometryWrapper(thisElement)) ); } domainSize = domainSize + detJ*gp->giveWeight(); } delete iRule; } printf("%f\n", domainSize); }
double MixedGradientPressureBC :: domainSize() { int nsd = this->domain->giveNumberOfSpatialDimensions(); double domain_size = 0.0; // This requires the boundary to be consistent and ordered correctly. Set *set = this->giveDomain()->giveSet(this->set); const IntArray &boundaries = set->giveBoundaryList(); for ( int pos = 1; pos <= boundaries.giveSize() / 2; ++pos ) { Element *e = this->giveDomain()->giveElement( boundaries.at(pos * 2 - 1) ); int boundary = boundaries.at(pos * 2); FEInterpolation *fei = e->giveInterpolation(); domain_size += fei->evalNXIntegral( boundary, FEIElementGeometryWrapper(e) ); } return domain_size / nsd; }
void IntElLine1PhF :: computeCovarBaseVectorAt(IntegrationPoint *ip, FloatArray &G) { FloatMatrix dNdxi; FEInterpolation *interp = this->giveInterpolation(); interp->evaldNdxi( dNdxi, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); G.resize(2); G.zero(); int numNodes = this->giveNumberOfNodes(); for ( int i = 1; i <= dNdxi.giveNumberOfRows(); i++ ) { double X1_i = 0.5 * ( this->giveNode(i)->giveCoordinate(1) + this->giveNode(i + numNodes / 2)->giveCoordinate(1) ); // (mean) point on the fictious mid surface double X2_i = 0.5 * ( this->giveNode(i)->giveCoordinate(2) + this->giveNode(i + numNodes / 2)->giveCoordinate(2) ); G.at(1) += dNdxi.at(i, 1) * X1_i; G.at(2) += dNdxi.at(i, 1) * X2_i; } }
double TransportGradientPeriodic :: domainSize(Domain *d, int setNum) { int nsd = d->giveNumberOfSpatialDimensions(); double domain_size = 0.0; // This requires the boundary to be consistent and ordered correctly. Set *set = d->giveSet(setNum); const IntArray &boundaries = set->giveBoundaryList(); for ( int pos = 1; pos <= boundaries.giveSize() / 2; ++pos ) { Element *e = d->giveElement( boundaries.at(pos * 2 - 1) ); int boundary = boundaries.at(pos * 2); FEInterpolation *fei = e->giveInterpolation(); domain_size += fei->evalNXIntegral( boundary, FEIElementGeometryWrapper(e) ); } return fabs(domain_size / nsd); }
void IntElLine1PhF :: computeNmatrixAt(GaussPoint *ip, FloatMatrix &answer) { // Returns the modified N-matrix which multiplied with u give the spatial jump. FloatArray N; FEInterpolation *interp = this->giveInterpolation(); interp->evalN( N, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); answer.resize(2, 8); answer.zero(); 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(1); answer.at(1, 7) = answer.at(2, 8) = N.at(2); }
void PlaneStressElement :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx, int upperIndx) { FEInterpolation *interp = this->giveInterpolation(); FloatMatrix dNdx; interp->evaldNdx( dNdx, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); answer.resize(3, dNdx.giveNumberOfRows() * 2); answer.zero(); for ( int i = 1; i <= dNdx.giveNumberOfRows(); i++ ) { answer.at(1, i * 2 - 1) = dNdx.at(i, 1); answer.at(2, i * 2 - 0) = dNdx.at(i, 2); answer.at(3, 2 * i - 1) = dNdx.at(i, 2); answer.at(3, 2 * i - 0) = dNdx.at(i, 1); } }
void L4Axisymm :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) { // Returns the [ 6 x (nno*2) ] strain-displacement matrix {B} of the receiver, // evaluated at gp. Uses reduced integration. // (epsilon_x,epsilon_y,...,Gamma_xy) = B . r // r = ( u1,v1,u2,v2,u3,v3,u4,v4) FloatArray N, NRed, redCoord; if ( numberOfFiAndShGaussPoints == 1 ) { // Reduced integration redCoord = {0.0, 0.0}; // eval in centroid } else { redCoord = gp->giveNaturalCoordinates(); } FEInterpolation *interp = this->giveInterpolation(); interp->evalN( N, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); interp->evalN( NRed, redCoord, FEIElementGeometryWrapper(this) ); // Evaluate radius at center double r = 0.0; for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) { double x = this->giveNode(i)->giveCoordinate(1); r += x * NRed.at(i); } FloatMatrix dNdx, dNdxRed; interp->evaldNdx( dNdx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); interp->evaldNdx( dNdxRed, redCoord, FEIElementGeometryWrapper(this) ); answer.resize(6, dNdx.giveNumberOfRows() * 2); answer.zero(); for ( int i = 1; i <= dNdx.giveNumberOfRows(); i++ ) { answer.at(1, i * 2 - 1) = dNdx.at(i, 1); answer.at(2, i * 2 - 0) = dNdx.at(i, 2); answer.at(3, i * 2 - 1) = NRed.at(i) / r; answer.at(6, 2 * i - 1) = dNdxRed.at(i, 2); answer.at(6, 2 * i - 0) = dNdxRed.at(i, 1); } }
const IntArray &Set :: giveNodeList() { // Lazy evaluation, we compute the unique set of nodes if needed (and store it). if ( this->totalNodes.giveSize() == 0 ) { IntArray afflictedNodes( this->domain->giveNumberOfDofManagers() ); afflictedNodes.zero(); for ( int ielem = 1; ielem <= this->elements.giveSize(); ++ielem ) { Element *e = this->domain->giveElement( this->elements.at(ielem) ); for ( int inode = 1; inode <= e->giveNumberOfNodes(); ++inode ) { afflictedNodes.at( e->giveNode(inode)->giveNumber() ) = 1; } } IntArray bNodes; for ( int ibnd = 1; ibnd <= this->elementBoundaries.giveSize() / 2; ++ibnd ) { Element *e = this->domain->giveElement( this->elementBoundaries.at(ibnd * 2 - 1) ); int boundary = this->elementBoundaries.at(ibnd * 2); FEInterpolation *fei = e->giveInterpolation(); fei->boundaryGiveNodes(bNodes, boundary); for ( int inode = 1; inode <= bNodes.giveSize(); ++inode ) { afflictedNodes.at( e->giveNode( bNodes.at(inode) )->giveNumber() ) = 1; } } IntArray eNodes; for ( int iedge = 1; iedge <= this->elementEdges.giveSize() / 2; ++iedge ) { Element *e = this->domain->giveElement( this->elementEdges.at(iedge * 2 - 1) ); int edge = this->elementEdges.at(iedge * 2); FEInterpolation3d *fei = static_cast< FEInterpolation3d * >( e->giveInterpolation() ); fei->computeLocalEdgeMapping(eNodes, edge); for ( int inode = 1; inode <= eNodes.giveSize(); ++inode ) { afflictedNodes.at( e->giveNode( eNodes.at(inode) )->giveNumber() ) = 1; } } for ( int inode = 1; inode <= this->nodes.giveSize(); ++inode ) { afflictedNodes.at( this->nodes.at(inode) ) = 1; } totalNodes.findNonzeros(afflictedNodes); } return this->totalNodes; }
bool Inclusion :: isMaterialModified(GaussPoint &iGP, Element &iEl, CrossSection * &opCS) const { // Check if the point is located inside the inclusion FloatArray N; FEInterpolation *interp = iEl.giveInterpolation(); interp->evalN( N, * iGP.giveNaturalCoordinates(), FEIElementGeometryWrapper(& iEl) ); const IntArray &elNodes = iEl.giveDofManArray(); double levelSetGP = 0.0; interpLevelSet(levelSetGP, N, elNodes); if ( levelSetGP < 0.0 ) { opCS = mpCrossSection; return true; } return false; }
void PlaneStrainElement :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx, int upperIndx) // Returns the [ 4 x (nno*2) ] strain-displacement matrix {B} of the receiver, // evaluated at gp. { FEInterpolation *interp = this->giveInterpolation(); FloatMatrix dNdx; interp->evaldNdx( dNdx, gp->giveNaturalCoordinates(), *this->giveCellGeometryWrapper() ); answer.resize(4, dNdx.giveNumberOfRows() * 2); answer.zero(); for ( int i = 1; i <= dNdx.giveNumberOfRows(); i++ ) { answer.at(1, i * 2 - 1) = dNdx.at(i, 1); answer.at(2, i * 2 - 0) = dNdx.at(i, 2); answer.at(4, 2 * i - 1) = dNdx.at(i, 2); answer.at(4, 2 * i - 0) = dNdx.at(i, 1); } }
double NLStructuralElement :: computeCurrentVolume(TimeStep *tStep) { double vol=0.0; for ( auto &gp: *this->giveDefaultIntegrationRulePtr() ) { FloatArray F; FloatMatrix Fm; computeDeformationGradientVector(F, gp, tStep); Fm.beMatrixForm(F); double J = Fm.giveDeterminant(); FEInterpolation *interpolation = this->giveInterpolation(); double detJ = fabs( ( interpolation->giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ) ); vol += gp->giveWeight() * detJ * J; } return vol; }
void MixedGradientPressureWeakPeriodic :: integrateTractionVelocityTangent(FloatMatrix &answer, Element *el, int boundary) { // Computes the integral: int dt . dv dA FloatArray normal, n, coords; FloatMatrix nMatrix, mMatrix; FEInterpolation *interp = el->giveInterpolation(); // Geometry interpolation. The displacements or velocities must have the same interpolation scheme (on the boundary at least). int maxorder = this->order + interp->giveInterpolationOrder() * 3; std :: unique_ptr< IntegrationRule >ir( interp->giveBoundaryIntegrationRule(maxorder, boundary) ); int nsd = this->giveDomain()->giveNumberOfSpatialDimensions(); answer.clear(); for ( GaussPoint *gp: *ir ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); FEIElementGeometryWrapper cellgeo(el); double detJ = interp->boundaryEvalNormal(normal, boundary, lcoords, cellgeo); interp->boundaryEvalN(n, boundary, lcoords, cellgeo); interp->boundaryLocal2Global(coords, boundary, lcoords, cellgeo); // Construct the basis functions for the tractions: this->constructMMatrix(mMatrix, coords, normal); nMatrix.beNMatrixOf(n, nsd); answer.plusProductUnsym( mMatrix, nMatrix, detJ * gp->giveWeight() ); } }
int SmoothedNodalInternalVariableField :: evaluateAt(FloatArray &answer, FloatArray &coords, ValueModeType mode, TimeStep *tStep) { int result = 0; // assume ok FloatArray lc, n; const FloatArray *nodalValue; // use whole domain recovery // create a new set containing all elements Set elemSet(0, this->domain); elemSet.addAllElements(); this->smoother->recoverValues(elemSet, istType, tStep); // request element containing target point Element *elem = this->domain->giveSpatialLocalizer()->giveElementContainingPoint(coords); if ( elem ) { // ok element containing target point found FEInterpolation *interp = elem->giveInterpolation(); if ( interp ) { // map target point to element local coordinates if ( interp->global2local( lc, coords, FEIElementGeometryWrapper(elem) ) ) { // evaluate interpolation functions at target point interp->evalN( n, lc, FEIElementGeometryWrapper(elem) ); // loop over element nodes for ( int i = 1; i <= n.giveSize(); i++ ) { // request nodal value this->smoother->giveNodalVector( nodalValue, elem->giveDofManagerNumber(i) ); // multiply nodal value by value of corresponding shape function and add this to answer answer.add(n.at(i), * nodalValue); } } else { // mapping from global to local coordinates failed result = 1; // failed } } else { // element without interpolation result = 1; // failed } } else { // no element containing given point found result = 1; // failed } return result; }
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 IntElLine2IntPen :: computeCovarBaseVectorAt(IntegrationPoint *ip, FloatArray &G) { // printf("Entering IntElLine2IntPen :: computeCovarBaseVectorAt\n"); // Since we are averaging over the whole element, always evaluate the base vectors at xi = 0. FloatArray xi_0 = {0.0}; FloatMatrix dNdxi; FEInterpolation *interp = this->giveInterpolation(); // interp->evaldNdxi( dNdxi, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); interp->evaldNdxi( dNdxi, xi_0, FEIElementGeometryWrapper(this) ); G.resize(2); G.zero(); int numNodes = this->giveNumberOfNodes(); for ( int i = 1; i <= dNdxi.giveNumberOfRows(); i++ ) { double X1_i = 0.5 * ( this->giveNode(i)->giveCoordinate(1) + this->giveNode(i + numNodes / 2)->giveCoordinate(1) ); // (mean) point on the fictious mid surface double X2_i = 0.5 * ( this->giveNode(i)->giveCoordinate(2) + this->giveNode(i + numNodes / 2)->giveCoordinate(2) ); G.at(1) += dNdxi.at(i, 1) * X1_i; G.at(2) += dNdxi.at(i, 1) * X2_i; } }
const IntArray &Set :: giveNodeList() { // Lazy evaluation, we compute the unique set of nodes if needed (and store it). if ( this->totalNodes.giveSize() == 0 ) { IntArray afflictedNodes( this->domain->giveNumberOfDofManagers() ); afflictedNodes.zero(); for ( int ielem = 1; ielem <= this->elements.giveSize(); ++ielem ) { Element *e = this->domain->giveElement( this->elements.at(ielem) ); for ( int inode = 1; inode <= e->giveNumberOfNodes(); ++inode ) { afflictedNodes.at( e->giveNode(inode)->giveNumber() ) = 1; } } /* boundary entities are obsolete, use edges and/or surfaces instead */ IntArray bNodes; for ( int ibnd = 1; ibnd <= this->elementBoundaries.giveSize() / 2; ++ibnd ) { Element *e = this->domain->giveElement( this->elementBoundaries.at(ibnd * 2 - 1) ); int boundary = this->elementBoundaries.at(ibnd * 2); FEInterpolation *fei = e->giveInterpolation(); fei->boundaryGiveNodes(bNodes, boundary); for ( int inode = 1; inode <= bNodes.giveSize(); ++inode ) { afflictedNodes.at( e->giveNode( bNodes.at(inode) )->giveNumber() ) = 1; } } IntArray eNodes; for ( int iedge = 1; iedge <= this->elementEdges.giveSize() / 2; ++iedge ) { Element *e = this->domain->giveElement( this->elementEdges.at(iedge * 2 - 1) ); int edge = this->elementEdges.at(iedge * 2); FEInterpolation *fei = e->giveInterpolation(); fei->boundaryEdgeGiveNodes(eNodes, edge); for ( int inode = 1; inode <= eNodes.giveSize(); ++inode ) { afflictedNodes.at( e->giveNode( eNodes.at(inode) )->giveNumber() ) = 1; } } for ( int isurf = 1; isurf <= this->elementSurfaces.giveSize() / 2; ++isurf ) { Element *e = this->domain->giveElement( this->elementSurfaces.at(isurf * 2 - 1) ); int surf = this->elementSurfaces.at(isurf * 2); FEInterpolation *fei = e->giveInterpolation(); fei->boundarySurfaceGiveNodes(eNodes, surf); for ( int inode = 1; inode <= eNodes.giveSize(); ++inode ) { afflictedNodes.at( e->giveNode( eNodes.at(inode) )->giveNumber() ) = 1; } } for ( int inode = 1; inode <= this->nodes.giveSize(); ++inode ) { afflictedNodes.at( this->nodes.at(inode) ) = 1; } totalNodes.findNonzeros(afflictedNodes); } return this->totalNodes; }
void SurfaceTensionBoundaryCondition :: computeLoadVectorFromElement(FloatArray &answer, Element *e, int side, TimeStep *tStep) { FEInterpolation *fei = e->giveInterpolation(); if ( !fei ) { OOFEM_ERROR("No interpolation or default integration available for element."); } std :: unique_ptr< IntegrationRule > iRule( fei->giveBoundaryIntegrationRule(fei->giveInterpolationOrder()-1, side) ); int nsd = e->giveDomain()->giveNumberOfSpatialDimensions(); if ( side == -1 ) { side = 1; } answer.clear(); if ( nsd == 2 ) { FEInterpolation2d *fei2d = static_cast< FEInterpolation2d * >(fei); ///@todo More of this grunt work should be moved to the interpolation classes IntArray bnodes; fei2d->boundaryGiveNodes(bnodes, side); int nodes = bnodes.giveSize(); FloatMatrix xy(2, nodes); for ( int i = 1; i <= nodes; i++ ) { Node *node = e->giveNode(bnodes.at(i)); ///@todo This should rely on the xindex and yindex in the interpolator.. xy.at(1, i) = node->giveCoordinate(1); xy.at(2, i) = node->giveCoordinate(2); } FloatArray tmp; // Integrand FloatArray es; // Tangent vector to curve FloatArray dNds; if ( e->giveDomain()->isAxisymmetric() ) { FloatArray N; FloatArray gcoords; for ( GaussPoint *gp: *iRule ) { fei2d->edgeEvaldNds( dNds, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); fei->boundaryEvalN( N, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); double J = fei->boundaryGiveTransformationJacobian( side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); fei->boundaryLocal2Global( gcoords, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); double r = gcoords(0); // First coordinate is the radial coord. es.beProductOf(xy, dNds); tmp.resize( 2 * nodes); for ( int i = 0; i < nodes; i++ ) { tmp(2 * i) = dNds(i) * es(0) * r + N(i); tmp(2 * i + 1) = dNds(i) * es(1) * r; } answer.add(- 2 * M_PI * gamma * J * gp->giveWeight(), tmp); } } else { for ( GaussPoint *gp: *iRule ) { double t = e->giveCrossSection()->give(CS_Thickness, gp); fei2d->edgeEvaldNds( dNds, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); double J = fei->boundaryGiveTransformationJacobian( side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); es.beProductOf(xy, dNds); tmp.resize( 2 * nodes); for ( int i = 0; i < nodes; i++ ) { tmp(2 * i) = dNds(i) * es(0); tmp(2 * i + 1) = dNds(i) * es(1); //B.at(1, 1+i*2) = B.at(2, 2+i*2) = dNds(i); } //tmp.beTProductOf(B, es); answer.add(- t * gamma * J * gp->giveWeight(), tmp); } } } else if ( nsd == 3 ) { FEInterpolation3d *fei3d = static_cast< FEInterpolation3d * >(fei); FloatArray n, surfProj; FloatMatrix dNdx, B; for ( GaussPoint *gp: *iRule ) { fei3d->surfaceEvaldNdx( dNdx, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); double J = fei->boundaryEvalNormal( n, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); // [I - n(x)n] in voigt form: surfProj = {1. - n(0)*n(0), 1. - n(1)*n(1), 1. - n(2)*n(2), - n(1)*n(2), - n(0)*n(2), - n(0)*n(1), }; // Construct B matrix of the surface nodes B.resize(6, 3 * dNdx.giveNumberOfRows()); for ( int i = 1; i <= dNdx.giveNumberOfRows(); i++ ) { B.at(1, 3 * i - 2) = dNdx.at(i, 1); B.at(2, 3 * i - 1) = dNdx.at(i, 2); B.at(3, 3 * i - 0) = dNdx.at(i, 3); B.at(5, 3 * i - 2) = B.at(4, 3 * i - 1) = dNdx.at(i, 3); B.at(6, 3 * i - 2) = B.at(4, 3 * i - 0) = dNdx.at(i, 2); B.at(6, 3 * i - 1) = B.at(5, 3 * i - 0) = dNdx.at(i, 1); } answer.plusProduct(B, surfProj, -gamma * J * gp->giveWeight() ); } } }
void SurfaceTensionBoundaryCondition :: computeTangentFromElement(FloatMatrix &answer, Element *e, int side, TimeStep *tStep) { FEInterpolation *fei = e->giveInterpolation(); if ( !fei ) { OOFEM_ERROR("No interpolation available for element."); } std :: unique_ptr< IntegrationRule > iRule( fei->giveBoundaryIntegrationRule(fei->giveInterpolationOrder()-1, side) ); int nsd = e->giveDomain()->giveNumberOfSpatialDimensions(); int nodes = e->giveNumberOfNodes(); if ( side == -1 ) { side = 1; } answer.clear(); if ( nsd == 2 ) { FEInterpolation2d *fei2d = static_cast< FEInterpolation2d * >(fei); ///@todo More of this grunt work should be moved to the interpolation classes FloatMatrix xy(2, nodes); Node *node; for ( int i = 1; i <= nodes; i++ ) { node = e->giveNode(i); xy.at(1, i) = node->giveCoordinate(1); xy.at(2, i) = node->giveCoordinate(2); } FloatArray tmpA(2 *nodes); FloatArray es; // Tangent vector to curve FloatArray dNds; FloatMatrix B(2, 2 *nodes); B.zero(); if ( e->giveDomain()->isAxisymmetric() ) { FloatArray N; FloatArray gcoords; FloatArray tmpB(2 *nodes); for ( GaussPoint *gp: *iRule ) { fei2d->edgeEvaldNds( dNds, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); fei->boundaryEvalN( N, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); double J = fei->boundaryGiveTransformationJacobian( side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); fei->boundaryLocal2Global( gcoords, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); double r = gcoords(0); // First coordinate is the radial coord. es.beProductOf(xy, dNds); // Construct the different matrices in the integrand; for ( int i = 0; i < nodes; i++ ) { tmpA(i * 2 + 0) = dNds(i) * es(0); tmpA(i * 2 + 1) = dNds(i) * es(1); tmpB(i * 2 + 0) = N(i); tmpB(i * 2 + 1) = 0; B(i * 2, 0) = B(i * 2 + 1, 1) = dNds(i); } double dV = 2 *M_PI *gamma *J *gp->giveWeight(); answer.plusDyadUnsym(tmpA, tmpB, dV); answer.plusDyadUnsym(tmpB, tmpA, dV); answer.plusProductSymmUpper(B, B, r * dV); answer.plusDyadUnsym(tmpA, tmpA, -r * dV); } } else { for ( GaussPoint *gp: *iRule ) { double t = e->giveCrossSection()->give(CS_Thickness, gp); ///@todo The thickness is not often relevant or used in FM. fei2d->edgeEvaldNds( dNds, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); double J = fei->boundaryGiveTransformationJacobian( side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); es.beProductOf(xy, dNds); // Construct the different matrices in the integrand; for ( int i = 0; i < nodes; i++ ) { tmpA(i * 2 + 0) = dNds(i) * es(0); tmpA(i * 2 + 1) = dNds(i) * es(1); B(i * 2, 0) = B(i * 2 + 1, 1) = dNds(i); } double dV = t * gamma * J * gp->giveWeight(); answer.plusProductSymmUpper(B, B, dV); answer.plusDyadSymmUpper(tmpA, -dV); } } answer.symmetrized(); } else if ( nsd == 3 ) { FEInterpolation3d *fei3d = static_cast< FEInterpolation3d * >(fei); OOFEM_ERROR("3D tangents not implemented yet."); //FloatMatrix tmp(3 *nodes, 3 *nodes); FloatMatrix dNdx; FloatArray n; for ( GaussPoint *gp: *iRule ) { fei3d->surfaceEvaldNdx( dNdx, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); /*double J = */ fei->boundaryEvalNormal( n, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); //double dV = gamma * J * gp->giveWeight(); for ( int i = 0; i < nodes; i++ ) { //tmp(3*i+0) = dNdx(i,0) - (dNdx(i,0)*n(0)* + dNdx(i,1)*n(1) + dNdx(i,2)*n(2))*n(0); //tmp(3*i+1) = dNdx(i,1) - (dNdx(i,0)*n(0)* + dNdx(i,1)*n(1) + dNdx(i,2)*n(2))*n(1); //tmp(3*i+2) = dNdx(i,2) - (dNdx(i,0)*n(0)* + dNdx(i,1)*n(1) + dNdx(i,2)*n(2))*n(2); } //answer.plusProductSymmUpper(A,B, dV); ///@todo Derive expressions for this. } } else { OOFEM_WARNING("Only 2D or 3D is possible!"); } }
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); }