LCOV - code coverage report
Current view: top level - ugbase/lib_grid/algorithms/geom_obj_util - volume_util_impl.hpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 21 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 8 0

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2010-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Sebastian Reiter
       4              :  * 
       5              :  * This file is part of UG4.
       6              :  * 
       7              :  * UG4 is free software: you can redistribute it and/or modify it under the
       8              :  * terms of the GNU Lesser General Public License version 3 (as published by the
       9              :  * Free Software Foundation) with the following additional attribution
      10              :  * requirements (according to LGPL/GPL v3 §7):
      11              :  * 
      12              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      13              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      14              :  * 
      15              :  * (2) The following notice must be displayed at a prominent place in the
      16              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      17              :  * 
      18              :  * (3) The following bibliography is recommended for citation and must be
      19              :  * preserved in all covered files:
      20              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      21              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      22              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      23              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      24              :  *   flexible software system for simulating pde based models on high performance
      25              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      26              :  * 
      27              :  * This program is distributed in the hope that it will be useful,
      28              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      29              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      30              :  * GNU Lesser General Public License for more details.
      31              :  */
      32              : 
      33              : #ifndef __H__LIB_GRID__VOLUME_UTIL_IMPL__
      34              : #define __H__LIB_GRID__VOLUME_UTIL_IMPL__
      35              : 
      36              : #include <algorithm>
      37              : #include <vector>
      38              : #include "lib_grid/lg_base.h"
      39              : #include "common/static_assert.h"
      40              : #include "common/util/vec_for_each.h"
      41              : #include "lib_grid/grid_objects/hexahedron_rules.h"
      42              : #include "lib_grid/grid_objects/prism_rules.h"
      43              : #include "lib_grid/grid_objects/pyramid_rules.h"
      44              : 
      45              : namespace ug
      46              : {
      47              : ////////////////////////////////////////////////////////////////////////
      48              : template <class TAAPos>
      49              : bool
      50            0 : ContainsPoint(Volume* vol, const vector3& p, TAAPos aaPos)
      51              : {
      52              : //      iterate over face descriptors of the sides and check whether the point
      53              : //      lies inside or outside
      54            0 :         FaceDescriptor fd;
      55              :         vector3 n, dir;
      56              : 
      57              : //      to minimize rounding errors we'll compare against a small-constant which is
      58              : //      relative to the first edge of the examined volume.
      59            0 :         EdgeDescriptor ed;
      60            0 :         vol->edge_desc(0, ed);
      61            0 :         number len = EdgeLength(&ed, aaPos);
      62              : 
      63              :         // the constant should be relative to the same geometric measure as what it is
      64              :         // compared against later on, i.e. length*area, since otherwise problems arise
      65              :         // with geometries scaled to very small extensions;
      66              :         // which is why I changed sqrt(lenSq) to lenSq^1.5 (mbreit, 2015-05-11)
      67            0 :         const number locSmall = len * len * len * SMALL;
      68              : 
      69            0 :         for(size_t i = 0; i < vol->num_faces(); ++i){
      70            0 :                 vol->face_desc(i, fd);
      71            0 :                 CalculateNormalNoNormalize(n, &fd, aaPos);
      72              :                 VecSubtract(dir, aaPos[fd.vertex(0)], p);
      73              : 
      74            0 :                 if(VecDot(dir, n) < -locSmall)
      75              :                         return false;
      76              :         }
      77              :         return true;
      78              : }
      79              : 
      80              : ////////////////////////////////////////////////////////////////////////
      81              : //      PointIsInsideTetrahedron
      82              : inline bool
      83            0 : PointIsInsideTetrahedron(const vector3& v, Tetrahedron* tet,
      84              :                                                  Grid::VertexAttachmentAccessor<APosition>& aaPos)
      85              : {
      86            0 :         return PointIsInsideTetrahedron(v, aaPos[tet->vertex(0)], aaPos[tet->vertex(1)],
      87            0 :                                                                         aaPos[tet->vertex(2)], aaPos[tet->vertex(3)]);
      88              : }
      89              : 
      90              : ////////////////////////////////////////////////////////////////////////
      91              : //      CalculateCenter
      92              : template<class TVertexPositionAttachmentAccessor>
      93              : typename TVertexPositionAttachmentAccessor::ValueType
      94            0 : CalculateCenter(const VolumeVertices* vol, TVertexPositionAttachmentAccessor& aaPosVRT)
      95              : {
      96              :         typename TVertexPositionAttachmentAccessor::ValueType v;
      97              : //      init v with 0.
      98              :         VecSet(v, 0);
      99              : 
     100            0 :         size_t numVrts = vol->num_vertices();
     101            0 :         VolumeVertices::ConstVertexArray vrts = vol->vertices();
     102              : 
     103              : //      sum up
     104            0 :         for(size_t i = 0; i < numVrts; ++i)
     105              :         {
     106            0 :                 VecAdd(v, v, aaPosVRT[vrts[i]]);
     107              :         }
     108              : 
     109              : //      average
     110            0 :         if(numVrts > 0)
     111            0 :                 VecScale(v, v, 1./(number)numVrts);
     112              : 
     113            0 :         return v;
     114              : }
     115              : 
     116              : ////////////////////////////////////////////////////////////////////////
     117              : template<class TAAPosVRT, class TAAWeightVRT>
     118              : UG_API
     119              : typename TAAPosVRT::ValueType
     120              : CalculateCenter(const VolumeVertices* vol, TAAPosVRT& aaPos, TAAWeightVRT& aaWeight)
     121              : {
     122              :         typename TAAPosVRT::ValueType v;
     123              :         typedef typename TAAWeightVRT::ValueType weight_t;
     124              : 
     125              : //      init v with 0.
     126              :         VecSet(v, 0);
     127              : 
     128              :         size_t numVrts = vol->num_vertices();
     129              :         VolumeVertices::ConstVertexArray vrts = vol->vertices();
     130              : 
     131              : //      sum up
     132              :         weight_t totalWeight = 0;
     133              :         for(size_t i = 0; i < numVrts; ++i)
     134              :         {
     135              :                 weight_t w = aaWeight[vrts[i]];
     136              :                 VecScaleAppend(v, w, aaPos[vrts[i]]);
     137              :                 totalWeight += w;
     138              :         }
     139              : 
     140              : //      average
     141              :         if(totalWeight != 0)
     142              :                 VecScale(v, v, 1./(number)totalWeight);
     143              : 
     144              :         return v;
     145              : }
     146              : 
     147              : 
     148              : ///     Can be used to compare vertices of their grids through their hash-value.
     149              : template <class TElem>
     150              : class CmpVrtsByHash{
     151              :         public:
     152              :                 CmpVrtsByHash(TElem* e) : m_e(e) {};
     153              :                 bool operator () (int i0, int i1) {
     154              :                         return m_e->vertex(i0)->get_hash_value() < m_e->vertex(i1)->get_hash_value();
     155              :                 }
     156              :         private:
     157              :                 TElem* m_e;
     158              : };
     159              : 
     160              : 
     161              : template <class TVolIter>
     162              : void ConvertToTetrahedra (
     163              :                 Grid& grid,
     164              :                 TVolIter volsBegin,
     165              :                 TVolIter volsEnd)
     166              : {
     167              :         using namespace std;
     168              : 
     169              : //      first we'll collect all quadrilaterals that are connected to selected
     170              : //      volumes. Avoid 'grid.mark' here, since it may be used by 'grid.associated_elements'
     171              :         Grid::face_traits::secure_container     faces;
     172              :         vector<Face*>     quads;
     173              : 
     174              :         for(TVolIter iv = volsBegin; iv != volsEnd; ++iv){
     175              :                 grid.associated_elements(faces, *iv);
     176              :                 for_each_in_vec(Face* f, faces){
     177              :                         if(f->num_vertices() == 4)
     178              :                                 quads.push_back(f);
     179              :                 }end_for;
     180              :         }
     181              : 
     182              : //      remove double entries
     183              :         grid.begin_marking();
     184              :         size_t offset = 0;
     185              : 
     186              :         for(size_t i = 0; i + offset < quads.size();){
     187              :                 if(offset > 0)
     188              :                         quads[i] = quads[i + offset];
     189              :                 
     190              :                 if(!grid.is_marked(quads[i])){
     191              :                         grid.mark(quads[i]);
     192              :                         ++i;
     193              :                 }
     194              :                 else{
     195              :                         ++offset;
     196              :                 }
     197              :         }
     198              : 
     199              :         if(offset > 0)
     200              :                 quads.resize(quads.size() - offset);
     201              : 
     202              :         grid.end_marking();
     203              : 
     204              :         for_each_in_vec(Face* f, quads){
     205              : //todo  in a parallel environment, global id's should be compared here
     206              :                 CmpVrtsByHash<Face> cmp(f);
     207              :         //      get the smallest vertex of the face
     208              :                 int smallest = 0;
     209              :                 for(int i = 1; i < 4; ++i){
     210              :                         if(cmp(i, smallest))
     211              :                                 smallest = i;
     212              :                 }
     213              : 
     214              :                 int i0 = smallest;
     215              :                 int i1 = (smallest + 1) % 4;
     216              :                 int i2 = (smallest + 2) % 4;
     217              :                 int i3 = (smallest + 3) % 4;
     218              :                 grid.create<Triangle>(TriangleDescriptor(f->vertex(i0), f->vertex(i1), f->vertex(i2)), f);
     219              :                 grid.create<Triangle>(TriangleDescriptor(f->vertex(i2), f->vertex(i3), f->vertex(i0)), f);
     220              :         }end_for;
     221              : 
     222              : 
     223              : //      now convert the given volume-elements
     224              :         UG_STATIC_ASSERT((prism_rules::MAX_NUM_CONVERT_TO_TETS_INDS_OUT < 
     225              :                                                         hex_rules::MAX_NUM_CONVERT_TO_TETS_INDS_OUT) &&
     226              :                                                 (pyra_rules::MAX_NUM_CONVERT_TO_TETS_INDS_OUT <
     227              :                                                         hex_rules::MAX_NUM_CONVERT_TO_TETS_INDS_OUT),
     228              :                                          HEX_RULES_MAX_NUM_CONVERT_TO_TETS_INDS_OUT__considered_to_be_highest_among_prism_pyra_and_hex);
     229              :         static const int arrayLen = hex_rules::MAX_NUM_CONVERT_TO_TETS_INDS_OUT;
     230              :         int inds[arrayLen];
     231              :         
     232              :         vector<Volume*> volsToErase;
     233              :         for(TVolIter iv = volsBegin; iv != volsEnd; ++iv){
     234              :                 Volume* vol = *iv;
     235              :                 const ReferenceObjectID roid = vol->reference_object_id();
     236              :                 CmpVrtsByHash<Volume> cmp(vol);
     237              :                 size_t numEntries = 0;
     238              : 
     239              :                 switch(roid){
     240              :                         case ROID_PYRAMID:
     241              :                                 numEntries = pyra_rules::ConvertToTetrahedra(inds, cmp);
     242              :                                 break;
     243              : 
     244              :                         case ROID_PRISM:
     245              :                                 numEntries = prism_rules::ConvertToTetrahedra(inds, cmp);
     246              :                                 break;
     247              : 
     248              :                         case ROID_HEXAHEDRON:
     249              :                                 UG_THROW("ConvertToTetrahedra for hexahedra not yet implemented!");
     250              :                                 break;
     251              :                         default:
     252              :                                 break;
     253              :                 }
     254              : 
     255              :                 if(numEntries > 0){
     256              :                         volsToErase.push_back(vol);
     257              :                         size_t i = 0;
     258              :                         Volume::ConstVertexArray vrts = vol->vertices();
     259              :                         while(i < numEntries){
     260              :                                 int goid = inds[i++];
     261              :                                 UG_COND_THROW(goid != GOID_TETRAHEDRON,
     262              :                                                           "Only tetrahedra may result from ConvertToTetrahedra");
     263              :                                 int i0 = inds[i++];
     264              :                                 int i1 = inds[i++];
     265              :                                 int i2 = inds[i++];
     266              :                                 int i3 = inds[i++];
     267              :                                 grid.create<Tetrahedron>(
     268              :                                         TetrahedronDescriptor(vrts[i0], vrts[i1], vrts[i2], vrts[i3]),
     269              :                                         vol);
     270              :                         }
     271              :                 }
     272              :         }
     273              : 
     274              : //      finally erase all unused volumes and quadrilaterals
     275              :         for_each_in_vec(Volume* v, volsToErase){
     276              :                 grid.erase(v);
     277              :         }end_for;
     278              : 
     279              :         Grid::volume_traits::secure_container   assVols;
     280              :         for_each_in_vec(Face* f, quads){
     281              :                 grid.associated_elements(assVols, f);
     282              :                 if(assVols.empty())
     283              :                         grid.erase(f);
     284              :         }end_for;
     285              : }
     286              : 
     287              : }//     end of namespace
     288              : 
     289              : #endif
        

Generated by: LCOV version 2.0-1