LCOV - code coverage report
Current view: top level - ugbase/lib_grid/tools - copy_attachment_handler.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 51 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 12 0

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Markus Breit
       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 LIB_GRID__COPY_ATTACHMENT_HANDLER_H_
      34              : #define LIB_GRID__COPY_ATTACHMENT_HANDLER_H_
      35              : 
      36              : #include "common/util/smart_pointer.h"  // for SmartPtr
      37              : #include "lib_grid/grid/grid_observer.h"  // for GridObserver
      38              : #include "lib_grid/multi_grid.h"  // for MultiGrid
      39              : 
      40              : #ifdef UG_PARALLEL
      41              :     #include "lib_grid/parallelization/util/compol_copy_attachment.h" // ComPol_CopyAttachment
      42              :     #include "lib_grid/parallelization/distributed_grid.h"        // DistributedGridManager
      43              : #endif
      44              : 
      45              : namespace ug{
      46              : 
      47              : 
      48              : /**
      49              :  * @brief handler for attachments in a multi-grid
      50              :  *
      51              :  * When using attachments in a multi-grid hierarchy, one
      52              :  * EITHER needs to create the attachment after the geometry is refined (and distributed)
      53              :  * up to the state in which the attachments are used - in this case, every geometric
      54              :  * object which the data is attached to will have its attachment and there is no problem
      55              :  * OR one creates the attachment before the geometry is refined (and distributed) - in
      56              :  * this case, if the attachment is required on elements that are created after creation
      57              :  * of the attachment, one needs to take care to supply those elements with attachment
      58              :  * values. This class will do exactly this, but only to a very limited extent:
      59              :  *
      60              :  * When this class is assigned a multi-grid, it will propagate attachment values from the
      61              :  * base level upwards to the children <b>of the same type<\b> by copying.
      62              :  * Vertical communication is performed on each level to make sure that all those children
      63              :  * will get their values.
      64              :  *
      65              :  * Moreover, making use of the GridObserver interface, this class will copy attachment
      66              :  * values to each child element (of equal type as their parent) created after assignment
      67              :  * of the grid.
      68              :  *
      69              :  *
      70              :  * This will not, in general, guarantee that every element of the required type will
      71              :  * get an attachment value. It will however suffice if the element type the attachment is
      72              :  * attached to is full-dimensional (in its domain); it will obviously also suffice if the
      73              :  * attachment values are only required on direct children (of equal type) of coarse grid
      74              :  * elements, e.g. on d-dimensional elements on a d-dimensional manifold.
      75              :  *
      76              :  * Example:
      77              :  *
      78              :  * If, in the base level, attachments (a1, a2) are attached to their resp. nodes like this:
      79              :  *
      80              :  *  a1 --------- a2    <-- lvl 0
      81              :  *
      82              :  * then, on the next level, the node marked by "o" will not have an attachment value
      83              :  * propagated from below (since it does not have a parent of the same type):
      84              :  *
      85              :  *  a1 --- o --- a2    <-- lvl 1
      86              :  *
      87              :  *  a1 --------- a2    <-- lvl 0
      88              :  *
      89              :  * You may, however, choose to derive another handler class from this implementation
      90              :  * and treat the cases where an upper-level element is child of an element of different
      91              :  * type there by overloading copy_from_other_elem_type().
      92              :  * In the same manner, you might use derivation and overloading (of the copy() method)
      93              :  * to perform a more specialized way of copying.
      94              :  *
      95              :  * @note Implementation relies on a template trick: One cannot - as decreed by the
      96              :  * standard - specialize template methods of a not fully specialized template class;
      97              :  * it is possible, however, to @e partially specialize nested template classes of a
      98              :  * template class. This is what is used here.
      99              :  *
     100              :  */
     101              : template <typename TElem, typename TAttachment>
     102              : class CopyAttachmentHandler : public GridObserver
     103              : {
     104              :         public:
     105              :                 /// constructor
     106            0 :                 CopyAttachmentHandler()
     107            0 :                 : m_bEnableVertComm(true) {}
     108              : 
     109              :                 /// destructor
     110            0 :                 virtual ~CopyAttachmentHandler()
     111              :                 {
     112            0 :                         if (m_spMG.valid())
     113            0 :                                 m_spMG->unregister_observer(this);
     114              : 
     115              :                         m_aa.invalidate();
     116            0 :                 };
     117              : 
     118              :                 void set_attachment(const TAttachment& attch)
     119              :                 {
     120              :                         m_a = attch;
     121              : 
     122              :                         // if we already have a grid, then this must be a reset
     123            0 :                         if (m_spMG.valid())
     124              :                         {
     125              :                                 m_aa.invalidate();
     126            0 :                                 m_aa.access(*m_spMG, m_a);
     127              :                         }
     128              :                 }
     129              : 
     130            0 :                 void set_grid(SmartPtr<MultiGrid> mg)
     131              :                 {
     132              :                         // do nothing if given grid is already set
     133            0 :                         if (m_spMG == mg) return;
     134              : 
     135              :                         // if another grid is already given, unregister from old grid and invalidate accessor
     136            0 :                         if (m_spMG.valid())
     137              :                         {
     138            0 :                                 m_spMG->unregister_observer(this);
     139              :                                 m_aa.invalidate();
     140              :                         }
     141              : 
     142              :                         // set new grid
     143            0 :                         m_spMG = mg;
     144            0 :                         UG_COND_THROW(!m_spMG.valid(), "No valid multigrid given!");
     145              : 
     146              :                         // register as appropriate observer
     147            0 :                         register_as_observer<TElem, void>(m_spMG, this);
     148              : 
     149              :                         // check that attachment is attached to grid
     150            0 :                         UG_COND_THROW(!m_spMG->has_attachment<TElem>(m_a),
     151              :                                                   "Given grid does not have given attachment attached to it.");
     152              : 
     153              :                         // init accessor
     154            0 :                         m_aa.access(*m_spMG, m_a);
     155              : 
     156              :                         // copy to all levels that are already present
     157            0 :                         propagate_to_levels();
     158              :                 }
     159              : 
     160              :                 void enable_vertical_communication(bool b)
     161              :                 {
     162              :                         m_bEnableVertComm = b;
     163              :                 }
     164              : 
     165              : 
     166              :                 // GridObserver implementations
     167            0 :                 virtual void vertex_created
     168              :                 (
     169              :                         Grid* grid,
     170              :                         Vertex* vrt,
     171              :                         GridObject* pParent = NULL,
     172              :                         bool replacesParent = false
     173              :                 )
     174              :                 {
     175            0 :                         propagate<Vertex, void>(vrt, pParent, this);
     176            0 :                 }
     177              : 
     178            0 :                 virtual void edge_created
     179              :                 (
     180              :                         Grid* grid,
     181              :                         Edge* e,
     182              :                         GridObject* pParent = NULL,
     183              :                         bool replacesParent = false
     184              :                 )
     185              :                 {
     186              :                         propagate<Edge, void>(e, pParent, this);
     187            0 :                 }
     188              : 
     189            0 :                 virtual void face_created
     190              :                 (
     191              :                         Grid* grid,
     192              :                         Face* f,
     193              :                         GridObject* pParent = NULL,
     194              :                         bool replacesParent = false
     195              :                 )
     196              :                 {
     197              :                         propagate<Face, void>(f, pParent, this);
     198            0 :                 }
     199              : 
     200            0 :                 virtual void volume_created
     201              :                 (
     202              :                         Grid* grid,
     203              :                         Volume* vol,
     204              :                         GridObject* pParent = NULL,
     205              :                         bool replacesParent = false
     206              :                 )
     207              :                 {
     208              :                         propagate<Volume, void>(vol, pParent, this);
     209            0 :                 }
     210              : 
     211              :         protected:
     212              : 
     213              :                 // this template will be used if created is called with anything BUT TElem (in that case: do nothing)
     214              :                 template <typename TCreatedElem, typename Dummy>
     215              :                 struct propagate
     216              :                 {
     217              :                         propagate(TCreatedElem* elem, GridObject* pParent, CopyAttachmentHandler<TElem, TAttachment>* cah) {};
     218              :                 };
     219              : 
     220              :                 // this template will be used if created is called with an elem of type TElem
     221              :                 template <typename Dummy>
     222              :                 struct propagate<TElem, Dummy>
     223              :                 {
     224            0 :                         propagate(TElem* elem, GridObject* pParent, CopyAttachmentHandler<TElem, TAttachment>* cah)
     225              :                         {
     226              :                                 // check that parent is given
     227            0 :                                 if (!pParent) return;
     228              : 
     229              :                                 // if parent is of different elem type than child
     230            0 :                                 TElem* par = dynamic_cast<TElem*>(pParent);
     231            0 :                                 if (!par)
     232              :                                 {
     233            0 :                                         cah->copy_from_other_elem_type(pParent, elem);
     234            0 :                                         return;
     235              :                                 }
     236              : 
     237              :                                 // copy attachment value from parent to child
     238            0 :                                 cah->copy(par, elem);
     239              :                         }
     240              :                 };
     241              : 
     242              :                 friend struct propagate<TElem, void>;
     243              : 
     244              :                 template <typename TObserverElem, typename Dummy>
     245              :                 struct register_as_observer
     246              :                 {
     247              :                         register_as_observer(SmartPtr<MultiGrid> mg, CopyAttachmentHandler<TObserverElem, TAttachment>* cah) {};
     248              :                 };
     249              : 
     250              :                 template <typename Dummy>
     251              :                 struct register_as_observer<Vertex, Dummy>
     252              :                 {
     253              :                         register_as_observer(SmartPtr<MultiGrid> mg, CopyAttachmentHandler<Vertex, TAttachment>* cah)
     254              :                         {
     255            0 :                                 mg->register_observer(cah, OT_VERTEX_OBSERVER);
     256            0 :                         }
     257              :                 };
     258              :                 template <typename Dummy>
     259              :                 struct register_as_observer<Edge, Dummy>
     260              :                 {
     261              :                         register_as_observer(SmartPtr<MultiGrid> mg, CopyAttachmentHandler<Edge, TAttachment>* cah)
     262              :                         {
     263              :                                 mg->register_observer(cah, OT_EDGE_OBSERVER);
     264              :                         }
     265              :                 };
     266              :                 template <typename Dummy>
     267              :                 struct register_as_observer<Face, Dummy>
     268              :                 {
     269              :                         register_as_observer(SmartPtr<MultiGrid> mg, CopyAttachmentHandler<Face, TAttachment>* cah)
     270              :                         {
     271              :                                 mg->register_observer(this, OT_FACE_OBSERVER);
     272              :                         }
     273              :                 };
     274              :                 template <typename Dummy>
     275              :                 struct register_as_observer<Volume, Dummy>
     276              :                 {
     277              :                         register_as_observer(SmartPtr<MultiGrid> mg, CopyAttachmentHandler<Volume, TAttachment>* cah)
     278              :                         {
     279              :                                 mg->register_observer(this, OT_VOLUME_OBSERVER);
     280              :                         }
     281              :                 };
     282              : 
     283              : 
     284            0 :                 void propagate_to_levels()
     285              :                 {
     286              :                         // ensure a final vertical communication on the top level
     287            0 :                         const size_t nProp = m_bEnableVertComm ? m_spMG->num_levels() + 1 : m_spMG->num_levels();
     288            0 :                         for (size_t i = 1; i < nProp; ++i)
     289            0 :                                 propagate_to_level(i, m_bEnableVertComm);
     290            0 :                 }
     291              : 
     292            0 :                 void propagate_to_level(size_t lvl, bool vertComm = true)
     293              :                 {
     294              : #ifdef UG_PARALLEL
     295              :                         // copy from vMasters to vSlaves
     296              :                         if (pcl::NumProcs() > 1 && vertComm)
     297              :                         {
     298              :                                 typedef typename GridLayoutMap::Types<TElem>::Layout layout_type;
     299              :                                 DistributedGridManager& dgm = *m_spMG->distributed_grid_manager();
     300              :                                 GridLayoutMap& glm = dgm.grid_layout_map();
     301              :                                 pcl::InterfaceCommunicator<layout_type> icom;
     302              : 
     303              :                                 ComPol_CopyAttachment<layout_type, TAttachment> compolCopy(*m_spMG, m_a);
     304              :                                 icom.exchange_data(glm, INT_V_MASTER, INT_V_SLAVE, compolCopy);
     305              :                                 icom.communicate();
     306              :                         }
     307              : #endif
     308              :                         // iterate over all TElems of level
     309              :                         typedef typename geometry_traits<TElem>::const_iterator iter_type;
     310            0 :                         iter_type iter = m_spMG->begin<TElem>(lvl);
     311            0 :                         iter_type iter_end = m_spMG->end<TElem>(lvl);
     312            0 :                         for (; iter != iter_end; ++iter)
     313              :                         {
     314              :                                 TElem* child = *iter;
     315              :                                 GridObject* parent = m_spMG->get_parent(*iter);
     316              : 
     317            0 :                                 propagate<TElem, void>(child, parent, this);
     318              :                         }
     319            0 :                 }
     320              : 
     321            0 :                 virtual void copy(TElem* parent, TElem* child)
     322              :                 {
     323            0 :                         m_aa[child] = m_aa[parent];
     324            0 :                 }
     325              : 
     326            0 :                 virtual void copy_from_other_elem_type(GridObject* parent, TElem* child) {};
     327              : 
     328              :         protected:
     329              :                 /// multigrid
     330              :                 SmartPtr<MultiGrid> m_spMG;
     331              : 
     332              :                 bool m_bEnableVertComm;
     333              : 
     334              :                 /// attachment to be handled
     335              :                 TAttachment m_a;
     336              : 
     337              :                 /// accessor for handled attachment
     338              :                 Grid::AttachmentAccessor<TElem, TAttachment> m_aa;
     339              : 
     340              : };
     341              : 
     342              : } // end namespace ug
     343              : 
     344              : #endif // LIB_GRID__COPY_ATTACHMENT_HANDLER_H__
        

Generated by: LCOV version 2.0-1