void PrescribedGradientBCWeak :: assembleTangentGPContributionNew(FloatMatrix &oTangent, TracSegArray &iEl, GaussPoint &iGP, const double &iScaleFactor, const FloatArray &iBndCoord) { int dim = domain->giveNumberOfSpatialDimensions(); double detJ = 0.5 * iEl.giveLength(); ////////////////////////////////// // Compute traction N-matrix // For now, assume piecewise constant approx FloatArray Ntrac = FloatArray { 1.0 }; FloatMatrix NtracMat; NtracMat.beNMatrixOf(Ntrac, dim); ////////////////////////////////// // Compute displacement N-matrix // Identify the displacement element // we are currently standing in // and compute local coordinates on // the displacement element SpatialLocalizer *localizer = domain->giveSpatialLocalizer(); FloatArray dispElLocCoord, closestPoint; Element *dispEl = localizer->giveElementClosestToPoint(dispElLocCoord, closestPoint, iBndCoord ); // Compute basis functions XfemElementInterface *xfemElInt = dynamic_cast< XfemElementInterface * >( dispEl ); FloatMatrix NdispMat; if ( xfemElInt != NULL && domain->hasXfemManager() ) { // If the element is an XFEM element, we use the XfemElementInterface to compute the N-matrix // of the enriched element. xfemElInt->XfemElementInterface_createEnrNmatrixAt(NdispMat, dispElLocCoord, * dispEl, false); } else { // Otherwise, use the usual N-matrix. const int numNodes = dispEl->giveNumberOfDofManagers(); FloatArray N(numNodes); const int dim = dispEl->giveSpatialDimension(); NdispMat.resize(dim, dim * numNodes); NdispMat.zero(); dispEl->giveInterpolation()->evalN( N, dispElLocCoord, FEIElementGeometryWrapper(dispEl) ); NdispMat.beNMatrixOf(N, dim); } FloatMatrix contrib; contrib.beTProductOf(NtracMat, NdispMat); contrib.times( iScaleFactor * detJ * iGP.giveWeight() ); oTangent = contrib; }
void PrescribedGradientBCNeumann :: integrateTangent(FloatMatrix &oTangent, Element *e, int iBndIndex) { FloatArray normal, n; FloatMatrix nMatrix, E_n; FloatMatrix contrib; Domain *domain = e->giveDomain(); XfemElementInterface *xfemElInt = dynamic_cast< XfemElementInterface * >( e ); FEInterpolation *interp = e->giveInterpolation(); // Geometry interpolation int nsd = e->giveDomain()->giveNumberOfSpatialDimensions(); // Interpolation order int order = interp->giveInterpolationOrder(); IntegrationRule *ir = NULL; IntArray edgeNodes; FEInterpolation2d *interp2d = dynamic_cast< FEInterpolation2d * >( interp ); if ( interp2d == NULL ) { OOFEM_ERROR("failed to cast to FEInterpolation2d.") } interp2d->computeLocalEdgeMapping(edgeNodes, iBndIndex); const FloatArray &xS = * ( e->giveDofManager( edgeNodes.at(1) )->giveCoordinates() ); const FloatArray &xE = * ( e->giveDofManager( edgeNodes.at( edgeNodes.giveSize() ) )->giveCoordinates() ); if ( xfemElInt != NULL && domain->hasXfemManager() ) { std :: vector< Line >segments; std :: vector< FloatArray >intersecPoints; xfemElInt->partitionEdgeSegment(iBndIndex, segments, intersecPoints); MaterialMode matMode = e->giveMaterialMode(); ir = new DiscontinuousSegmentIntegrationRule(1, e, segments, xS, xE); int numPointsPerSeg = 1; ir->SetUpPointsOnLine(numPointsPerSeg, matMode); } else { ir = interp->giveBoundaryIntegrationRule(order, iBndIndex); } oTangent.clear(); for ( GaussPoint *gp: *ir ) { FloatArray &lcoords = * gp->giveNaturalCoordinates(); FEIElementGeometryWrapper cellgeo(e); // Evaluate the normal; double detJ = interp->boundaryEvalNormal(normal, iBndIndex, lcoords, cellgeo); interp->boundaryEvalN(n, iBndIndex, lcoords, cellgeo); // If cracks cross the edge, special treatment is necessary. // Exploit the XfemElementInterface to minimize duplication of code. if ( xfemElInt != NULL && domain->hasXfemManager() ) { // Compute global coordinates of Gauss point FloatArray globalCoord; interp->boundaryLocal2Global(globalCoord, iBndIndex, lcoords, cellgeo); // Compute local coordinates on the element FloatArray locCoord; e->computeLocalCoordinates(locCoord, globalCoord); xfemElInt->XfemElementInterface_createEnrNmatrixAt(nMatrix, locCoord, * e, false); } else { // Evaluate the velocity/displacement coefficients nMatrix.beNMatrixOf(n, nsd); } if ( nsd == 3 ) { OOFEM_ERROR("not implemented for nsd == 3.") } else if ( nsd == 2 ) { E_n.resize(4, 2); E_n.at(1, 1) = normal.at(1); E_n.at(1, 2) = 0.0; E_n.at(2, 1) = 0.0; E_n.at(2, 2) = normal.at(2); E_n.at(3, 1) = normal.at(2); E_n.at(3, 2) = 0.0; E_n.at(4, 1) = 0.0; E_n.at(4, 2) = normal.at(1); } else { E_n.clear(); } contrib.beProductOf(E_n, nMatrix); oTangent.add(detJ * gp->giveWeight(), contrib); } delete ir; }