/** \file Views.h */ #ifndef MY_VIEWS_H #define MY_VIEWS_H #include #include #include #include "AMDiS.h" #ifdef USE_BACKGROUNDMESH #include "BackgroundMesh.h" #endif #ifdef USE_KD_TREE #include "kdtree_nanoflann_dof.h" #endif using namespace AMDiS; /// Abstract-Function-Views /// ________________________________________________________________________________________________ /// result = 0.5*(f(x)+1) template struct PhaseView : AbstractFunction > { PhaseView(AbstractFunction > &fct_) : fct(fct_) {} PhaseView(AbstractFunction > *fct_) : fct(*fct_) {} T operator()(const WorldVector& x) const { return std::max(0.0, std::min(1.0, 0.5*(fct(x)+1.0))); } private: AbstractFunction > fct; }; /// result = 2*f(x)-1 template struct ChView : AbstractFunction > { ChView(AbstractFunction > &fct_) : fct(fct_) {} ChView(AbstractFunction > *fct_) : fct(*fct_) {} T operator()(const WorldVector& x) const { return std::max(-1.0, std::min(1.0, 2.0*fct(x)-1.0)); } private: AbstractFunction > fct; }; template struct MultView : AbstractFunction > { MultView(AbstractFunction > &fct_, double factor_) : fct(fct_), factor(factor_) {} MultView(AbstractFunction > *fct_, double factor_) : fct(*fct_), factor(factor_) {} T operator()(const WorldVector& x) const { return factor*fct(x); } private: AbstractFunction > fct; double factor; }; /// DOFVector-Views /// ________________________________________________________________________________________________ template struct DOFView : public DOFVector { typedef T result_type; DOFView(DOFVector *vec_) : DOFVector(vec_->getFeSpace(), "dof_view"), vector(vec_) { nullify(value0); } DOFView(DOFVector &vec_) : DOFVector(vec_.getFeSpace(), "dof_view"), vector(&vec_) { nullify(value0); } /// Returns \ref vec[i] inline const T& operator[](WorldVector &x) const { FUNCNAME("DOFVector::operator[x]"); DegreeOfFreedom idx = -1; WorldVector x_ = coordsView(x); bool inside = vector->getDofIdxAtPoint(x_, idx); return (inside ? operator[](idx) : value0); } /// Returns \ref vec[i] inline T& operator[](WorldVector &x) { FUNCNAME("DOFVector::operator[x]"); DegreeOfFreedom idx = -1; WorldVector x_ = coordsView(x); bool inside = vector->getDofIdxAtPoint(x_, idx); return (inside ? operator[](idx) : value0); } inline T& operator[](DegreeOfFreedom idx) { DOFVector::operator[](idx)= valueView(idx); return DOFVector::operator[](idx); } inline const T& operator[](DegreeOfFreedom idx) const { const T& swap(valueView(idx)); T& swap2 = const_cast(DOFVector::operator[](idx)); swap2 = swap; return swap2; } inline const T evalAtPoint(WorldVector &p, ElInfo *oldElInfo = NULL, T* valueReturn = NULL ) const { FUNCNAME("DOFVector::operator[x]"); WorldVector x_ = coordsView(p); const FiniteElemSpace* feSpace = vector->getFeSpace(); if (oldElInfo && feSpace->getMesh() == oldElInfo->getMesh()) { Mesh* mesh = feSpace->getMesh(); DimVec lambda(mesh->getDim(), NO_INIT); int k = oldElInfo->worldToCoord(x_, &lambda); if (k < 0) { std::vector localIndices; // DOF-indices of all DOFs in trinangle mtl::dense_vector uh; // evaluation of DOFVectors at QPs localIndices.resize(feSpace->getBasisFcts()->getNumber()); uh.change_dim(mesh->getDim()+1); feSpace->getBasisFcts()->getLocalIndices(oldElInfo->getElement(), feSpace->getAdmin(), localIndices); for (int l = 0; l < feSpace->getBasisFcts()->getNumber(); l++) uh[l] = (*vector)[localIndices[l]]; T value = feSpace->getBasisFcts()->evalUh(lambda, uh); return value; } } #ifdef USE_BACKGROUNDMESH using namespace experimental; bool use_backgroundmesh = false; Parameters::get("backgroundMesh->enabled",use_backgroundmesh); if (use_backgroundmesh) { Box* box = Box::provideBackgroundMesh(feSpace); int evaluation_accuracy = 0; Parameters::get("backgroundMesh->evaluation accuracy",evaluation_accuracy); T value = box->evalAtPoint(*vector, x_, evaluation_accuracy); return value; } #endif #ifdef USE_KD_TREE using namespace experimental; bool use_kdtree = false; Parameters::get("KD-Tree->enabled",use_kdtree); if (use_kdtree) { KD_Tree_Dof* tree = provideKDTree(feSpace); T value = tree->evalAtPoint(*vector, x_); return value; } #endif DegreeOfFreedom idx = -1; T value = value0; Mesh* mesh = feSpace->getMesh(); ElInfo *elInfo = mesh->createNewElInfo(); DimVec lambda(mesh->getDim(), NO_INIT); bool inside = mesh->findElInfoAtPoint(x_, elInfo, lambda, (oldElInfo ? oldElInfo->getMacroElement() : NULL), NULL, NULL); if (inside) { std::vector localIndices; mtl::dense_vector uh; localIndices.resize(feSpace->getBasisFcts()->getNumber()); uh.change_dim(feSpace->getBasisFcts()->getNumber()); feSpace->getBasisFcts()->getLocalIndices(elInfo->getElement(), feSpace->getAdmin(), localIndices); for (int l = 0; l < feSpace->getBasisFcts()->getNumber(); l++) uh[l] = valueView(localIndices[l]); value = feSpace->getBasisFcts()->evalUh(lambda, uh); } if (valueReturn) *valueReturn = value; delete elInfo; return value; } protected: virtual inline T valueView(DegreeOfFreedom idx) const { return (*vector)[idx]; } virtual inline WorldVector coordsView(WorldVector &x) const { return x; } void setDefaultValue(T& value0_) { value0 = value0_; }; DOFVector *vector; T value0; }; /// DOFVector-Views ... Value-Views /// ________________________________________________________________________________________________ template struct PhaseDOFView : public DOFView { typedef T result_type; PhaseDOFView(DOFVector &vec_) : DOFView(&vec_) {} PhaseDOFView(DOFVector *vec_) : DOFView(vec_) {} protected: inline T valueView(DegreeOfFreedom idx) const { return std::max(0.0, std::min(1.0, 0.5*((*DOFView::vector)[idx]+1.0))); } }; template struct InvPhaseView : public DOFView { typedef T result_type; InvPhaseView(DOFVector &vec_) : DOFView(&vec_) {} InvPhaseView(DOFVector *vec_) : DOFView(vec_) {} protected: inline T valueView(DegreeOfFreedom idx) const { return -(*DOFView::vector)[idx]; } }; /// DOFVector-Views ... Coord-Views /// ________________________________________________________________________________________________ /// vec[x] := vec.evalAtPoint(R^(-1) * x) template struct RotateView : public DOFView { typedef T result_type; RotateView(DOFVector &vec_, WorldMatrix R_) : DOFView(&vec_), R(R_) {} RotateView(DOFVector *vec_, WorldMatrix R_) : DOFView(vec_), R(R_) {} RotateView(DOFVector &vec_, double alpha) : DOFView(&vec_) { R.setDiag(1.0); R[0][0] = cos(alpha); R[0][1] = -sin(alpha); R[1][0] = sin(alpha); R[1][1] = cos(alpha); } RotateView(DOFVector *vec_, double alpha) : DOFView(vec_) { R.setDiag(1.0); R[0][0] = cos(alpha); R[0][1] = -sin(alpha); R[1][0] = sin(alpha); R[1][1] = cos(alpha); } protected: inline WorldVector coordsView(WorldVector &x) const { WorldVector x_; WorldMatrix R_ = R; for (int i = 0; i < R_.getNumRows(); i++) for (int j = 0; j < i; j++) std::swap(R_[i][j], R_[j][i]); x_.multMatrixVec(R_, x); return x_; } private: WorldMatrix R; }; /// vec[x] := vec.evalAtPoint(x ./ scale) template struct ScaleView : public DOFView { typedef T result_type; ScaleView(DOFVector &vec_, WorldVector scale_) : DOFView(&vec_), scale(scale_) {} ScaleView(DOFVector *vec_, WorldVector scale_) : DOFView(vec_), scale(scale_) {} ScaleView(DOFVector &vec_, double scale_) : DOFView(&vec_) { scale.set(scale_); } ScaleView(DOFVector *vec_, double scale_) : DOFView(vec_) { scale.set(scale_); } protected: inline WorldVector coordsView(WorldVector &x) const { WorldVector x_; for (int i = 0; i < x_.getSize(); i++) x_[i] = x[i]/scale[i]; return x_; } private: WorldVector scale; }; /// vec[x] := vec.evalAtPoint(x - shift) template struct ShiftView : public DOFView { typedef T result_type; ShiftView(DOFVector &vec_, WorldVector shift_) : DOFView(&vec_), shift(shift_) {} ShiftView(DOFVector *vec_, WorldVector shift_) : DOFView(vec_), shift(shift_) {} void setShift(WorldVector &shift_) { shift = shift_; } protected: inline WorldVector coordsView(WorldVector &x) const { WorldVector x_; for (int i = 0; i < x_.getSize(); i++) x_[i] = x[i]-shift[i]; return x_; } private: WorldVector shift; }; /// evalAtPoint for several Data-Structures /// ________________________________________________________________________________________________ // DOFVector can be accessed by locating the elInfo and than using barycentric coordinates // The default value, if p outside of geometry, is 0.0 template inline T evalAtPoint(const DOFVector &obj, WorldVector &p, ElInfo* oldElInfo = NULL) { const FiniteElemSpace* feSpace = obj.getFeSpace(); Mesh* mesh = feSpace->getMesh(); if (oldElInfo && feSpace->getMesh() == oldElInfo->getMesh()) { DimVec lambda(mesh->getDim(), NO_INIT); oldElInfo->worldToCoord(p, &lambda); std::vector localIndices; // DOF-indices of all DOFs in trinangle mtl::dense_vector uh; // evaluation of DOFVectors at QPs localIndices.resize(feSpace->getBasisFcts()->getNumber()); uh.change_dim(mesh->getDim()+1); feSpace->getBasisFcts()->getLocalIndices(oldElInfo->getElement(), feSpace->getAdmin(), localIndices); for (int l = 0; l < feSpace->getBasisFcts()->getNumber(); l++) uh[l] = obj[localIndices[l]]; T value = feSpace->getBasisFcts()->evalUh(lambda, uh); return value; } #ifdef USE_BACKGROUNDMESH using namespace experimental; bool use_backgroundmesh = false; Parameters::get("backgroundMesh->enabled",use_backgroundmesh); if (use_backgroundmesh) { Box* box = Box::provideBackgroundMesh(feSpace); int evaluation_accuracy = 0; Parameters::get("backgroundMesh->evaluation accuracy",evaluation_accuracy); T value = box->evalAtPoint(obj, p, evaluation_accuracy); return value; } #endif #ifdef USE_KD_TREE using namespace experimental; bool use_kdtree = false; Parameters::get("KD-Tree->enabled",use_kdtree); if (use_kdtree) { KD_Tree_Dof* tree = provideKDTree(feSpace); T value = tree->evalAtPoint(obj, p); return value; } #endif T value; nullify(value); ElInfo *elInfo = mesh->createNewElInfo(); DimVec lambda(mesh->getDim(), NO_INIT); std::vector localIndices; // DOF-indices of all DOFs in trinangle mtl::dense_vector uh; localIndices.resize(feSpace->getBasisFcts()->getNumber()); uh.change_dim(feSpace->getBasisFcts()->getNumber()); bool inside = mesh->findElInfoAtPoint(p, elInfo, lambda, NULL, NULL, NULL); if (inside) { feSpace->getBasisFcts()->getLocalIndices(elInfo->getElement(), obj.getFeSpace()->getAdmin(), localIndices); for (int l = 0; l < feSpace->getBasisFcts()->getNumber(); l++) uh[l] = obj[localIndices[l]]; value = feSpace->getBasisFcts()->evalUh(lambda, uh); } delete elInfo; return value; }; // DOFView can be accessed by own method template inline T evalAtPoint(const DOFView &obj, WorldVector &p, ElInfo* elInfo = NULL) { return obj.evalAtPoint(p, elInfo); }; // intrinsic types can return values directly template inline T evalAtPoint(T &obj, WorldVector &p, ElInfo* elInfo = NULL) { return obj; }; // AbstractFunctions with argument-type = WorldVector can be accessed directly template inline T evalAtPoint(AbstractFunction > &obj, WorldVector &p, ElInfo* elInfo = NULL) { return obj(p); }; /// Type-Traits for value_type of Data-Structures /// ________________________________________________________________________________________________ template struct ValueType { typedef T type; }; template struct ValueType > { typedef T type; }; template struct ValueType > { typedef T type; }; template struct ValueType > { typedef T type; }; template struct ValueType > { typedef T type; }; template struct ValueType > { typedef T type; }; template struct ValueType, Derived > >::type> { typedef double type; }; template struct ValueType >, Derived > >::type> { typedef WorldVector type; }; template struct ValueType >, Derived > >::type> { typedef double type; }; template struct ValueType, WorldVector >, Derived > >::type> { typedef WorldVector type; }; /// transformDOF by coords (independent of mesh and feSpace) /// ________________________________________________________________________________________________ // result = vec template inline void interpol_coords(Vector &vec, DOFVector &result) { typedef typename ValueType::type T; DOFVector > coords(result.getFeSpace(), "coords"); result.getFeSpace()->getMesh()->getDofIndexCoords(result.getFeSpace(), coords); DOFIterator > it_coords(&coords, USED_DOFS); DOFIterator it_result(&result, USED_DOFS); for (it_coords.reset(), it_result.reset(); !it_coords.end(); ++it_coords, ++it_result) { *it_result = evalAtPoint(vec, *it_coords); } }; // result = op(vec) template inline void transformDOF_coords(Vector &vec, DOFVector &result, AbstractFunction::type> *op) { typedef typename ValueType::type T; DOFVector > coords(result.getFeSpace(), "coords"); result.getFeSpace()->getMesh()->getDofIndexCoords(result.getFeSpace(), coords); DOFIterator > it_coords(&coords, USED_DOFS); DOFIterator it_result(&result, USED_DOFS); for (it_coords.reset(), it_result.reset(); !it_coords.end(); ++it_coords, ++it_result) { T value = evalAtPoint(vec, *it_coords); *it_result = (*op)(value); } }; // result = binary_op(vec1, vec2) template inline void transformDOF_coords(Vector1 &vec1, Vector2 &vec2, DOFVector &result, BinaryAbstractFunction::type, typename ValueType::type> *binary_op) { typedef typename ValueType::type T1; typedef typename ValueType::type T2; DOFVector > coords(result.getFeSpace(), "coords"); result.getFeSpace()->getMesh()->getDofIndexCoords(result.getFeSpace(), coords); DOFIterator > it_coords(&coords, USED_DOFS); DOFIterator it_result(&result, USED_DOFS); for (it_coords.reset(), it_result.reset(); !it_coords.end(); ++it_coords, ++it_result) { T1 value1 = evalAtPoint(vec1, *it_coords); T2 value2 = evalAtPoint(vec2, *it_coords); *it_result = (*binary_op)(value1, value2); } }; // result = tertiary_op(vec1, vec2, vec3) template inline void transformDOF_coords(Vector1 &vec1, Vector2 &vec2, Vector3 &vec3, DOFVector &result, TertiaryAbstractFunction::type, typename ValueType::type, typename ValueType::type> *tertiary_op) { typedef typename ValueType::type T1; typedef typename ValueType::type T2; typedef typename ValueType::type T3; DOFVector > coords(result.getFeSpace(), "coords"); result.getFeSpace()->getMesh()->getDofIndexCoords(result.getFeSpace(), coords); DOFIterator > it_coords(&coords, USED_DOFS); DOFIterator it_result(&result, USED_DOFS); for (it_coords.reset(), it_result.reset(); !it_coords.end(); ++it_coords, ++it_result) { T1 value1 = evalAtPoint(vec1, *it_coords); T2 value2 = evalAtPoint(vec2, *it_coords); T3 value3 = evalAtPoint(vec3, *it_coords); *it_result = (*tertiary_op)(value1, value2, value3); } }; // result = quart_op(vec1, vec2, vec3, vec4) template inline void transformDOF_coords(Vector1 &vec1, Vector2 &vec2, Vector3 &vec3, Vector4 &vec4, DOFVector &result, QuartAbstractFunction::type, typename ValueType::type, typename ValueType::type, typename ValueType::type> *quart_op) { typedef typename ValueType::type T1; typedef typename ValueType::type T2; typedef typename ValueType::type T3; typedef typename ValueType::type T4; DOFVector > coords(result.getFeSpace(), "coords"); result.getFeSpace()->getMesh()->getDofIndexCoords(result.getFeSpace(), coords); DOFIterator > it_coords(&coords, USED_DOFS); DOFIterator it_result(&result, USED_DOFS); for (it_coords.reset(), it_result.reset(); !it_coords.end(); ++it_coords, ++it_result) { T1 value1 = evalAtPoint(vec1, *it_coords); T2 value2 = evalAtPoint(vec2, *it_coords); T3 value3 = evalAtPoint(vec3, *it_coords); T4 value4 = evalAtPoint(vec4, *it_coords); *it_result = (*quart_op)(value1, value2, value3, value4); } }; #endif // MY_VIEWS_H