void Tr1Darcy :: computeEdgeBCSubVectorAt(FloatArray &answer, Load *load, int iEdge, TimeStep *tStep) { /* * Given the load *load, return it's contribution. * */ answer.resize(3); answer.zero(); if ( load->giveType() == TransmissionBC ) { // Neumann boundary conditions (traction) BoundaryLoad *boundaryLoad; boundaryLoad = ( BoundaryLoad * ) load; int numberOfEdgeIPs; numberOfEdgeIPs = ( int ) ceil( ( boundaryLoad->giveApproxOrder() + 1. ) / 2. ) * 2; GaussIntegrationRule iRule(1, this, 1, 1); GaussPoint *gp; FloatArray N, loadValue, reducedAnswer; reducedAnswer.resize(3); reducedAnswer.zero(); IntArray mask; iRule.setUpIntegrationPoints(_Line, numberOfEdgeIPs, _Unknown); for ( int i = 0; i < iRule.getNumberOfIntegrationPoints(); i++ ) { gp = iRule.getIntegrationPoint(i); FloatArray *lcoords = gp->giveCoordinates(); this->interpolation_lin.edgeEvalN(N, *lcoords, FEIElementGeometryWrapper(this)); double dV = this->computeEdgeVolumeAround(gp, iEdge); if ( boundaryLoad->giveFormulationType() == BoundaryLoad :: BL_EntityFormulation ) { // Edge load in xi-eta system boundaryLoad->computeValueAt(loadValue, tStep, *lcoords, VM_Total); } else { // Edge load in x-y system FloatArray gcoords; this->interpolation_lin.edgeLocal2global(gcoords, iEdge, *lcoords, FEIElementGeometryWrapper(this)); boundaryLoad->computeValueAt(loadValue, tStep, gcoords, VM_Total); } reducedAnswer.add(loadValue.at(1) * dV, N); } this->interpolation_lin.computeLocalEdgeMapping(mask, iEdge); answer.assemble(reducedAnswer, mask); } }
void Tet21Stokes :: computeBoundaryLoadVector(FloatArray &answer, BoundaryLoad *load, int iSurf, CharType type, ValueModeType mode, TimeStep *tStep) { if ( type != ExternalForcesVector ) { answer.clear(); return; } answer.resize(34); answer.zero(); if ( load->giveType() == TransmissionBC ) { // Neumann boundary conditions (traction) int numberOfSurfaceIPs = ( int ) ceil( ( load->giveApproxOrder() + 1. ) / 2. ) * 2; ///@todo Check this. GaussIntegrationRule iRule(1, this, 1, 1); FloatArray N, t, f(18); f.zero(); iRule.SetUpPointsOnTriangle(numberOfSurfaceIPs, _Unknown); for ( GaussPoint *gp: iRule ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); this->interpolation_quad.surfaceEvalN( N, iSurf, lcoords, FEIElementGeometryWrapper(this) ); double dA = gp->giveWeight() * this->interpolation_quad.surfaceGiveTransformationJacobian( iSurf, lcoords, FEIElementGeometryWrapper(this) ); if ( load->giveFormulationType() == Load :: FT_Entity ) { // load in xi-eta system load->computeValueAt(t, tStep, lcoords, VM_Total); } else { // Edge load in x-y system FloatArray gcoords; this->interpolation_quad.surfaceLocal2global( gcoords, iSurf, lcoords, FEIElementGeometryWrapper(this) ); load->computeValueAt(t, tStep, gcoords, VM_Total); } // Reshape the vector for ( int j = 0; j < N.giveSize(); j++ ) { f(3 * j + 0) += N(j) * t(0) * dA; f(3 * j + 1) += N(j) * t(1) * dA; f(3 * j + 2) += N(j) * t(2) * dA; } } answer.assemble(f, this->surf_ordering [ iSurf - 1 ]); } else { OOFEM_ERROR("Strange boundary condition type"); } }
void Tr21Stokes :: computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global) { if ( type != ExternalForcesVector ) { answer.clear(); return; } if ( load->giveType() == TransmissionBC ) { // Neumann boundary conditions (traction) int numberOfEdgeIPs = ( int ) ceil( ( load->giveApproxOrder() + 1. ) / 2. ) * 2; GaussIntegrationRule iRule(1, this, 1, 1); FloatArray N, t, f(6); f.zero(); iRule.SetUpPointsOnLine(numberOfEdgeIPs, _Unknown); for ( GaussPoint *gp: iRule ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); this->interpolation_quad.edgeEvalN( N, boundary, lcoords, FEIElementGeometryWrapper(this) ); double detJ = fabs( this->interpolation_quad.boundaryGiveTransformationJacobian( boundary, lcoords, FEIElementGeometryWrapper(this) ) ); double dS = gp->giveWeight() * detJ; if ( load->giveFormulationType() == Load :: FT_Entity ) { // Edge load in xi-eta system load->computeValueAt(t, tStep, lcoords, VM_Total); } else { // Edge load in x-y system FloatArray gcoords; this->interpolation_quad.boundaryLocal2Global( gcoords, boundary, lcoords, FEIElementGeometryWrapper(this) ); load->computeValueAt(t, tStep, gcoords, VM_Total); } // Reshape the vector for ( int j = 0; j < 3; j++ ) { f(2 * j) += N(j) * t(0) * dS; f(2 * j + 1) += N(j) * t(1) * dS; } } answer.resize(15); answer.zero(); answer.assemble(f, this->edge_ordering [ boundary - 1 ]); } else { OOFEM_ERROR("Strange boundary condition type"); } }
void Tr21Stokes :: computeEdgeBCSubVectorAt(FloatArray &answer, Load *load, int iEdge, TimeStep *tStep) { answer.resize(15); answer.zero(); if ( load->giveType() == TransmissionBC ) { // Neumann boundary conditions (traction) BoundaryLoad *boundaryLoad = ( BoundaryLoad * ) load; int numberOfEdgeIPs = ( int ) ceil( ( boundaryLoad->giveApproxOrder() + 1. ) / 2. ) * 2; GaussIntegrationRule iRule(1, this, 1, 1); GaussPoint *gp; FloatArray N, t, f(6); IntArray edge_mapping; f.zero(); iRule.setUpIntegrationPoints(_Line, numberOfEdgeIPs, _Unknown); for ( int i = 0; i < iRule.getNumberOfIntegrationPoints(); i++ ) { gp = iRule.getIntegrationPoint(i); FloatArray *lcoords = gp->giveCoordinates(); this->interpolation_quad.edgeEvalN(N, * lcoords, FEIElementGeometryWrapper(this)); double detJ = fabs(this->interpolation_quad.edgeGiveTransformationJacobian(iEdge, * lcoords, FEIElementGeometryWrapper(this))); double dS = gp->giveWeight() * detJ; if ( boundaryLoad->giveFormulationType() == BoundaryLoad :: BL_EntityFormulation ) { // Edge load in xi-eta system boundaryLoad->computeValueAt(t, tStep, * lcoords, VM_Total); } else { // Edge load in x-y system FloatArray gcoords; this->interpolation_quad.edgeLocal2global(gcoords, iEdge, * lcoords, FEIElementGeometryWrapper(this)); boundaryLoad->computeValueAt(t, tStep, gcoords, VM_Total); } // Reshape the vector for ( int j = 0; j < 3; j++ ) { f(2 * j) += N(j) * t(0) * dS; f(2 * j + 1) += N(j) * t(1) * dS; } } answer.assemble(f, this->edge_ordering [ iEdge - 1 ]); } else { OOFEM_ERROR("Tr21Stokes :: computeEdgeBCSubVectorAt - Strange boundary condition type"); } }
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 SolutionbasedShapeFunction :: computeCorrectionFactors(modeStruct &myMode, IntArray *Dofs, double *am, double *ap) { /* * *Compute c0, cp, cm, Bp, Bm, Ap and Am */ double A0p = 0.0, App = 0.0, A0m = 0.0, Amm = 0.0, Bp = 0.0, Bm = 0.0, c0 = 0.0, cp = 0.0, cm = 0.0; EngngModel *m = myMode.myEngngModel; Set *mySet = m->giveDomain(1)->giveSet(externalSet); IntArray BoundaryList = mySet->giveBoundaryList(); for ( int i = 0; i < BoundaryList.giveSize() / 2; i++ ) { int ElementID = BoundaryList(2 * i); int Boundary = BoundaryList(2 * i + 1); Element *thisElement = m->giveDomain(1)->giveElement(ElementID); FEInterpolation *geoInterpolation = thisElement->giveInterpolation(); IntArray bnodes, zNodes, pNodes, mNodes; FloatMatrix nodeValues; geoInterpolation->boundaryGiveNodes(bnodes, Boundary); nodeValues.resize( this->dofs.giveSize(), bnodes.giveSize() ); nodeValues.zero(); // Change to global ID for bnodes and identify the intersection of bnodes and the zero boundary splitBoundaryNodeIDs(myMode, * thisElement, bnodes, pNodes, mNodes, zNodes, nodeValues); std :: unique_ptr< IntegrationRule >iRule(geoInterpolation->giveBoundaryIntegrationRule(order, Boundary)); for ( GaussPoint *gp: *iRule ) { FloatArray *lcoords = gp->giveCoordinates(); FloatArray gcoords, normal, N; FloatArray Phi; double detJ = fabs( geoInterpolation->boundaryGiveTransformationJacobian( Boundary, * lcoords, FEIElementGeometryWrapper(thisElement) ) ) * gp->giveWeight(); geoInterpolation->boundaryEvalNormal( normal, Boundary, * lcoords, FEIElementGeometryWrapper(thisElement) ); geoInterpolation->boundaryEvalN( N, Boundary, * lcoords, FEIElementGeometryWrapper(thisElement) ); geoInterpolation->boundaryLocal2Global( gcoords, Boundary, * lcoords, FEIElementGeometryWrapper(thisElement) ); FloatArray pPhi, mPhi, zPhi; pPhi.resize( Dofs->giveSize() ); pPhi.zero(); mPhi.resize( Dofs->giveSize() ); mPhi.zero(); zPhi.resize( Dofs->giveSize() ); zPhi.zero(); // Build phi (analytical averaging, not projected onto the mesh) computeBaseFunctionValueAt(Phi, gcoords, * Dofs, * myMode.myEngngModel); // Build zPhi for this DofID for ( int l = 1; l <= zNodes.giveSize(); l++ ) { int nodeID = zNodes.at(l); for ( int m = 1; m <= this->dofs.giveSize(); m++ ) { zPhi.at(m) = zPhi.at(m) + N.at(nodeID) * nodeValues.at(m, nodeID); } } // Build pPhi for this DofID for ( int l = 1; l <= pNodes.giveSize(); l++ ) { int nodeID = pNodes.at(l); for ( int m = 1; m <= this->dofs.giveSize(); m++ ) { pPhi.at(m) = pPhi.at(m) + N.at(nodeID) * nodeValues.at(m, nodeID); } } // Build mPhi for this DofID for ( int l = 1; l <= mNodes.giveSize(); l++ ) { int nodeID = mNodes.at(l); for ( int m = 1; m <= this->dofs.giveSize(); m++ ) { mPhi.at(m) = mPhi.at(m) + N.at(nodeID) * nodeValues.at(m, nodeID); } } c0 = c0 + zPhi.dotProduct(normal, 3) * detJ; cp = cp + pPhi.dotProduct(normal, 3) * detJ; cm = cm + mPhi.dotProduct(normal, 3) * detJ; App = App + pPhi.dotProduct(pPhi, 3) * detJ; Amm = Amm + mPhi.dotProduct(mPhi, 3) * detJ; A0p = A0p + zPhi.dotProduct(pPhi, 3) * detJ; A0m = A0m + zPhi.dotProduct(mPhi, 3) * detJ; Bp = Bp + Phi.dotProduct(pPhi, 3) * detJ; Bm = Bm + Phi.dotProduct(mPhi, 3) * detJ; } } * am = -( A0m * cp * cp - Bm * cp * cp - A0p * cm * cp + App * c0 * cm + Bp * cm * cp ) / ( App * cm * cm + Amm * cp * cp ); * ap = -( A0p * cm * cm - Bp * cm * cm - A0m * cm * cp + Amm * c0 * cp + Bm * cm * cp ) / ( App * cm * cm + Amm * cp * cp ); }