#include "ElInfo.h" #include "BasisFunction.h" #include "Element.h" #include "Line.h" #include "Triangle.h" #include "Tetrahedron.h" #include "FiniteElemSpace.h" #include "Flag.h" #include "MacroElement.h" #include "Mesh.h" #include "Global.h" #include "FixVec.h" #include "DOFVector.h" namespace AMDiS { int ElInfo::traverseId = -1; int ElInfo::traverseIdCounter = 0; ElInfo::ElInfo(Mesh *aMesh) : mesh_(aMesh), element_(NULL), parent_(NULL), macroElement_(NULL), coord_(mesh_->getDim(), NO_INIT), boundary_(mesh_->getDim(), DEFAULT_VALUE, INTERIOR), projection_(mesh_->getDim(), NO_INIT), oppCoord_(mesh_->getDim(), NO_INIT), neighbour_(mesh_->getDim(), NO_INIT), neighbourCoord_(mesh_->getDim(), NO_INIT), oppVertex_(mesh_->getDim(), NO_INIT), grdLambda_(mesh_->getDim(), NO_INIT) //parametric_(false) { projection_.set(NULL); for (int i = 0; i < neighbourCoord_.getSize(); i++) { neighbourCoord_[i].init(mesh_->getDim()); } dimOfWorld = Global::getGeo(WORLD); } ElInfo::~ElInfo() { } /****************************************************************************/ /* transform local coordintes l to world coordinates; if w is non NULL */ /* store them at w otherwise return a pointer to some local static */ /* area containing world coordintes */ /****************************************************************************/ const WorldVector *ElInfo::coordToWorld(const DimVec& l, WorldVector* w) const { int dim = l.getSize() - 1; static WorldVector world[2]; WorldVector *ret = w ? w : &world[omp_get_thread_num()]; double c = l[0]; for (int j = 0; j < dimOfWorld; j++) (*ret)[j] = c * coord_[0][j]; int vertices = Global::getGeo(VERTEX, dim); for (int i = 1; i < vertices; i++) { c = l[i]; for (int j = 0; j < dimOfWorld; j++) (*ret)[j] += c * coord_[i][j]; } return ret; } /****************************************************************************/ /* compute volume of an element */ /****************************************************************************/ double ElInfo::calcDet() const { testFlag(Mesh::FILL_COORDS); return calcDet(coord_); } double ElInfo::calcDet(const FixVec, VERTEX> &coords) { FUNCNAME("ElInfo::calcDet()"); int dim = coords.getSize() - 1; int dow = Global::getGeo(WORLD); TEST_EXIT_DBG(dim <= dow)("dim > dow\n"); double det = 0.0; if (dim == 0) return 1.0; // dim = dim of world WorldVector e1, e2, e3, v0; v0 = coords[0]; for (int i = 0; i < dow; i++) { e1[i] = coords[1][i] - v0[i]; if(dim > 1) e2[i] = coords[2][i] - v0[i]; if(dim > 2) e3[i] = coords[3][i] - v0[i]; } switch (dow) { case 1: det = coords[1][0] - coords[0][0]; break; case 2: if(dim == 1) { det = norm(&e1); } else { det = e1[0]*e2[1] - e1[1]*e2[0]; } break; case 3: { WorldVector n; if (dim > 1) { n[0] = e1[1] * e2[2] - e1[2] * e2[1]; n[1] = e1[2] * e2[0] - e1[0] * e2[2]; n[2] = e1[0] * e2[1] - e1[1] * e2[0]; } if (dim == 1) { det = norm(&e1); } else if (dim == 2) { det = norm(&n); } else if (dim == 3) { det = n[0] * e3[0] + n[1] * e3[1] + n[2] * e3[2]; } else ERROR_EXIT("not yet for problem dimension = %d", dim); break; } default: ERROR_EXIT("not yet for Global::getGeo(WORLD) = %d", dow); } return abs(det); } void ElInfo::testFlag(const Flag& flags) const { TEST_EXIT_DBG(fillFlag_.isSet(flags))("flag not set\n"); } void ElInfo::fillDetGrdLambda() { if (fillFlag_.isSet(Mesh::FILL_GRD_LAMBDA)) { det_ = calcGrdLambda(grdLambda_); } else { if (fillFlag_.isSet(Mesh::FILL_DET)) { det_ = calcDet(); } } } BoundaryType ElInfo::getBoundary(GeoIndex pos, int i) { static int indexOffset[3][3] = { { 0, 0, 0}, { 3, 0, 0}, {10, 4, 0} }; int dim = mesh_->getDim(); int posIndex = DIM_OF_INDEX(pos, dim); int offset = indexOffset[dim - 1][posIndex]; return boundary_[offset + i]; } }