#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), oppVertex_(mesh_->getDim(), NO_INIT), grdLambda_(mesh_->getDim(), NO_INIT) //parametric_(false) { projection_.set(NULL); } 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 { return coordToWorld(l, &coord_, w); } const WorldVector *ElInfo::coordToWorld(const DimVec& l, const FixVec, VERTEX> *coords, WorldVector *w) { static WorldVector world; double c; WorldVector *ret; WorldVector v; int i, j; int dim = l.getSize() - 1; int dimOfWorld = Global::getGeo(WORLD); ret = w ? w : &world; v = (*coords)[0]; c = l[0]; for (j = 0; j < dimOfWorld; j++) (*ret)[j] = c*v[j]; int vertices = Global::getGeo(VERTEX, dim); for (i = 1; i < vertices; i++) { v = (*coords)[i]; c = l[i]; for (j = 0; j < dimOfWorld; j++) (*ret)[j] += c*v[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 i; int dim = coords.getSize() - 1; int dow = Global::getGeo(WORLD); TEST_EXIT(dim <= dow)("dim > dow\n"); double det = 0.0; // --> changes Christina if (dim == 0) return 1.0; // --> end: changes Christina // dim = dim of world WorldVector e1, e2, e3, v0; v0 = coords[0]; for (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(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]; } // BoundaryType ElInfo::getBoundOfBoundary(int i) const { // WARNING("USE: getBoundary() instead of getBoundOfBoundary()\n"); // TEST_EXIT(boundary_)("no boundary\n"); // return (*boundary_)[i]; // } }