#include "elements.h" #include "geom.h" #include "getmatrix.h" #include "userset.h" #include "utils.h" #include "vdop.h" #include #include #include #include using namespace std; vector shrinkColumns(vector const &v2, int col2, int col1) { assert( v2.size()%col2 == 0 ); assert( col1<=col2 ); int const nrows = static_cast(v2.size()/col2); vector v1(nrows*col1); for (int k=0; k mergeColumns(vector const &v1, int col1, vector const &v2, int col2) { assert( v2.size()%col2 == 0 ); assert( v1.size()%col1 == 0 ); assert( v1.size()/col1 == v2.size()/col2 ); int const nrows = static_cast(v2.size()/col2); int const ncols = col1+col2; vector vm(nrows*ncols); for (int k=0; k indexVectorBlowUp(vector const &vin, int ndof_v, int offset) { vector wout(vin.size()*ndof_v); for (size_t k=0; k P1_2d::getGlobalDOFIndices(vector const &ia_geom) const { assert(0 == nDOFs_loc() % nVertices_loc()); int const ndof_v = nDOFs_loc()/nVertices_loc(); // DOFs per vertex return indexVectorBlowUp(ia_geom,ndof_v,0); } vector P1_3d::getGlobalDOFIndices(vector const &ia_geom) const { assert(0 == nDOFs_loc() % nVertices_loc()); int const ndof_v = nDOFs_loc()/nVertices_loc(); // DOFs per vertex return indexVectorBlowUp(ia_geom,ndof_v,0); } vector P2_3d::getGlobalDOFIndices(vector const &ia_geom) const { assert(0 == nDOFs_loc() % nVertices_loc()); int const ndof_v = nDOFs_loc()/nVertices_loc(); // DOFs per vertex //cout << "LLLLLLLLLLL " << ndof_v << endl; return indexVectorBlowUp(ia_geom,ndof_v,0); } vector P1_2vec_3d::getGlobalDOFIndices(vector const &ia_geom_P2) const { int const nv1(4); // #vertices tet linear int const nv2(10); // #vertices tet quadratic // first: P1 part - scalar vector ia_geom_P1 = shrinkColumns(ia_geom_P2, nv2, nv1); auto const ia_p1(indexVectorBlowUp(ia_geom_P1,1,0)); int const nP1_dofs = *max_element(cbegin(ia_p1),cend(ia_p1)); // offset for next numbering // second: P2 part - vector auto const ia_p2(indexVectorBlowUp(ia_geom_P2,3,nP1_dofs)); // merging of ia_p1 and ia_p2 int const col1=nv1*1; int const col2=nv2*3; vector ia_dofs(mergeColumns(ia_p1, col1, ia_p2, col2)); return ia_dofs; } ////###################################################################### // general routine for lin. triangular elements void P1_2d::CalcLaplace( int const ial[3], double const xc[], vector> &ske, vector &fe, const function &f_func ) const { assert(nVertices_loc()==3); assert(nDOFs_loc()==3); //cout << ske.size() << " " << nDOFs_loc() << endl; assert(static_cast(ske.size())==nDOFs_loc()); const int i1 = 2*ial[0], i2 = 2*ial[1], i3 = 2*ial[2]; const double x13 = xc[i3 + 0] - xc[i1 + 0], y13 = xc[i3 + 1] - xc[i1 + 1], x21 = xc[i1 + 0] - xc[i2 + 0], y21 = xc[i1 + 1] - xc[i2 + 1], x32 = xc[i2 + 0] - xc[i3 + 0], y32 = xc[i2 + 1] - xc[i3 + 1]; const double jac = std::abs(x21 * y13 - x13 * y21); ske[0][0] = 0.5 / jac * (y32 * y32 + x32 * x32); ske[0][1] = 0.5 / jac * (y13 * y32 + x13 * x32); ske[0][2] = 0.5 / jac * (y21 * y32 + x21 * x32); ske[1][0] = ske[0][1]; ske[1][1] = 0.5 / jac * (y13 * y13 + x13 * x13); ske[1][2] = 0.5 / jac * (y21 * y13 + x21 * x13); ske[2][0] = ske[0][2]; ske[2][1] = ske[1][2]; ske[2][2] = 0.5 / jac * (y21 * y21 + x21 * x21); const double xm = (xc[i1 + 0] + xc[i2 + 0] + xc[i3 + 0]) / 3.0, ym = (xc[i1 + 1] + xc[i2 + 1] + xc[i3 + 1]) / 3.0; fe[0] = fe[1] = fe[2] = 0.5 * jac * f_func(xm, ym) / 3.0; } void P1_2d::CalcLaplace( int const ial[3], double const xc[], vector> &ske, vector &fe) const { CalcLaplace(ial,xc,ske,fe,rhs_lap2); } void P1_3d::CalcLaplace( int const ial[4], double const xc[], vector> &ske, vector &fe, const function &f_func) const { assert(nVertices_loc()==4); assert(nDOFs_loc()==4); assert(static_cast(ske.size())==nDOFs_loc()); assert(3==nDim_loc()); // global (geom.) vertex indices const int i1 = 3*ial[0], i2 = 3*ial[1], i3 = 3*ial[2], i4 = 3*ial[3]; // coordinates of geom. vertices const double x1{xc[i1+0]}, x2{xc[i2+0]}, x3{xc[i3+0]}, x4{xc[i4+0]}; const double y1{xc[i1+1]}, y2{xc[i2+1]}, y3{xc[i3+1]}, y4{xc[i4+1]}; const double z1{xc[i1+2]}, z2{xc[i2+2]}, z3{xc[i3+2]}, z4{xc[i4+2]}; // center of gravity of the tetrahedron const double xm{(x1+x2+x3+x4)/4}, ym{(y1+y2+y3+y4)/4}, zm{(z1+z2+z3+z4)/4}; // copy-paste from Matlab file tet_elem.m const double detA=x1*y3*z2 - x1*y2*z3 + x2*y1*z3 - x2*y3*z1 - x3*y1*z2 + x3*y2*z1 + x1*y2*z4 - x1*y4*z2 - x2*y1*z4 + x2*y4*z1 + x4*y1*z2 - x4*y2*z1 - x1*y3*z4 + x1*y4*z3 + x3*y1*z4 - x3*y4*z1 - x4*y1*z3 + x4*y3*z1 + x2*y3*z4 - x2*y4*z3 - x3*y2*z4 + x3*y4*z2 + x4*y2*z3 - x4*y3*z2; const double gradPhi[4][3] = { // 1/detA* {y3*z2 - y2*z3 + y2*z4 - y4*z2 - y3*z4 + y4*z3, x2*z3 - x3*z2 - x2*z4 + x4*z2 + x3*z4 - x4*z3, x3*y2 - x2*y3 + x2*y4 - x4*y2 - x3*y4 + x4*y3}, {y1*z3 - y3*z1 - y1*z4 + y4*z1 + y3*z4 - y4*z3, x3*z1 - x1*z3 + x1*z4 - x4*z1 - x3*z4 + x4*z3, x1*y3 - x3*y1 - x1*y4 + x4*y1 + x3*y4 - x4*y3}, {y2*z1 - y1*z2 + y1*z4 - y4*z1 - y2*z4 + y4*z2, x1*z2 - x2*z1 - x1*z4 + x4*z1 + x2*z4 - x4*z2, x2*y1 - x1*y2 + x1*y4 - x4*y1 - x2*y4 + x4*y2}, {y1*z2 - y2*z1 - y1*z3 + y3*z1 + y2*z3 - y3*z2, x2*z1 - x1*z2 + x1*z3 - x3*z1 - x2*z3 + x3*z2, x1*y2 - x2*y1 - x1*y3 + x3*y1 + x2*y3 - x3*y2}, }; for (int row=0; row> &ske, vector &fe) const { CalcLaplace(ial,xc,ske,fe,rhs_lap3); } void P1_2vec_3d::CalcLaplace( int const ial[10], double const xc[], vector> &ske, vector &fe, const function &f_func ) const { cout << "P1_2vec_3d::CalcLaplace\n"; assert(nVertices_loc()==10); assert(nDOFs_loc()==34); //cout << ske.size() << " " << nDOFs_loc() << endl; assert(static_cast(ske.size())==nDOFs_loc()); // Dummy filling for first test for (size_t row=0; row