double FEI2dLineLin :: edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { normal.resize(2); normal.at(1) = cellgeo.giveVertexCoordinates(2)->at(xind) - cellgeo.giveVertexCoordinates(1)->at(xind); normal.at(2) = -(cellgeo.giveVertexCoordinates(2)->at(yind) - cellgeo.giveVertexCoordinates(1)->at(yind)); return normal.normalize()*0.5; }
double FEI2dLineLin :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) { double x2_x1, y2_y1; x2_x1 = cellgeo.giveVertexCoordinates(2)->at(xind) - cellgeo.giveVertexCoordinates(1)->at(xind); y2_y1 = cellgeo.giveVertexCoordinates(2)->at(yind) - cellgeo.giveVertexCoordinates(1)->at(yind); return sqrt(x2_x1*x2_x1 + y2_y1*y2_y1)/2.0; }
double FEI2dLineLin :: edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo) { double x2_x1, y2_y1; x2_x1 = cellgeo.giveVertexCoordinates(2)->at(xind) - cellgeo.giveVertexCoordinates(1)->at(xind); y2_y1 = cellgeo.giveVertexCoordinates(2)->at(yind) - cellgeo.giveVertexCoordinates(1)->at(yind); return sqrt(x2_x1*x2_x1 + y2_y1*y2_y1); }
void FEI3dLineLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { double ksi; FloatArray n(2); ksi = lcoords.at(1); answer.beScaled( ( 1. - ksi ) * 0.5, *cellgeo.giveVertexCoordinates(1) ); answer.add( ( 1. + ksi ) * 0.5, *cellgeo.giveVertexCoordinates(2) ); }
void FEI2dLineLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { FloatArray n; this->evalN(n, lcoords, cellgeo); answer.resize(max(xind,yind)); answer.zero(); answer.at(xind) = ( n(0) * cellgeo.giveVertexCoordinates(1)->at(xind) + n(1) * cellgeo.giveVertexCoordinates(2)->at(xind) ); answer.at(yind) = ( n(0) * cellgeo.giveVertexCoordinates(1)->at(yind) + n(1) * cellgeo.giveVertexCoordinates(2)->at(yind) ); }
double FEI2dQuadLin :: edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo) { double dx, dy; int nodeA, nodeB; nodeA = edgeNodes.at(1); nodeB = edgeNodes.at(2); dx = cellgeo.giveVertexCoordinates(nodeB)->at(xind) - cellgeo.giveVertexCoordinates(nodeA)->at(xind); dy = cellgeo.giveVertexCoordinates(nodeB)->at(yind) - cellgeo.giveVertexCoordinates(nodeA)->at(yind); return sqrt(dx * dx + dy * dy); }
int FEI3dLineLin :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) { FloatArray vec, x; vec.beDifferenceOf(*cellgeo.giveVertexCoordinates(2), *cellgeo.giveVertexCoordinates(1)); x.beDifferenceOf(coords, *cellgeo.giveVertexCoordinates(1)); double l2 = vec.computeSquaredNorm(); double xvec = x.dotProduct(vec); answer.setValues(1, 2.0 * xvec / l2 - 1.0); answer.at(1) = clamp(answer.at(1), -1.0, 1.0); return false; // No point to check if point is "inside". }
void FEI2dQuadConst :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { answer.resize(2); answer.at(1) = 0.25*( cellgeo.giveVertexCoordinates(1)->at(xind) + cellgeo.giveVertexCoordinates(2)->at(xind) + cellgeo.giveVertexCoordinates(3)->at(xind) + cellgeo.giveVertexCoordinates(4)->at(xind) ); answer.at(2) = 0.25*( cellgeo.giveVertexCoordinates(1)->at(yind) + cellgeo.giveVertexCoordinates(2)->at(yind) + cellgeo.giveVertexCoordinates(3)->at(yind) + cellgeo.giveVertexCoordinates(4)->at(yind) ); }
double FEI2dQuadLin :: edgeEvalNormal(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { int nodeA, nodeB; IntArray edgeNodes; this->computeLocalEdgeMapping(edgeNodes, iedge); nodeA = edgeNodes.at(1); nodeB = edgeNodes.at(2); answer.resize(2); answer.at(1) = -(cellgeo.giveVertexCoordinates(nodeB)->at(yind) - cellgeo.giveVertexCoordinates(nodeA)->at(yind) ); answer.at(2) = (cellgeo.giveVertexCoordinates(nodeB)->at(xind) - cellgeo.giveVertexCoordinates(nodeA)->at(xind) ); return answer.normalize() * 0.5; }
void FEI2dQuadLin :: edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { IntArray edgeNodes; FloatArray n; this->computeLocalEdgeMapping(edgeNodes, iedge); this->edgeEvalN(n, iedge, lcoords, cellgeo); answer.resize(2); answer.at(1) = ( n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(xind) + n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(xind) ); answer.at(2) = ( n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(yind) + n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(yind) ); }
double FEI2dLineLin :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) { const FloatArray *node; double x1, x2, y1, y2; node = cellgeo.giveVertexCoordinates(1); x1 = node->at(xind); y1 = node->at(yind); node = cellgeo.giveVertexCoordinates(2); x2 = node->at(xind); y2 = node->at(yind); return x2 * y1 - x1 * y2; }
double FEI2dQuadLin :: giveArea(const FEICellGeometry &cellgeo) const { const FloatArray *node1 = cellgeo.giveVertexCoordinates(1); const FloatArray *node2 = cellgeo.giveVertexCoordinates(2); const FloatArray *node3 = cellgeo.giveVertexCoordinates(3); const FloatArray *node4 = cellgeo.giveVertexCoordinates(4); double x13 = node1->at(xind) - node3->at(xind); double y13 = node1->at(yind) - node3->at(yind); double x24 = node2->at(xind) - node4->at(xind); double y24 = node2->at(yind) - node4->at(yind); return fabs( 0.5 * ( x13 * y24 - x24 * y13 ) ); }
double FEI3dWedgeLin :: giveCharacteristicLength(const FEICellGeometry &cellgeo) const { const FloatArray *n1 = cellgeo.giveVertexCoordinates(1); const FloatArray *n2 = cellgeo.giveVertexCoordinates(6); ///@todo Change this so that it is not dependent on node order. return n1->distance(n2); }
double FEI3dHexaLin :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { FloatArray a, b, dNdksi(4), dNdeta(4); double ksi, eta; IntArray snodes; this->computeLocalSurfaceMapping(snodes, isurf); ksi = lcoords.at(1); eta = lcoords.at(2); // No need to divide by 1/4, we'll normalize anyway; dNdksi.at(1) = ( 1. + eta ); dNdksi.at(2) = -( 1. + eta ); dNdksi.at(3) = -( 1. - eta ); dNdksi.at(4) = ( 1. - eta ); dNdeta.at(1) = ( 1. + ksi ); dNdeta.at(2) = ( 1. - ksi ); dNdeta.at(3) = -( 1. - ksi ); dNdeta.at(4) = -( 1. + ksi ); for (int i = 1; i <= 4; ++i) { a.add(dNdksi.at(i), *cellgeo.giveVertexCoordinates(snodes.at(i))); b.add(dNdeta.at(i), *cellgeo.giveVertexCoordinates(snodes.at(i))); } answer.beVectorProductOf(a, b); return answer.normalize()*0.0625; }
void FEI2dTrQuad :: evald2Ndx2(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { double x1, x2, x3, y1, y2, y3, y23, x32, y31, x13, area; answer.resize(6, 3); x1 = cellgeo.giveVertexCoordinates(1)->at(xind); x2 = cellgeo.giveVertexCoordinates(2)->at(xind); x3 = cellgeo.giveVertexCoordinates(3)->at(xind); y1 = cellgeo.giveVertexCoordinates(1)->at(yind); y2 = cellgeo.giveVertexCoordinates(2)->at(yind); y3 = cellgeo.giveVertexCoordinates(3)->at(yind); area = 0.5 * ( x2 * y3 + x1 * y2 + y1 * x3 - x2 * y1 - x3 * y2 - x1 * y3 ); y23 = ( y2 - y3 ) / ( 2. * area ); x32 = ( x3 - x2 ) / ( 2. * area ); y31 = ( y3 - y1 ) / ( 2. * area ); x13 = ( x1 - x3 ) / ( 2. * area ); answer.at(1, 1) = 4 * y23 * y23; answer.at(1, 2) = 4 * x32 * x32; answer.at(1, 3) = 4 * y23 * x32; answer.at(2, 1) = 4 * y31 * y31; answer.at(2, 2) = 4 * x13 * x13; answer.at(2, 3) = 4 * y31 * x13; answer.at(3, 1) = 4 * y23 * y23 + 8 * y31 * y23 + 4 * y31 * y31; answer.at(3, 2) = 4 * x32 * x32 + 8 * x13 * x32 + 4 * x13 * x13; answer.at(3, 3) = 4 * y23 * x32 + 4 * y31 * x32 + 4 * y23 * x13 + 4 * y31 * x13; answer.at(4, 1) = 8 * y31 * y23; answer.at(4, 2) = 8 * x13 * x32; answer.at(4, 3) = 4 * y31 * x32 + 4 * y23 * x13; answer.at(5, 1) = ( -8 ) * y31 * y23 + ( -8 ) * y31 * y31; answer.at(5, 2) = ( -8 ) * x13 * x32 + ( -8 ) * x13 * x13; answer.at(5, 3) = ( -4 ) * y31 * x32 + ( -4 ) * y23 * x13 + ( -8 ) * y31 * x13; answer.at(6, 1) = ( -8 ) * y23 * y23 + ( -8 ) * y31 * y23; answer.at(6, 2) = ( -8 ) * x32 * x32 + ( -8 ) * x13 * x32; answer.at(6, 3) = ( -8 ) * y23 * x32 + ( -4 ) * y31 * x32 + ( -4 ) * y23 * x13; }
void FEI2dLineLin :: edgeEvaldNds(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { double xi = lcoords(0); answer.resize(2); answer(0) = -0.5*xi; answer(1) = 0.5*xi; double es1 = answer(0)*cellgeo.giveVertexCoordinates(1)->at(xind) + answer(1)*cellgeo.giveVertexCoordinates(2)->at(xind); double es2 = answer(0)*cellgeo.giveVertexCoordinates(1)->at(yind) + answer(1)*cellgeo.giveVertexCoordinates(2)->at(yind); double J = sqrt(es1*es1+es2*es2); answer.times(1/J); //return J; }
int FEI2dLineLin :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) { double xi; double x2_x1, y2_y1; x2_x1 = cellgeo.giveVertexCoordinates(2)->at(xind) - cellgeo.giveVertexCoordinates(1)->at(xind); y2_y1 = cellgeo.giveVertexCoordinates(2)->at(yind) - cellgeo.giveVertexCoordinates(1)->at(yind); // Projection of the global coordinate gives the value interpolated in [0,1]. xi = (x2_x1*gcoords(0) + y2_y1*gcoords(1))/(sqrt(x2_x1*x2_x1 + y2_y1*y2_y1)); // Map to [-1,1] domain. xi = xi*2 - 1; answer.resize(1); answer(0) = clamp(xi, -1., 1.); return false; }
void FEI3dHexaLin :: surfaceLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { IntArray nodes; FloatArray n; this->computeLocalSurfaceMapping(nodes, iedge); this->surfaceEvalN(n, lcoords, cellgeo); answer.resize(3); answer.at(1) = n.at(1) * cellgeo.giveVertexCoordinates( nodes.at(1) )->at(1) + n.at(2) *cellgeo.giveVertexCoordinates( nodes.at(2) )->at(1) + n.at(3) * cellgeo.giveVertexCoordinates( nodes.at(3) )->at(1) + n.at(4) *cellgeo.giveVertexCoordinates( nodes.at(4) )->at(1); answer.at(2) = n.at(1) * cellgeo.giveVertexCoordinates( nodes.at(1) )->at(2) + n.at(2) *cellgeo.giveVertexCoordinates( nodes.at(2) )->at(2) + n.at(3) * cellgeo.giveVertexCoordinates( nodes.at(3) )->at(2) + n.at(4) *cellgeo.giveVertexCoordinates( nodes.at(4) )->at(2); answer.at(3) = n.at(1) * cellgeo.giveVertexCoordinates( nodes.at(1) )->at(3) + n.at(2) *cellgeo.giveVertexCoordinates( nodes.at(2) )->at(3) + n.at(3) * cellgeo.giveVertexCoordinates( nodes.at(3) )->at(3) + n.at(4) *cellgeo.giveVertexCoordinates( nodes.at(4) )->at(3); }
double FEI2dQuadLin :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) { IntArray eNodes; const FloatArray *node; double x1, x2, y1, y2; this->computeLocalEdgeMapping(eNodes, iEdge); node = cellgeo.giveVertexCoordinates( eNodes.at(1) ); x1 = node->at(xind); y1 = node->at(yind); node = cellgeo.giveVertexCoordinates( eNodes.at(2) ); x2 = node->at(xind); y2 = node->at(yind); return -( x2 * y1 - x1 * y2 ); }
void FEI3dTetQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { FloatArray N; this->evalN(N, lcoords, cellgeo); answer.resize(0); for ( int i = 1; i <= N.giveSize(); i++ ) { answer.add( N(i), *cellgeo.giveVertexCoordinates(i)); } }
void FEI3dTrQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { FloatArray n; this->evalN(n, lcoords, cellgeo); answer.clear(); for ( int i = 1; i <= 6; ++i ) { answer.add( n.at(i), * cellgeo.giveVertexCoordinates(i) ); } }
int FEI3dTrQuad :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) { //OOFEM_ERROR("FEI3dTrQuad :: global2local - Not supported"); //return -1; ///@todo this is for linear triangle int xind = 1; int yind = 2; double detJ, x1, x2, x3, y1, y2, y3; answer.resize(3); x1 = cellgeo.giveVertexCoordinates(1)->at(xind); x2 = cellgeo.giveVertexCoordinates(2)->at(xind); x3 = cellgeo.giveVertexCoordinates(3)->at(xind); y1 = cellgeo.giveVertexCoordinates(1)->at(yind); y2 = cellgeo.giveVertexCoordinates(2)->at(yind); y3 = cellgeo.giveVertexCoordinates(3)->at(yind); detJ = x1*(y2 - y3) + x2*(-y1 + y3) + x3*(y1 - y2); answer.at(1) = ( ( x2 * y3 - x3 * y2 ) + ( y2 - y3 ) * gcoords.at(xind) + ( x3 - x2 ) * gcoords.at(yind) ) / detJ; answer.at(2) = ( ( x3 * y1 - x1 * y3 ) + ( y3 - y1 ) * gcoords.at(xind) + ( x1 - x3 ) * gcoords.at(yind) ) / detJ; answer.at(3) = 1. - answer.at(1) - answer.at(2); // check if point is inside bool inside = true; for ( int i = 1; i <= 3; i++ ) { if ( answer.at(i) < ( 0. - POINT_TOL ) ) { answer.at(i) = 0.; inside = false; } else if ( answer.at(i) > ( 1. + POINT_TOL ) ) { answer.at(i) = 1.; inside = false; } } return inside; }
void FEI3dHexaLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { FloatArray n; this->evalN(n, lcoords, cellgeo); answer.resize(0); for (int i = 1; i <= 8; i++ ) { answer.add(n.at(i), *cellgeo.giveVertexCoordinates(i)); } }
double FEI3dLineLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { ///@todo Not clear what this function should return. Just dNds would make sense if the caller defines a local coordinate system. FloatArray vec; vec.beDifferenceOf(*cellgeo.giveVertexCoordinates(2), *cellgeo.giveVertexCoordinates(1)); double detJ = vec.computeSquaredNorm() * 0.5; double l2_inv = 0.5 / detJ; answer.resize(2, 3); answer.at(1, 1) = -vec.at(1)*l2_inv; answer.at(2, 1) = vec.at(1)*l2_inv; answer.at(1, 2) = -vec.at(2)*l2_inv; answer.at(2, 2) = vec.at(2)*l2_inv; answer.at(1, 3) = -vec.at(3)*l2_inv; answer.at(2, 3) = vec.at(3)*l2_inv; return detJ; }
void FEI2dQuadLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { const double &ksi = lcoords.at(1); const double &eta = lcoords.at(2); const double n1 = ( 1. + ksi ) * ( 1. + eta ) * 0.25; const double n2 = ( 1. - ksi ) * ( 1. + eta ) * 0.25; const double n3 = ( 1. - ksi ) * ( 1. - eta ) * 0.25; const double n4 = ( 1. + ksi ) * ( 1. - eta ) * 0.25; const FloatArray* const p1 = cellgeo.giveVertexCoordinates(1); const FloatArray* const p2 = cellgeo.giveVertexCoordinates(2); const FloatArray* const p3 = cellgeo.giveVertexCoordinates(3); const FloatArray* const p4 = cellgeo.giveVertexCoordinates(4); answer = {n1 * p1->at(xind) + n2 * p2->at(xind) + n3 * p3->at(xind) + n4 * p4->at(xind), n1 * p1->at(yind) + n2 * p2->at(yind) + n3 * p3->at(yind) + n4 * p4->at(yind)} ; }
void FEI3dWedgeLin :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) // Returns the jacobian matrix J (x,y,z)/(ksi,eta,dzeta) of the receiver. { FloatMatrix dNduvw, coords; this->giveLocalDerivative(dNduvw, lcoords); coords.resize(3, 6); for ( int i = 1; i <= 6; i++ ) { coords.setColumn(* cellgeo.giveVertexCoordinates(i), i); } jacobianMatrix.beProductOf(coords, dNduvw); }
double FEI2dTrQuad :: edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { IntArray edgeNodes; this->computeLocalEdgeMapping(edgeNodes, iedge); double xi = lcoords(0); double dN1dxi = -0.5 + xi; double dN2dxi = 0.5 + xi; double dN3dxi = -2.0 * xi; normal.resize(2); normal.at(1) = dN1dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(yind) + dN2dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(yind) + dN3dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(3) )->at(yind); normal.at(2) = -dN1dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(xind) + - dN2dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(xind) + - dN3dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(3) )->at(xind); return normal.normalize(); }
double FEI3dTrQuad :: giveArea(const FEICellGeometry &cellgeo) const { ///@todo this only correct for a planar triangle in the xy-plane const FloatArray *p; double x1, x2, x3, x4, x5, x6, y1, y2, y3, y4, y5, y6; p = cellgeo.giveVertexCoordinates(1); x1 = p->at(1); y1 = p->at(2); p = cellgeo.giveVertexCoordinates(2); x2 = p->at(1); y2 = p->at(2); p = cellgeo.giveVertexCoordinates(3); x3 = p->at(1); y3 = p->at(2); p = cellgeo.giveVertexCoordinates(4); x4 = p->at(1); y4 = p->at(2); p = cellgeo.giveVertexCoordinates(5); x5 = p->at(1); y5 = p->at(2); p = cellgeo.giveVertexCoordinates(6); x6 = p->at(1); y6 = p->at(2); return (4*(-(x4*y1) + x6*y1 + x4*y2 - x5*y2 + x5*y3 - x6*y3) + x2*(y1 - y3 - 4*y4 + 4*y5) + x1*(-y2 + y3 + 4*y4 - 4*y6) + x3*(-y1 + y2 - 4*y5 + 4*y6))/6; }
double FEI2dTrQuad :: giveArea(const FEICellGeometry &cellgeo) const { const FloatArray *p; double x1, x2, x3, x4, x5, x6, y1, y2, y3, y4, y5, y6; p = cellgeo.giveVertexCoordinates(1); x1 = p->at(1); y1 = p->at(2); p = cellgeo.giveVertexCoordinates(2); x2 = p->at(1); y2 = p->at(2); p = cellgeo.giveVertexCoordinates(3); x3 = p->at(1); y3 = p->at(2); p = cellgeo.giveVertexCoordinates(4); x4 = p->at(1); y4 = p->at(2); p = cellgeo.giveVertexCoordinates(5); x5 = p->at(1); y5 = p->at(2); p = cellgeo.giveVertexCoordinates(6); x6 = p->at(1); y6 = p->at(2); return fabs( ( 4 * ( -( x4 * y1 ) + x6 * y1 + x4 * y2 - x5 * y2 + x5 * y3 - x6 * y3 ) + x2 * ( y1 - y3 - 4 * y4 + 4 * y5 ) + x1 * ( -y2 + y3 + 4 * y4 - 4 * y6 ) + x3 * ( -y1 + y2 - 4 * y5 + 4 * y6 ) ) / 6 ); }
void FEI3dTrQuad :: surfaceLocal2global(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { //Note: This gives the coordinate in the reference system FloatArray N; this->surfaceEvalN(N, isurf, lcoords, cellgeo); answer.clear(); for ( int i = 0; i < N.giveSize(); ++i ) { answer.add( N(i), * cellgeo.giveVertexCoordinates(i) ); } }