LCOV - code coverage report
Current view: top level - ugbase/lib_grid/tools - surface_view.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 59 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 17 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              : #include <sstream>
      34              : #include "surface_view.h"
      35              : #include "common/assert.h"
      36              : #include "lib_grid/parallelization/util/compol_boolmarker.h"
      37              : #include "lib_grid/file_io/file_io.h"
      38              : #include "periodic_boundary_manager.h"
      39              : 
      40              : #ifdef UG_PARALLEL
      41              :         #include "pcl/pcl_interface_communicator.h"
      42              :         #include "pcl/pcl_process_communicator.h"
      43              :         #include "lib_grid/parallelization/util/compol_copy_attachment.h"
      44              : #endif
      45              : 
      46              : using namespace std;
      47              : 
      48              : namespace ug{
      49              : 
      50              : ///     adds marking at extracting side
      51              : //todo: change to ComPol_AttachmentBinaryOr
      52              : template <class TLayout>
      53              : class ComPol_GatherSurfaceStates : public pcl::ICommunicationPolicy<TLayout>
      54              : {
      55              :         public:
      56              :                 typedef TLayout                                                         Layout;
      57              :                 typedef typename Layout::Type                           GeomObj;
      58              :                 typedef typename Layout::Element                        Element;
      59              :                 typedef typename Layout::Interface                      Interface;
      60              :                 typedef typename Interface::const_iterator      InterfaceIter;
      61              : 
      62              :         ///     Construct the communication policy with a ug::BoolMarker.
      63              :                 ComPol_GatherSurfaceStates(MultiGrid& mg,
      64              :                                                 MultiElementAttachmentAccessor<SurfaceView::ASurfaceState>& aaElemSurfState)
      65              :                          :      m_mg(mg), m_aaESS(aaElemSurfState)
      66              :                 {}
      67              : 
      68              :                 virtual ~ComPol_GatherSurfaceStates()   {}
      69              : 
      70              :                 virtual int get_required_buffer_size(const Interface& interface)
      71              :                 {
      72              :                         return interface.size() * sizeof(byte);
      73              :                 }
      74              : 
      75              :         ///     write surface state for each entry
      76              :                 virtual bool collect(ug::BinaryBuffer& buff, const Interface& intfc)
      77              :                 {
      78              :                 //      write the entry indices of marked elements.
      79              :                         for(InterfaceIter iter = intfc.begin(); iter != intfc.end(); ++iter)
      80              :                         {
      81              :                                 Element elem = intfc.get_element(iter);
      82              :                                 byte val = m_aaESS[elem].get();
      83              :                                 buff.write((char*)&val, sizeof(byte));
      84              :                         }
      85              :                         return true;
      86              :                 }
      87              : 
      88              :         ///     reads marks from the given stream
      89              :                 virtual bool extract(ug::BinaryBuffer& buff, const Interface& intfc)
      90              :                 {
      91              :                         for(InterfaceIter iter = intfc.begin(); iter != intfc.end(); ++iter)
      92              :                         {
      93              :                                 Element elem = intfc.get_element(iter);
      94              :                                 byte nv;
      95              :                                 buff.read((char*)&nv, sizeof(byte));
      96              :                                 if(nv > m_aaESS[elem].get())
      97              :                                         m_aaESS[elem] = nv;
      98              :                         }
      99              :                         return true;
     100              :                 }
     101              : 
     102              :         protected:
     103              :                 MultiGrid&                                                                                                  m_mg;
     104              :                 MultiElementAttachmentAccessor<SurfaceView::ASurfaceState>        m_aaESS;
     105              : };
     106              : 
     107              : ////////////////////////////////////////////////////////////////////////////////
     108              : //      Create Surface View
     109              : ////////////////////////////////////////////////////////////////////////////////
     110              : template <class TElem>
     111            0 : bool SurfaceView::
     112              : is_local_surface_view_element(TElem* elem)
     113              : {
     114              :         #ifdef UG_PARALLEL
     115              :                 return !(m_pMG->has_children(elem)
     116              :                                  || m_distGridMgr->is_ghost(elem));
     117              :         #else
     118            0 :                 return !m_pMG->has_children(elem);
     119              :         #endif
     120              : }
     121              : 
     122            0 : void SurfaceView::
     123              : refresh_surface_states()
     124              : {
     125              : //todo  we need a global max-dim!!! (empty processes have to do the right thing, too)
     126              :         int maxElem = -1;
     127            0 :         if(m_pMG->num<Volume>() > 0) maxElem = VOLUME;
     128            0 :         else if(m_pMG->num<Face>() > 0) maxElem = FACE;
     129            0 :         else if(m_pMG->num<Edge>() > 0) maxElem = EDGE;
     130            0 :         else if(m_pMG->num<Vertex>() > 0) maxElem = VERTEX;
     131              : 
     132              :         #ifdef UG_PARALLEL
     133              :                 pcl::ProcessCommunicator pc;
     134              :                 maxElem = pc.allreduce(maxElem, PCL_RO_MAX);
     135              :         #endif
     136              : 
     137              :         switch(maxElem){
     138            0 :                 case VOLUME: refresh_surface_states<Volume>(); break;
     139            0 :                 case FACE:refresh_surface_states<Face>(); break;
     140            0 :                 case EDGE: refresh_surface_states<Edge>(); break;
     141            0 :                 case VERTEX: refresh_surface_states<Vertex>(); break;
     142              :                 default: break;
     143              :         }
     144            0 : }
     145              : 
     146              : template <class TElem>
     147            0 : void SurfaceView::
     148              : refresh_surface_states()
     149              : {
     150              : //      some typedefs
     151              :         typedef typename geometry_traits<TElem>::iterator ElemIter;
     152              : 
     153            0 :         MultiGrid& mg = *m_pMG;
     154              : 
     155              : //      reset surface states of all elements. Initially, we'll set all states to hidden
     156              :         SetAttachmentValues(m_aaSurfState, mg.begin<Vertex>(), mg.end<Vertex>(), MG_SHADOW_PURE);
     157              :         SetAttachmentValues(m_aaSurfState, mg.begin<Edge>(), mg.end<Edge>(), MG_SHADOW_PURE);
     158              :         SetAttachmentValues(m_aaSurfState, mg.begin<Face>(), mg.end<Face>(), MG_SHADOW_PURE);
     159              :         SetAttachmentValues(m_aaSurfState, mg.begin<Volume>(), mg.end<Volume>(), MG_SHADOW_PURE);
     160              : 
     161              : //      iterate through all levels of the mgsh
     162            0 :         for(size_t level = 0; level < mg.num_levels(); ++level)
     163              :         {
     164              :         //      iterate through all elements on that level
     165            0 :                 for(ElemIter iter = mg.begin<TElem>(level);
     166            0 :                         iter != mg.end<TElem>(level); ++iter)
     167              :                 {
     168              :                         TElem* elem = *iter;
     169              : 
     170            0 :                         if(is_local_surface_view_element(elem)){
     171              :                                 surface_state(elem).set(MG_SURFACE_PURE);
     172            0 :                                 mark_sides_as_surface_or_shadow<TElem, typename TElem::side>(elem);
     173              :                         }
     174              :                 }
     175              :         }
     176              : 
     177              : //      we now have to mark all shadowing elements.
     178              : //      Only low dimensional elements can be shadows.
     179              : //      Perform assignment on higher dimensional elements first, since lower
     180              : //      dimensional elements may shadow higher dimensional elements...
     181              :         if(TElem::HAS_SIDES){
     182              :         //      communicate states between all processes
     183              :         //      this is necessary here, since mark_shadowing relies on correct SHADOWED marks.
     184              :                 adjust_parallel_surface_states<Vertex>();
     185              :                 adjust_parallel_surface_states<Edge>();
     186              :                 adjust_parallel_surface_states<Face>();
     187              :                 adjust_parallel_surface_states<Volume>();
     188            0 :                 mark_shadowing<typename TElem::side>(true);
     189              :         }
     190              : 
     191              : //      communicate states between all processes
     192              :         adjust_parallel_surface_states<Vertex>();
     193              :         adjust_parallel_surface_states<Edge>();
     194              :         adjust_parallel_surface_states<Face>();
     195              :         adjust_parallel_surface_states<Volume>();
     196            0 : }
     197              : 
     198              : template <class TElem, class TSide>
     199            0 : void SurfaceView::
     200              : mark_sides_as_surface_or_shadow(TElem* elem, byte surfaceState)
     201              : {
     202              :         typedef typename PeriodicBoundaryManager::Group<TSide>::SlaveContainer
     203              :                 periodic_slave_container_t;
     204              :         typedef typename periodic_slave_container_t::iterator periodic_slave_iterator_t;
     205              : 
     206              :         if(!TElem::HAS_SIDES)
     207              :                 return;
     208              : 
     209              :         typename Grid::traits<TSide>::secure_container    sides;
     210            0 :         PeriodicBoundaryManager* pdm = m_pMG->periodic_boundary_manager();
     211              : 
     212            0 :         m_pMG->associated_elements(sides, elem);
     213            0 :         for(size_t i = 0; i < sides.size(); ++i){
     214              :                 TSide* s = sides[i];
     215            0 :                 if(surface_state(s) == MG_SHADOW_PURE){
     216            0 :                         size_t numChildren = m_pMG->num_children<TSide>(s);
     217            0 :                         if(numChildren == 0)
     218              :                                 surface_state(s).set(surfaceState);
     219            0 :                         else if(numChildren == 1)
     220              :                                 surface_state(s).set(MG_SHADOW_RIM_COPY);
     221              :                         else
     222              :                                 surface_state(s).set(MG_SHADOW_RIM_NONCOPY);
     223              : 
     224              :                 //      if a periodic boundary manager exists, we have to copy this state
     225              :                 //      to all linked elements
     226            0 :                         if(pdm && pdm->is_periodic(s)){
     227            0 :                                 TSide* master = pdm->master(s);
     228              :                                 surface_state(master) = surface_state(s);
     229            0 :                                 periodic_slave_container_t* slaves = pdm->slaves(master);
     230            0 :                                 for(periodic_slave_iterator_t i = slaves->begin();
     231            0 :                                         i != slaves->end(); ++i)
     232              :                                 {
     233            0 :                                         surface_state(*i) = surface_state(master);
     234              :                                 }
     235              :                         }
     236              :                 }
     237              :         }
     238              : 
     239              :         if(TSide::HAS_SIDES)
     240            0 :                 mark_sides_as_surface_or_shadow<TElem, typename TSide::side>(elem, surfaceState);
     241              : }
     242              : 
     243              : template <class TElem>
     244            0 : void SurfaceView::
     245              : mark_shadowing(bool markSides)
     246              : {
     247              :         typedef typename Grid::traits<TElem>::iterator TIter;
     248              : 
     249            0 :         MultiGrid& mg = *m_pMG;
     250              : 
     251            0 :         for(size_t lvl = 1; lvl < mg.num_levels(); ++lvl){
     252            0 :                 for(TIter iter = mg.begin<TElem>(lvl); iter != mg.end<TElem>(lvl); ++iter)
     253              :                 {
     254              :                         TElem* e = *iter;
     255            0 :                         if(surface_state(e).contains(MG_SHADOW_PURE))
     256            0 :                                 continue;
     257              : 
     258              :                         GridObject* p = mg.get_parent(e);
     259            0 :                         if(p && (surface_state(p).contains(MG_SHADOW_RIM_COPY)
     260            0 :                                          || surface_state(p).contains(MG_SHADOW_RIM_NONCOPY)))
     261              :                         {
     262              :                                 #ifdef UG_PARALLEL
     263              :                                 //      The following assertions make sure that during gmg no values have to
     264              :                                 //      be copied across v-interfaces during add-missing-coarse-grid-correction etc.
     265              :                                 //      However, when a closure is used, shadowing shadows do currently exist
     266              :                                 //      and this is why the assertion is only triggered for parallel cases
     267              :                                 //      (in which closure isn't assumed to work anyways).
     268              :                                 //      The assertion probably shouldn't be done here but directly in the gmg.
     269              :                                         UG_COND_THROW((pcl::NumProcs() > 1) &&
     270              :                                                                   surface_state(e).contains(MG_SHADOW_RIM_COPY),
     271              :                                                                   "SHADOWING-SHADOW_COPY encountered: " << ElementDebugInfo(mg, e));
     272              :                                         UG_COND_THROW((pcl::NumProcs() > 1) &&
     273              :                                                                   surface_state(e).contains(MG_SHADOW_RIM_NONCOPY),
     274              :                                                                   "SHADOWING-SHADOW_NONCOPY encountered: " << ElementDebugInfo(mg, e));
     275              :                                 #endif
     276              :                                 surface_state(e).add(MG_SURFACE_RIM);
     277              :                                 surface_state(e).remove(MG_SURFACE_PURE);
     278              :                         }
     279              :                 }
     280              :         }
     281              : 
     282            0 :         if(markSides && TElem::HAS_SIDES){
     283            0 :                 mark_shadowing<typename TElem::side>(markSides);
     284              :         }
     285            0 : }
     286              : 
     287              : template <class TElem>
     288              : void SurfaceView::
     289              : adjust_parallel_surface_states()
     290              : {
     291              :         #ifdef UG_PARALLEL
     292              :                 typedef typename GridLayoutMap::Types<TElem>::Layout      Layout;
     293              : 
     294              :                 GridLayoutMap& glm = m_distGridMgr->grid_layout_map();
     295              :                 ComPol_GatherSurfaceStates<Layout>        cpAdjust(*m_pMG, m_aaSurfState);
     296              :                 pcl::InterfaceCommunicator<Layout> com;
     297              :                 com.exchange_data(glm, INT_H_SLAVE, INT_H_MASTER, cpAdjust);
     298              :         //      the v-communication is only required if constrained ghosts can be surface elements.
     299              :                 com.exchange_data(glm, INT_V_MASTER, INT_V_SLAVE, cpAdjust);
     300              :                 com.communicate();
     301              : 
     302              :                 ComPol_CopyAttachment<Layout, ASurfaceState> cpCopyStates(*m_pMG, m_aSurfState);
     303              :                 com.exchange_data(glm, INT_H_MASTER, INT_H_SLAVE, cpCopyStates);
     304              :                 com.communicate();
     305              : 
     306              :         //  communicate final marks to v-masters (if one wants to iterate over ghosts...)
     307              :                 com.exchange_data(glm, INT_V_SLAVE, INT_V_MASTER, cpCopyStates);
     308              :                 com.communicate();
     309              :         #endif
     310              : }
     311              : 
     312              : 
     313              : ////////////////////////////////////////////////////////////////////////////////
     314              : // SurfaceView
     315              : ////////////////////////////////////////////////////////////////////////////////
     316              : 
     317            0 : SurfaceView::SurfaceView(SmartPtr<MGSubsetHandler> spMGSH,
     318            0 :                          bool adaptiveMG) :
     319              :         m_spMGSH(spMGSH),
     320            0 :         m_adaptiveMG(adaptiveMG),
     321            0 :         m_pMG(m_spMGSH->multi_grid()),
     322            0 :         m_distGridMgr(m_spMGSH->multi_grid()->distributed_grid_manager())
     323              : {
     324              :         UG_ASSERT(m_pMG, "A MultiGrid has to be assigned to the given subset handler");
     325              : 
     326            0 :         m_pMG->attach_to_all_dv(m_aSurfState, 0);
     327            0 :         m_aaSurfState.access(*m_pMG, m_aSurfState);
     328              : 
     329            0 :         refresh_surface_states();
     330            0 : }
     331              : 
     332            0 : SurfaceView::~SurfaceView()
     333              : {
     334            0 :         m_pMG->detach_from_all(m_aSurfState);
     335            0 : }
     336              : 
     337              : }// end of namespace
        

Generated by: LCOV version 2.0-1