void TrPlanestressRotAllman :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) // Returns the displacement interpolation matrix {N} of the receiver, eva- // luated at gp. { FloatArray L, n; std::vector< FloatArray > lxy; answer.resize(3, 9); answer.zero(); this->computeLocalNodalCoordinates(lxy); // get ready for tranformation into 3d this->qinterpolation.evalN( n, iLocCoord, FEIVertexListGeometryWrapper(lxy) ); this->interp.evalN( L, iLocCoord, FEIVertexListGeometryWrapper(lxy)); answer.at(1, 1) = answer.at(2, 2) = n.at(1) + n.at(4) / 2. + n.at(6) / 2.; answer.at(1, 4) = answer.at(2, 5) = n.at(2) + n.at(4) / 2. + n.at(5) / 2.; answer.at(1, 7) = answer.at(2, 8) = n.at(3) + n.at(5) / 2. + n.at(6) / 2.; answer.at(1, 3) = n.at(6) * ( lxy [ 0 ].at(2) - lxy [ 2 ].at(2) ) / 8.0 - n.at(4) * ( lxy [ 1 ].at(2) - lxy [ 0 ].at(2) ) / 8.0; answer.at(1, 6) = n.at(4) * ( lxy [ 1 ].at(2) - lxy [ 0 ].at(2) ) / 8.0 - n.at(5) * ( lxy [ 2 ].at(2) - lxy [ 1 ].at(2) ) / 8.0; answer.at(1, 9) = n.at(5) * ( lxy [ 2 ].at(2) - lxy [ 1 ].at(2) ) / 8.0 - n.at(6) * ( lxy [ 0 ].at(2) - lxy [ 2 ].at(2) ) / 8.0; answer.at(2, 3) = -n.at(6) * ( lxy [ 0 ].at(1) - lxy [ 2 ].at(1) ) / 8.0 + n.at(4) * ( lxy [ 1 ].at(1) - lxy [ 0 ].at(1) ) / 8.0; answer.at(2, 6) = -n.at(4) * ( lxy [ 1 ].at(1) - lxy [ 0 ].at(1) ) / 8.0 + n.at(5) * ( lxy [ 2 ].at(1) - lxy [ 1 ].at(1) ) / 8.0; answer.at(2, 9) = -n.at(5) * ( lxy [ 2 ].at(1) - lxy [ 1 ].at(1) ) / 8.0 + n.at(6) * ( lxy [ 0 ].at(1) - lxy [ 2 ].at(1) ) / 8.0; // linear approx for rotations answer.at(3, 3) = L.at(1); answer.at(3, 6) = L.at(2); answer.at(3, 9) = L.at(3); }
void Quad1MindlinShell3D :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) { FloatArray n, ns; FloatMatrix dn, dns; const FloatArray &localCoords = * gp->giveNaturalCoordinates(); this->interp.evaldNdx( dn, localCoords, FEIVertexListGeometryWrapper(lnodes) ); this->interp.evalN( n, localCoords, FEIVoidCellGeometry() ); answer.resize(8, 4 * 5); answer.zero(); // enforce one-point reduced integration if requested if ( this->reducedIntegrationFlag ) { FloatArray lc(2); lc.zero(); // set to element center coordinates this->interp.evaldNdx( dns, lc, FEIVertexListGeometryWrapper(lnodes) ); this->interp.evalN( ns, lc, FEIVoidCellGeometry() ); } else { dns = dn; ns = n; } // Note: This is just 5 dofs (sixth column is all zero, torsional stiffness handled separately.) for ( int i = 0; i < 4; ++i ) { ///@todo Check the rows for both parts here, to be consistent with _3dShell material definition // Part related to the membrane (columns represent coefficients for D_u, D_v) answer(0, 0 + i * 5) = dn(i, 0);//eps_x = du/dx answer(1, 1 + i * 5) = dn(i, 1);//eps_y = dv/dy answer(2, 0 + i * 5) = dn(i, 1);//gamma_xy = du/dy+dv/dx answer(2, 1 + i * 5) = dn(i, 0); // Part related to the plate (columns represent the dofs D_w, R_u, R_v) ///@todo Check sign here answer(3 + 0, 2 + 2 + i * 5) = dn(i, 0);// kappa_x = d(fi_y)/dx answer(3 + 1, 2 + 1 + i * 5) =-dn(i, 1);// kappa_y = -d(fi_x)/dy answer(3 + 2, 2 + 2 + i * 5) = dn(i, 1);// kappa_xy=d(fi_y)/dy-d(fi_x)/dx answer(3 + 2, 2 + 1 + i * 5) =-dn(i, 0); // shear strains answer(3 + 3, 2 + 0 + i * 5) = dns(i, 0);// gamma_xz = fi_y+dw/dx answer(3 + 3, 2 + 2 + i * 5) = ns(i); answer(3 + 4, 2 + 0 + i * 5) = dns(i, 1);// gamma_yz = -fi_x+dw/dy answer(3 + 4, 2 + 1 + i * 5) = -ns(i); } }
void Quad1MindlinShell3D :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) { FloatArray n; FloatMatrix dn; this->interp.evaldNdx(dn, *gp->giveCoordinates(), FEIVertexListGeometryWrapper(4, (const FloatArray **)lnodes)); this->interp.evalN(n, *gp->giveCoordinates(), FEIVoidCellGeometry()); answer.resize(8, 4*5); answer.zero(); // Note: This is just 5 dofs (sixth column is all zero, torsional stiffness handled separately.) for (int i = 0; i < 4; ++i) { ///@todo Check the rows for both parts here, to be consistent with _3dShell material definition // Part related to the membrane (columns represent coefficients for D_u, D_v) answer(0, 0 + i*5) = dn(i,0); answer(1, 1 + i*5) = dn(i,1); answer(2, 0 + i*5) = dn(i,1); answer(2, 1 + i*5) = dn(i,0); // Part related to the plate (columns represent the dofs D_w, R_u, R_v) ///@todo Check sign here answer(3 + 0, 2 + 1 + i*5) = dn(i,0); answer(3 + 1, 2 + 2 + i*5) = dn(i,1); answer(3 + 2, 2 + 1 + i*5) = dn(i,1); answer(3 + 2, 2 + 2 + i*5) = dn(i,0); answer(3 + 3, 2 + 0 + i*5) = -dn(i,1); answer(3 + 3, 2 + 2 + i*5) = n(i); answer(3 + 4, 2 + 0 + i*5) = -dn(i,0); answer(3 + 4, 2 + 1 + i*5) = n(i); } }
void TrPlanestressRotAllman :: computeNmatrixAt(GaussPoint *aGaussPoint, FloatMatrix &answer) // Returns the displacement interpolation matrix {N} of the receiver, eva- // luated at aGaussPoint. { FloatArray L(3), n(6), lxy[6]; const FloatArray *lxyptr[]= {lxy, lxy+1, lxy+2, lxy+3, lxy+4, lxy+5}; answer.resize(3, 9); answer.zero(); this->computeLocalCoordinates(lxy); // get ready for tranformation into 3d this->qinterpolation.evalN( n, * aGaussPoint->giveCoordinates(), FEIVertexListGeometryWrapper(6, lxyptr) ); this->interp.evalN (L, * aGaussPoint->giveCoordinates(), FEIElementGeometryWrapper(this) ); answer.at(1,1) = answer.at(2,2) = n.at(1)+n.at(4)/2.+n.at(6)/2.; answer.at(1,4) = answer.at(2,5) = n.at(2)+n.at(4)/2.+n.at(5)/2.; answer.at(1,7) = answer.at(2,8) = n.at(3)+n.at(5)/2.+n.at(6)/2.; answer.at(1,3) = n.at(6)*(lxy[0].at(2)-lxy[2].at(2))/8.0-n.at(4)*(lxy[1].at(2)-lxy[0].at(2))/8.0; answer.at(1,6) = n.at(4)*(lxy[1].at(2)-lxy[0].at(2))/8.0-n.at(5)*(lxy[2].at(2)-lxy[1].at(2))/8.0; answer.at(1,9) = n.at(5)*(lxy[2].at(2)-lxy[1].at(2))/8.0-n.at(6)*(lxy[0].at(2)-lxy[2].at(2))/8.0; answer.at(2,3) =-n.at(6)*(lxy[0].at(1)-lxy[2].at(1))/8.0+n.at(4)*(lxy[1].at(1)-lxy[0].at(1))/8.0; answer.at(2,6) =-n.at(4)*(lxy[1].at(1)-lxy[0].at(1))/8.0+n.at(5)*(lxy[2].at(1)-lxy[1].at(1))/8.0; answer.at(2,9) =-n.at(5)*(lxy[2].at(1)-lxy[1].at(1))/8.0+n.at(6)*(lxy[0].at(1)-lxy[2].at(1))/8.0; // linear approx for rotations answer.at(3,3) = L.at(1); answer.at(3,6) = L.at(2); answer.at(3,9) = L.at(3); }
void TrPlanestressRotAllman :: computeEgdeNMatrixAt(FloatMatrix &answer, int iedge, GaussPoint *gp) { FloatArray lxy[6]; const FloatArray *lxyptr[]= {lxy, lxy+1, lxy+2, lxy+3, lxy+4, lxy+5}; FloatArray l, n; IntArray en; FEI2dTrQuad qi (1,2); this->computeLocalCoordinates(lxy); // get ready for tranformation into 3d qi.edgeEvalN( n, iedge, *gp->giveCoordinates(), FEIVertexListGeometryWrapper(6, lxyptr) ); qi.computeLocalEdgeMapping (en, iedge); // get edge mapping this->interp.edgeEvalN( l, iedge, *gp->giveCoordinates(), FEIElementGeometryWrapper(this) ); answer.resize(3,6); answer.at(1, 1) = answer.at(2,2) = n.at(1) + n.at(3)/2.0; answer.at(1, 4) = answer.at(2,5) = n.at(2) + n.at(3)/2.0; answer.at(1, 3) = n.at(3)*(lxy[en.at(2)-1].at(2)-lxy[en.at(1)-1].at(2))/8.0; answer.at(1, 6) = -answer.at(1, 3); answer.at(2, 3) = n.at(3)*(lxy[en.at(2)-1].at(1)-lxy[en.at(1)-1].at(1))/8.0; answer.at(2, 6) = -answer.at(2, 3); answer.at(3, 3) = l.at(1); answer.at(3, 6) = l.at(2); }
bool CCTPlate3d :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coords) //converts global coordinates to local planar area coordinates, //does not return a coordinate in the thickness direction, but //does check that the point is in the element thickness { // rotate the input point Coordinate System into the element CS FloatArray inputCoords_ElCS; std::vector< FloatArray > lc(3); FloatArray llc; this->giveLocalCoordinates( inputCoords_ElCS, const_cast< FloatArray & >(coords) ); for ( int _i = 0; _i < 3; _i++ ) { this->giveLocalCoordinates( lc [ _i ], * this->giveNode(_i + 1)->giveCoordinates() ); } FEI2dTrLin _interp(1, 2); bool inplane = _interp.global2local(llc, inputCoords_ElCS, FEIVertexListGeometryWrapper(lc)) > 0; answer.resize(2); answer.at(1) = inputCoords_ElCS.at(1); answer.at(2) = inputCoords_ElCS.at(2); GaussPoint _gp(NULL, 1, new FloatArray ( answer ), 2.0, _2dPlate); // now check if the third local coordinate is within the thickness of element bool outofplane = ( fabs( inputCoords_ElCS.at(3) ) <= this->giveCrossSection()->give(CS_Thickness, & _gp) / 2. ); return inplane && outofplane; }
void Quad1MindlinShell3D :: computeEdgeIpGlobalCoords(FloatArray &answer, GaussPoint *gp, int iEdge) { FloatArray local; this->interp.edgeLocal2global( local, iEdge, * gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lnodes) ); local.resize(3); local.at(3) = 0.; answer.beProductOf(this->lcsMatrix, local); }
double Quad1MindlinShell3D :: computeVolumeAround(GaussPoint *gp) { double detJ, weight; weight = gp->giveWeight(); detJ = fabs( this->interp.giveTransformationJacobian( * gp->giveCoordinates(), FEIVertexListGeometryWrapper(4, (const FloatArray **)lnodes) ) ); return detJ * weight; }
void TrPlanestressRotAllman :: computeBmatrixAt(GaussPoint *aGaussPoint, FloatMatrix &answer, int li, int ui) // Returns the [3x12] strain-displacement matrix {B} of the receiver, eva- // luated at aGaussPoint. { FloatMatrix dnx; FloatArray lxy[6]; const FloatArray *lxyptr[]= {lxy, lxy+1, lxy+2, lxy+3, lxy+4, lxy+5}; this->computeLocalCoordinates(lxy); // get ready for tranformation into 3d this->qinterpolation.evaldNdx( dnx, * aGaussPoint->giveCoordinates(), FEIVertexListGeometryWrapper(6, lxyptr) ); answer.resize(3, 9); answer.zero(); // epsilon_x answer.at(1,1)=dnx.at(1, 1) + 0.5*dnx.at(4, 1) + 0.5*dnx.at(6, 1); answer.at(1,4)=dnx.at(2, 1) + 0.5*dnx.at(4, 1) + 0.5*dnx.at(5, 1); answer.at(1,7)=dnx.at(3, 1) + 0.5*dnx.at(5, 1) + 0.5*dnx.at(6, 1); answer.at(1,3)=dnx.at(6, 1)*(lxy[0].at(2)-lxy[2].at(2))/8.0-dnx.at(4, 1)*(lxy[1].at(2)-lxy[0].at(2))/8.0; answer.at(1,6)=dnx.at(4, 1)*(lxy[1].at(2)-lxy[0].at(2))/8.0-dnx.at(5, 1)*(lxy[2].at(2)-lxy[1].at(2))/8.0; answer.at(1,9)=dnx.at(5, 1)*(lxy[2].at(2)-lxy[1].at(2))/8.0-dnx.at(6, 1)*(lxy[0].at(2)-lxy[2].at(2))/8.0; // epsilon_y answer.at(2,2)=dnx.at(1, 2) + 0.5*dnx.at(4, 2) + 0.5*dnx.at(6, 2); answer.at(2,5)=dnx.at(2, 2) + 0.5*dnx.at(4, 2) + 0.5*dnx.at(5, 2); answer.at(2,8)=dnx.at(3, 2) + 0.5*dnx.at(5, 2) + 0.5*dnx.at(6, 2); answer.at(2,3)=-dnx.at(6, 2)*(lxy[0].at(1)-lxy[2].at(1))/8.0+dnx.at(4, 2)*(lxy[1].at(1)-lxy[0].at(1))/8.0; answer.at(2,6)=-dnx.at(4, 2)*(lxy[1].at(1)-lxy[0].at(1))/8.0+dnx.at(5, 2)*(lxy[2].at(1)-lxy[1].at(1))/8.0; answer.at(2,9)=-dnx.at(5, 2)*(lxy[2].at(1)-lxy[1].at(1))/8.0+dnx.at(6, 2)*(lxy[0].at(1)-lxy[2].at(1))/8.0; // gamma_xy (shear) answer.at(3,1)=dnx.at(1, 2) + 0.5*dnx.at(4, 2) + 0.5*dnx.at(6, 2); answer.at(3,2)=dnx.at(1, 1) + 0.5*dnx.at(4, 1) + 0.5*dnx.at(6, 1); answer.at(3,4)=dnx.at(2, 2) + 0.5*dnx.at(4, 2) + 0.5*dnx.at(5, 2); answer.at(3,5)=dnx.at(2, 1) + 0.5*dnx.at(4, 1) + 0.5*dnx.at(5, 1); answer.at(3,7)=dnx.at(3, 2) + 0.5*dnx.at(5, 2) + 0.5*dnx.at(6, 2); answer.at(3,8)=dnx.at(3, 1) + 0.5*dnx.at(5, 1) + 0.5*dnx.at(6, 1); answer.at(3,3) = dnx.at(6, 2)*(lxy[0].at(2)-lxy[2].at(2))/8.0-dnx.at(4, 2)*(lxy[1].at(2)-lxy[0].at(2))/8.0; answer.at(3,3)+=-dnx.at(6, 1)*(lxy[0].at(1)-lxy[2].at(1))/8.0+dnx.at(4, 1)*(lxy[1].at(1)-lxy[0].at(1))/8.0; answer.at(3,6) = dnx.at(4, 2)*(lxy[1].at(2)-lxy[0].at(2))/8.0-dnx.at(5, 2)*(lxy[2].at(2)-lxy[1].at(2))/8.0; answer.at(3,6)+=-dnx.at(4, 1)*(lxy[1].at(1)-lxy[0].at(1))/8.0+dnx.at(5, 1)*(lxy[2].at(1)-lxy[1].at(1))/8.0; answer.at(3,9) = dnx.at(5, 2)*(lxy[2].at(2)-lxy[1].at(2))/8.0-dnx.at(6, 2)*(lxy[0].at(2)-lxy[2].at(2))/8.0; answer.at(3,9)+=-dnx.at(5, 1)*(lxy[2].at(1)-lxy[1].at(1))/8.0+dnx.at(6, 1)*(lxy[0].at(1)-lxy[2].at(1))/8.0; }
void TrPlanestressRotAllman :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) // Returns the [3x12] strain-displacement matrix {B} of the receiver, eva- // luated at gp. { FloatMatrix dnx; std::vector< FloatArray > lxy; this->computeLocalNodalCoordinates(lxy); // get ready for tranformation into 3d this->qinterpolation.evaldNdx( dnx, gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lxy) ); answer.resize(3, 9); answer.zero(); // epsilon_x answer.at(1, 1) = dnx.at(1, 1) + 0.5 * dnx.at(4, 1) + 0.5 * dnx.at(6, 1); answer.at(1, 4) = dnx.at(2, 1) + 0.5 * dnx.at(4, 1) + 0.5 * dnx.at(5, 1); answer.at(1, 7) = dnx.at(3, 1) + 0.5 * dnx.at(5, 1) + 0.5 * dnx.at(6, 1); answer.at(1, 3) =+dnx.at(6, 1) * ( lxy [ 0 ].at(2) - lxy [ 2 ].at(2) ) / 8.0 - dnx.at(4, 1) * ( lxy [ 1 ].at(2) - lxy [ 0 ].at(2) ) / 8.0; answer.at(1, 6) =+dnx.at(4, 1) * ( lxy [ 1 ].at(2) - lxy [ 0 ].at(2) ) / 8.0 - dnx.at(5, 1) * ( lxy [ 2 ].at(2) - lxy [ 1 ].at(2) ) / 8.0; answer.at(1, 9) =+dnx.at(5, 1) * ( lxy [ 2 ].at(2) - lxy [ 1 ].at(2) ) / 8.0 - dnx.at(6, 1) * ( lxy [ 0 ].at(2) - lxy [ 2 ].at(2) ) / 8.0; // epsilon_y answer.at(2, 2) = dnx.at(1, 2) + 0.5 * dnx.at(4, 2) + 0.5 * dnx.at(6, 2); answer.at(2, 5) = dnx.at(2, 2) + 0.5 * dnx.at(4, 2) + 0.5 * dnx.at(5, 2); answer.at(2, 8) = dnx.at(3, 2) + 0.5 * dnx.at(5, 2) + 0.5 * dnx.at(6, 2); answer.at(2, 3) =-dnx.at(6, 2) * ( lxy [ 0 ].at(1) - lxy [ 2 ].at(1) ) / 8.0 + dnx.at(4, 2) * ( lxy [ 1 ].at(1) - lxy [ 0 ].at(1) ) / 8.0; answer.at(2, 6) =-dnx.at(4, 2) * ( lxy [ 1 ].at(1) - lxy [ 0 ].at(1) ) / 8.0 + dnx.at(5, 2) * ( lxy [ 2 ].at(1) - lxy [ 1 ].at(1) ) / 8.0; answer.at(2, 9) =-dnx.at(5, 2) * ( lxy [ 2 ].at(1) - lxy [ 1 ].at(1) ) / 8.0 + dnx.at(6, 2) * ( lxy [ 0 ].at(1) - lxy [ 2 ].at(1) ) / 8.0; // gamma_xy (shear) answer.at(3, 1) = dnx.at(1, 2) + 0.5 * dnx.at(4, 2) + 0.5 * dnx.at(6, 2); answer.at(3, 2) = dnx.at(1, 1) + 0.5 * dnx.at(4, 1) + 0.5 * dnx.at(6, 1); answer.at(3, 4) = dnx.at(2, 2) + 0.5 * dnx.at(4, 2) + 0.5 * dnx.at(5, 2); answer.at(3, 5) = dnx.at(2, 1) + 0.5 * dnx.at(4, 1) + 0.5 * dnx.at(5, 1); answer.at(3, 7) = dnx.at(3, 2) + 0.5 * dnx.at(5, 2) + 0.5 * dnx.at(6, 2); answer.at(3, 8) = dnx.at(3, 1) + 0.5 * dnx.at(5, 1) + 0.5 * dnx.at(6, 1); answer.at(3, 3) = dnx.at(6, 2) * ( lxy [ 0 ].at(2) - lxy [ 2 ].at(2) ) / 8.0 - dnx.at(4, 2) * ( lxy [ 1 ].at(2) - lxy [ 0 ].at(2) ) / 8.0; answer.at(3, 3) += -dnx.at(6, 1) * ( lxy [ 0 ].at(1) - lxy [ 2 ].at(1) ) / 8.0 + dnx.at(4, 1) * ( lxy [ 1 ].at(1) - lxy [ 0 ].at(1) ) / 8.0; answer.at(3, 6) = dnx.at(4, 2) * ( lxy [ 1 ].at(2) - lxy [ 0 ].at(2) ) / 8.0 - dnx.at(5, 2) * ( lxy [ 2 ].at(2) - lxy [ 1 ].at(2) ) / 8.0; answer.at(3, 6) += -dnx.at(4, 1) * ( lxy [ 1 ].at(1) - lxy [ 0 ].at(1) ) / 8.0 + dnx.at(5, 1) * ( lxy [ 2 ].at(1) - lxy [ 1 ].at(1) ) / 8.0; answer.at(3, 9) = dnx.at(5, 2) * ( lxy [ 2 ].at(2) - lxy [ 1 ].at(2) ) / 8.0 - dnx.at(6, 2) * ( lxy [ 0 ].at(2) - lxy [ 2 ].at(2) ) / 8.0; answer.at(3, 9) += -dnx.at(5, 1) * ( lxy [ 2 ].at(1) - lxy [ 1 ].at(1) ) / 8.0 + dnx.at(6, 1) * ( lxy [ 0 ].at(1) - lxy [ 2 ].at(1) ) / 8.0; }
void TrPlanestressRotAllman :: computeStiffnessMatrixZeroEnergyStabilization(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { FloatMatrix b(1,9), d(1,1); FloatMatrix dnx; FloatArray lxy[6], lec; const FloatArray *lxyptr[]= {lxy, lxy+1, lxy+2, lxy+3, lxy+4, lxy+5}; lec.setValues(3, 0.333333333333, 0.333333333333, 0.333333333333); // element center in local coordinates this->computeLocalCoordinates(lxy); // get ready for tranformation into 3d this->qinterpolation.evaldNdx( dnx, lec, FEIVertexListGeometryWrapper(6, lxyptr) ); // evaluate (dv/dx-du/dy)/2. at element center b.at(1,1)=-1.0*(dnx.at(1, 2) + 0.5*dnx.at(4, 2) + 0.5*dnx.at(6, 2)); b.at(1,2)=dnx.at(1, 1) + 0.5*dnx.at(4, 1) + 0.5*dnx.at(6, 1); b.at(1,4)=-1.0*(dnx.at(2, 2) + 0.5*dnx.at(4, 2) + 0.5*dnx.at(5, 2)); b.at(1,5)=dnx.at(2, 1) + 0.5*dnx.at(4, 1) + 0.5*dnx.at(5, 1); b.at(1,7)=-1.0*(dnx.at(3, 2) + 0.5*dnx.at(5, 2) + 0.5*dnx.at(6, 2)); b.at(1,8)=dnx.at(3, 1) + 0.5*dnx.at(5, 1) + 0.5*dnx.at(6, 1); b.at(1,3) =-dnx.at(6, 2)*(lxy[0].at(2)-lxy[2].at(2))/8.0+dnx.at(4, 2)*(lxy[1].at(2)-lxy[0].at(2))/8.0; b.at(1,3)+=-dnx.at(6, 1)*(lxy[0].at(1)-lxy[2].at(1))/8.0+dnx.at(4, 1)*(lxy[1].at(1)-lxy[0].at(1))/8.0; b.at(1,6) =-dnx.at(4, 2)*(lxy[1].at(2)-lxy[0].at(2))/8.0+dnx.at(5, 2)*(lxy[2].at(2)-lxy[1].at(2))/8.0; b.at(1,6)+=-dnx.at(4, 1)*(lxy[1].at(1)-lxy[0].at(1))/8.0+dnx.at(5, 1)*(lxy[2].at(1)-lxy[1].at(1))/8.0; b.at(1,9) =-dnx.at(5, 2)*(lxy[2].at(2)-lxy[1].at(2))/8.0+dnx.at(6, 2)*(lxy[0].at(2)-lxy[2].at(2))/8.0; b.at(1,9)+=-dnx.at(5, 1)*(lxy[2].at(1)-lxy[1].at(1))/8.0+dnx.at(6, 1)*(lxy[0].at(1)-lxy[2].at(1))/8.0; b.times(0.5); // add -1.0*sum(r_w)/3.0 b.at(1,3)-=1.0/3.0; b.at(1,6)-=1.0/3.0; b.at(1,9)-=1.0/3.0; // add alpha*Volume*B^T[G]B to element stiffness matrix double coeff = this->giveMaterial()->give (Gxy, this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0)) * this->giveArea() * this->giveCrossSection()->give(CS_Thickness) * 1.e-6; answer.beTProductOf (b,b); answer.times(coeff); }
double Quad1MindlinShell3D :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { double detJ = this->interp.edgeGiveTransformationJacobian( iEdge, * gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lnodes) ); return detJ *gp->giveWeight(); }
void Quad1MindlinShell3D :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) { FloatArray n, ns; FloatMatrix dn, dns; const FloatArray &localCoords = gp->giveNaturalCoordinates(); this->interp.evaldNdx( dn, localCoords, FEIVertexListGeometryWrapper(lnodes) ); this->interp.evalN( n, localCoords, FEIVoidCellGeometry() ); answer.resize(8, 4 * 5); answer.zero(); // enforce one-point reduced integration if requested if ( this->reducedIntegrationFlag ) { FloatArray lc(2); lc.zero(); // set to element center coordinates this->interp.evaldNdx( dns, lc, FEIVertexListGeometryWrapper(lnodes) ); this->interp.evalN( ns, lc, FEIVoidCellGeometry() ); } else { dns = dn; ns = n; } // Note: This is just 5 dofs (sixth column is all zero, torsional stiffness handled separately.) for ( int i = 0; i < 4; ++i ) { ///@todo Check the rows for both parts here, to be consistent with _3dShell material definition // Part related to the membrane (columns represent coefficients for D_u, D_v) answer(0, 0 + i * 5) = dn(i, 0);//eps_x = du/dx answer(1, 1 + i * 5) = dn(i, 1);//eps_y = dv/dy answer(2, 0 + i * 5) = dn(i, 1);//gamma_xy = du/dy+dv/dx answer(2, 1 + i * 5) = dn(i, 0); // Part related to the plate (columns represent the dofs D_w, R_u, R_v) ///@todo Check sign here answer(3 + 0, 2 + 2 + i * 5) = dn(i, 0);// kappa_x = d(fi_y)/dx answer(3 + 1, 2 + 1 + i * 5) =-dn(i, 1);// kappa_y = -d(fi_x)/dy answer(3 + 2, 2 + 2 + i * 5) = dn(i, 1);// kappa_xy=d(fi_y)/dy-d(fi_x)/dx answer(3 + 2, 2 + 1 + i * 5) =-dn(i, 0); // shear strains answer(3 + 3, 2 + 0 + i * 5) = dns(i, 0);// gamma_xz = fi_y+dw/dx answer(3 + 3, 2 + 2 + i * 5) = ns(i); answer(3 + 4, 2 + 0 + i * 5) = dns(i, 1);// gamma_yz = -fi_x+dw/dy answer(3 + 4, 2 + 1 + i * 5) = -ns(i); } #if 0 // Experimental MITC4 support. // Based on "Short communication A four-node plate bending element based on mindling/reissner plate theory and a mixed interpolation" // KJ Bathe, E Dvorkin double x1, x2, x3, x4; double y1, y2, y3, y4; double Ax, Bx, Cx, Ay, By, Cy; double r = localCoords[0]; double s = localCoords[1]; x1 = lnodes[0][0]; x2 = lnodes[1][0]; x3 = lnodes[2][0]; x4 = lnodes[3][0]; y1 = lnodes[0][1]; y2 = lnodes[1][1]; y3 = lnodes[2][1]; y4 = lnodes[3][1]; Ax = x1 - x2 - x3 + x4; Bx = x1 - x2 + x3 - x4; Cx = x1 + x2 - x3 - x4; Ay = y1 - y2 - y3 + y4; By = y1 - y2 + y3 - y4; Cy = y1 + y2 - y3 - y4; FloatMatrix jac; this->interp.giveJacobianMatrixAt(jac, localCoords, FEIVertexListGeometryWrapper(lnodes) ); double detJ = jac.giveDeterminant(); double rz = sqrt( sqr(Cx + r*Bx) + sqr(Cy + r*By)) / ( 16 * detJ ); double sz = sqrt( sqr(Ax + s*Bx) + sqr(Ay + s*By)) / ( 16 * detJ ); // TODO: Not sure about this part (the reference is not explicit about these angles. / Mikael // Not sure about the transpose either. OOFEM_WARNING("The MITC4 implementation isn't verified yet. Highly experimental"); FloatArray dxdr = {jac(0,0), jac(0,1)}; dxdr.normalize(); FloatArray dxds = {jac(1,0), jac(1,1)}; dxds.normalize(); double c_b = dxdr(0); //cos(beta); double s_b = dxdr(1); //sin(beta); double c_a = dxds(0); //cos(alpha); double s_a = dxds(1); //sin(alpha); // gamma_xz = "fi_y+dw/dx" in standard formulation answer(6, 2 + 5*0) = rz * s_b * ( (1+s)) - sz * s_a * ( (1+r)); answer(6, 2 + 5*1) = rz * s_b * (-(1+s)) - sz * s_a * ( (1-r)); answer(6, 2 + 5*2) = rz * s_b * (-(1-s)) - sz * s_a * (-(1-r)); answer(6, 2 + 5*3) = rz * s_b * ( (1-s)) - sz * s_a * (-(1+r)); answer(6, 3 + 5*0) = rz * s_b * (y2-y1) * 0.5 * (1+s) - sz * s_a * (y4-y1) * 0.5 * (1+r); // tx1 answer(6, 4 + 5*0) = rz * s_b * (x1-x2) * 0.5 * (1+s) - sz * s_a * (x1-x4) * 0.5 * (1+r); // ty1 answer(6, 3 + 5*1) = rz * s_b * (y2-y1) * 0.5 * (1+s) - sz * s_a * (y3-x2) * 0.5 * (1+r); // tx2 answer(6, 4 + 5*1) = rz * s_b * (x1-x2) * 0.5 * (1+s) - sz * s_a * (x2-x3) * 0.5 * (1+r); // ty2 answer(6, 3 + 5*2) = rz * s_b * (y3-y4) * 0.5 * (1-s) - sz * s_a * (y3-y2) * 0.5 * (1-r); // tx3 answer(6, 4 + 5*2) = rz * s_b * (x4-x3) * 0.5 * (1-s) - sz * s_a * (x2-x3) * 0.5 * (1-r); // ty3 answer(6, 3 + 5*3) = rz * s_b * (y3-y4) * 0.5 * (1-s) - sz * s_a * (y4-y1) * 0.5 * (1-r); // tx4 answer(6, 4 + 5*3) = rz * s_b * (x4-x3) * 0.5 * (1-s) - sz * s_a * (x1-x4) * 0.5 * (1-r); // ty4 // gamma_yz = -fi_x+dw/dy in standard formulation answer(7, 2 + 5*0) = - rz * c_b * ( (1+s)) + sz * c_a * ( (1+r)); answer(7, 2 + 5*1) = - rz * c_b * (-(1+s)) + sz * c_a * ( (1-r)); answer(7, 2 + 5*2) = - rz * c_b * (-(1-s)) + sz * c_a * (-(1-r)); answer(7, 2 + 5*3) = - rz * c_b * ( (1-s)) + sz * c_a * (-(1+r)); answer(7, 3 + 5*0) = - rz * c_b * (y2-y1) * 0.5 * (1+s) + sz * c_a * (y4-y1) * 0.5 * (1+r); // tx1 answer(7, 4 + 5*0) = - rz * c_b * (x1-x2) * 0.5 * (1+s) + sz * c_a * (x1-x4) * 0.5 * (1+r); // ty1 answer(7, 3 + 5*1) = - rz * c_b * (y2-y1) * 0.5 * (1+s) + sz * c_a * (y3-x2) * 0.5 * (1+r); // tx2 answer(7, 4 + 5*1) = - rz * c_b * (x1-x2) * 0.5 * (1+s) + sz * c_a * (x2-x3) * 0.5 * (1+r); // ty2 answer(7, 3 + 5*2) = - rz * c_b * (y3-y4) * 0.5 * (1-s) + sz * c_a * (y3-y2) * 0.5 * (1-r); // tx3 answer(7, 4 + 5*2) = - rz * c_b * (x4-x3) * 0.5 * (1-s) + sz * c_a * (x2-x3) * 0.5 * (1-r); // ty3 answer(7, 3 + 5*3) = - rz * c_b * (y3-y4) * 0.5 * (1-s) + sz * c_a * (y4-y1) * 0.5 * (1-r); // tx4 answer(7, 4 + 5*3) = - rz * c_b * (x4-x3) * 0.5 * (1-s) + sz * c_a * (x1-x4) * 0.5 * (1-r); // ty4 #endif }
double InterfaceElement3dTrLin :: computeVolumeAround(GaussPoint *gp) // Returns the length of the receiver. This method is valid only if 1 // Gauss point is used. { double determinant, weight, thickness, volume; // first compute local nodal coordinates in element plane std::vector< FloatArray > lncp(3); FloatMatrix lcs(3, 3); this->computeLCS(lcs); for ( int i = 1; i <= 3; i++ ) { lncp[ i - 1 ].beProductOf(lcs, *this->giveNode(i)->giveCoordinates()); } determinant = fabs( this->interpolation.giveTransformationJacobian( * gp->giveCoordinates(), FEIVertexListGeometryWrapper(lncp) ) ); weight = gp->giveWeight(); thickness = this->giveCrossSection()->give(CS_Thickness, gp); volume = determinant * weight * thickness; return volume; }
int PatchIntegrationRule :: SetUpPointsOnTriangle(int nPoints, MaterialMode mode) { int pointsPassed = 0; // TODO: set properly firstLocalStrainIndx = 1; lastLocalStrainIndx = 3; //////////////////////////////////////////// // Allocate Gauss point array // It may happen that the patch contains triangles with // zero area. This does no harm, since their weights in // the quadrature will be zero. However, they invoke additional // computational cost and therefore we want to avoid them. // Thus, count the number of triangles with finite area // and keep only those triangles. double totArea = 0.0; for(size_t i = 0; i < mTriangles.size(); i++) { totArea += mTriangles[i].getArea(); } std::vector<int> triToKeep; const double triTol = ( 1.0e-6 )*totArea; for(size_t i = 0; i < mTriangles.size(); i++) { if( mTriangles[i].getArea() > triTol ) { triToKeep.push_back(i); } } int nPointsTot = nPoints * triToKeep.size(); FloatArray coords_xi1, coords_xi2, weights; this->giveTriCoordsAndWeights(nPoints, coords_xi1, coords_xi2, weights); this->gaussPointArray = new GaussPoint * [ nPointsTot ]; //////////////////////////////////////////// std :: vector< FloatArray >newGPCoord; double parentArea = this->elem->computeArea(); // Loop over triangles for ( int i = 0; i < int( triToKeep.size() ); i++ ) { // TODO: Probably unnecessary to allocate here const FloatArray **coords = new const FloatArray * [ mTriangles [ triToKeep[i] ].giveNrVertices() ]; // this we should put into the function before for ( int k = 0; k < mTriangles [ triToKeep[i] ].giveNrVertices(); k++ ) { coords [ k ] = new FloatArray( ( mTriangles [ triToKeep[i] ].giveVertex(k + 1) ) ); } // Can not be used because it writes to the start of the array instead of appending. // int nPointsTri = GaussIntegrationRule :: SetUpPointsOnTriangle(nPoints, mode); for ( int j = 0; j < nPoints; j++ ) { FloatArray global; GaussPoint * &gp = this->gaussPointArray [ pointsPassed ]; FloatArray *coord = new FloatArray(2); coord->at(1) = coords_xi1.at(j + 1); coord->at(2) = coords_xi2.at(j + 1); gp = new GaussPoint(this, pointsPassed + 1, coord, weights.at(j + 1), mode); mTriInterp.local2global( global, * gp->giveCoordinates(), FEIVertexListGeometryWrapper(mTriangles [ triToKeep[i] ].giveNrVertices(), coords) ); newGPCoord.push_back(global); FloatArray local; this->elem->computeLocalCoordinates(local, global); gp->setCoordinates(local); double refElArea = this->elem->giveParentElSize(); gp->setWeight(2.0 * refElArea * gp->giveWeight() * mTriangles [ triToKeep[i] ].getArea() / parentArea); // update integration weight pointsPassed++; } for ( int k = 0; k < mTriangles [ triToKeep[i] ].giveNrVertices(); k++ ) { delete coords [ k ]; } delete [] coords; } #if PATCH_INT_DEBUG > 0 double time = 0.0; Element *el = this->elem; if(el != NULL) { Domain *dom = el->giveDomain(); if(dom != NULL) { EngngModel *em = dom->giveEngngModel(); if(em != NULL) { TimeStep *ts = em->giveCurrentStep(); if(ts != NULL) { time = ts->giveTargetTime(); } } } } int elIndex = this->elem->giveGlobalNumber(); std :: stringstream str; str << "GaussPointsTime" << time << "El" << elIndex << ".vtk"; std :: string name = str.str(); XFEMDebugTools :: WritePointsToVTK(name, newGPCoord); #endif numberOfIntegrationPoints = pointsPassed; return numberOfIntegrationPoints; }
int PatchIntegrationRule :: SetUpPointsOnWedge(int nPointsTri, int nPointsDepth, MaterialMode mode) { //int pointsPassed = 0; // TODO: set properly firstLocalStrainIndx = 1; lastLocalStrainIndx = 3; double totArea = 0.0; for ( size_t i = 0; i < mTriangles.size(); i++ ) { totArea += mTriangles [ i ].getArea(); } std :: vector< int >triToKeep; const double triTol = ( 1.0e-6 ) * totArea; for ( size_t i = 0; i < mTriangles.size(); i++ ) { if ( mTriangles [ i ].getArea() > triTol ) { triToKeep.push_back(i); } } int nPointsTot = nPointsTri * nPointsDepth * triToKeep.size(); FloatArray coords_xi1, coords_xi2, coords_xi3, weightsTri, weightsDepth; this->giveTriCoordsAndWeights(nPointsTri, coords_xi1, coords_xi2, weightsTri); this->giveLineCoordsAndWeights(nPointsDepth, coords_xi3, weightsDepth); this->gaussPoints.resize(nPointsTot); std :: vector< FloatArray >newGPCoord; double parentArea = this->elem->computeArea(); int count = 0; // Loop over triangles for ( int i = 0; i < int( triToKeep.size() ); i++ ) { Triangle triangle = mTriangles [ triToKeep [ i ] ]; // global coords of the the triangle verticies std::vector< FloatArray > gCoords( triangle.giveNrVertices() ); for ( int j = 0; j < triangle.giveNrVertices(); j++ ) { gCoords[j] = (triangle.giveVertex(j + 1)); } for ( int k = 1; k <= nPointsTri; k++ ) { for ( int m = 1; m <= nPointsDepth; m++ ) { // local coords in the parent triangle FloatArray *lCoords = new FloatArray(3); lCoords->at(1) = coords_xi1.at(k); lCoords->at(2) = coords_xi2.at(k); lCoords->at(3) = coords_xi3.at(m); double refElArea = 0.5; double oldWeight = weightsTri.at(k) * weightsDepth.at(m); double newWeight = 2.0 * refElArea * oldWeight * triangle.getArea() / parentArea; GaussPoint *gp = new GaussPoint(this, count + 1, lCoords, newWeight, mode); this->gaussPoints[count] = gp; count++; // Compute global gp coordinate in the element from local gp coord in the sub triangle FloatArray global; mTriInterp.local2global( global, * gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(gCoords) ); // Compute local gp coordinate in the element from global gp coord in the element FloatArray local; this->elem->computeLocalCoordinates(local, global); local.at(3) = coords_xi3.at(m); // manually set third coordinate // compute global coords again, since interpolator dosn't give the z-coord this->elem->computeGlobalCoordinates(global, local); gp->setGlobalCoordinates(global); gp->setNaturalCoordinates(local); gp->setSubPatchCoordinates(local); // Store new global gp coord for vtk output newGPCoord.push_back(global); } } //for ( int k = 0; k < mTriangles [ triToKeep [ i ] ].giveNrVertices(); k++ ) { // delete gCoords [ k ]; //} //delete [] gCoords; } XfemManager *xMan = elem->giveDomain()->giveXfemManager(); if ( xMan != NULL ) { if ( xMan->giveVtkDebug() ) { double time = 0.0; Element *el = this->elem; if ( el != NULL ) { Domain *dom = el->giveDomain(); if ( dom != NULL ) { EngngModel *em = dom->giveEngngModel(); if ( em != NULL ) { TimeStep *ts = em->giveCurrentStep(); if ( ts != NULL ) { time = ts->giveTargetTime(); } } } } int elIndex = this->elem->giveGlobalNumber(); std :: stringstream str; str << "GaussPointsTime" << time << "El" << elIndex << ".vtk"; std :: string name = str.str(); XFEMDebugTools :: WritePointsToVTK(name, newGPCoord); } } return this->giveNumberOfIntegrationPoints(); }