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

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Dmitry Logashenko
       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              : /*
      34              :  * Implementation of the degenerated layer subset manager.
      35              :  */
      36              : // ug4 headers
      37              : #include "common/util/string_util.h"
      38              : 
      39              : namespace ug {
      40              : 
      41              : /**
      42              :  * Class constructor: Parses the subset names, attaches itself to the grid
      43              :  * to be updated if the grid is refined, and writes itself to the properties
      44              :  * of the subsets.
      45              :  */
      46              : template <int dim>
      47            0 : DegeneratedLayerManager<dim>::DegeneratedLayerManager
      48              : (
      49              :         SmartPtr<MultiGridSubsetHandler> spSH ///< [in] subset handler of the grid
      50              : )
      51            0 : :       m_spSH (spSH), m_bClosed (false)
      52              : {
      53              : // Check the subset handler:
      54            0 :         if (m_spSH.invalid ())
      55            0 :                 UG_THROW ("DegeneratedLayerManager: Invalid subset handler specified!");
      56              :         
      57              : //      Initialize the data:
      58            0 :         m_layerSsGrp.set_subset_handler (m_spSH);
      59              :         
      60              : //      Initialize the attachment:
      61              :         MultiGrid * pMG = (MultiGrid *) (m_spSH->multi_grid ());
      62            0 :         pMG->template attach_to_dv<Vertex> (m_aVertexMarks, D_LAYER_UNKNOWN);
      63              :         m_aaVertMarks.access (*pMG, m_aVertexMarks);
      64              :         
      65              : //      Register the callbacks in the message hub:
      66            0 :         m_spGridAdaptionCallbackID =
      67              :                 pMG->message_hub()->register_class_callback
      68              :                         (this, & DegeneratedLayerManager<dim>::grid_adaption_callback);
      69            0 :         m_spGridDistributionCallbackID =
      70              :                 pMG->message_hub()->register_class_callback
      71              :                         (this, & DegeneratedLayerManager<dim>::grid_distribution_callback);
      72            0 : }
      73              : 
      74              : /**
      75              :  * Class destructor: Detaches the attachment.
      76              :  */
      77              : template <int dim>
      78            0 : DegeneratedLayerManager<dim>::~DegeneratedLayerManager ()
      79              : {
      80              :         MultiGrid * pMG = (MultiGrid *) (m_spSH->multi_grid ());
      81              :         m_aaVertMarks.invalidate ();
      82            0 :         pMG->template detach_from<Vertex> (m_aVertexMarks);
      83            0 :         m_bClosed = false; // (to be on the very safe side...)
      84            0 : }
      85              : 
      86              : /**
      87              :  * Adds subsets to the manager
      88              :  */
      89              : template <int dim>
      90            0 : void DegeneratedLayerManager<dim>::add
      91              : (
      92              :         const char * ss_names ///< [in] subset names of the degenerated layers
      93              : )
      94              : {
      95            0 :         if (m_bClosed)
      96              :                 UG_LOG ("DegeneratedLayerManager: Adding subsets to a closed manager.");
      97              :         
      98              : //      If extended - then not closed any more
      99            0 :         m_bClosed = false;
     100              :         
     101              : //      Parse the subset names:
     102              :         std::vector<std::string> vssNames;
     103            0 :         TokenizeString (ss_names, vssNames);
     104              :         
     105              : //      Add the subsets to the group:
     106            0 :         m_layerSsGrp.add (vssNames);
     107            0 : }
     108              : 
     109              : /**
     110              :  * Removes subsets from the manager
     111              :  */
     112              : template <int dim>
     113            0 : void DegeneratedLayerManager<dim>::remove
     114              : (
     115              :         const char * ss_names ///< [in] subset names of the fractures
     116              : )
     117              : {
     118              : //      If extended - then not closed any more
     119            0 :         m_bClosed = false;
     120              : 
     121              : //      Parse the subset names:
     122              :         std::vector<std::string> vssNames;
     123            0 :         TokenizeString (ss_names, vssNames);
     124              : 
     125              : //      Add the subsets to the group:
     126            0 :         m_layerSsGrp.remove (vssNames);
     127            0 : }
     128              : 
     129              : /**
     130              :  * Closes the manager: Computes the vertex marks
     131              :  */
     132              : template <int dim>
     133            0 : void DegeneratedLayerManager<dim>::close ()
     134              : {
     135              :         size_t init_n_subsets = m_layerSsGrp.size ();
     136              :         
     137              : //      Check the dimensionality of the subsets:
     138              :         size_t i = 0;
     139            0 :         while (i < m_layerSsGrp.size ())
     140            0 :         if (DimensionOfSubset (*m_spSH, m_layerSsGrp [i]) != dim)
     141              :         {
     142            0 :                 UG_LOG ("DegeneratedLayerManager: Low-dimensional subset '"
     143              :                         << m_spSH->get_subset_name (m_layerSsGrp [i])
     144              :                                 << "' specified as a degenerated layer. Removed from the list.\n");
     145            0 :                 m_layerSsGrp.remove (m_layerSsGrp [i]);
     146              :                 i = 0;
     147              :         }
     148            0 :         else i++;
     149              :         
     150              : //      Check if all the subsets are removed due to the illegal dimensionality
     151            0 :         if (init_n_subsets != 0 && m_layerSsGrp.size () == 0)
     152            0 :                 UG_THROW ("DegeneratedLayerManager: All the specified subsets have illegal dimensionality!\n");
     153              :         
     154              : //      Mark the vertices:
     155            0 :         mark_vertices ();
     156              :         
     157              : //      Done:
     158            0 :         m_bClosed = true;
     159            0 : }
     160              : 
     161              : /**
     162              :  * Adds the registered subsets to the refiner
     163              :  */
     164              : template <int dim>
     165            0 : void DegeneratedLayerManager<dim>::init_refiner
     166              : (
     167              :         SmartPtr<GlobalFracturedMediaRefiner> refiner,
     168              :         bool as_low_dim
     169              : )
     170              : {
     171            0 :         if (! is_closed ())
     172            0 :                 UG_THROW ("DegeneratedLayerManager: The manager must be closed before use.");
     173            0 :         for (size_t i = 0; i <  m_layerSsGrp.size (); i++)
     174            0 :                 refiner->mark_as_fracture (m_layerSsGrp[i], as_low_dim);
     175            0 : }
     176              : 
     177              : /**
     178              :  * Marks the vertices in such a way that the inner layer vertices are
     179              :  * marked with D_LAYER_INNER, whereas all other vertices (at the fractures
     180              :  * and in the bulk medium) are marked with D_LAYER_OUTER. After the call,
     181              :  * there should be no vertices marked with D_LAYER_UNKNOWN.
     182              :  */
     183              : template <int dim>
     184            0 : void DegeneratedLayerManager<dim>::mark_vertices ()
     185              : {
     186              :         typedef typename geometry_traits<element_type>::const_iterator t_elem_iter;
     187              :         
     188              :         MultiGrid * pMG = (MultiGrid *) (m_spSH->multi_grid ());
     189              :         
     190              : //      Mark all vertices of the fracture elements:
     191            0 :         for (size_t i = 0; i < m_layerSsGrp.size (); i++)
     192              :         {
     193              :                 int si = m_layerSsGrp [i];
     194            0 :                 for (size_t lev = 0; lev < pMG->num_levels (); lev++)
     195              :                 {
     196            0 :                         t_elem_iter list_end = m_spSH->template end<element_type> (si, lev);
     197            0 :                         for (t_elem_iter iElem = m_spSH->template begin<element_type> (si, lev);
     198            0 :                                         iElem != list_end; ++iElem)
     199              :                         {
     200              :                                 element_type * elem = *iElem;
     201            0 :                                 for (size_t i = 0; i < elem->num_vertices (); i++)
     202              :                                 {
     203            0 :                                         Vertex * vert = elem->vertex(i);
     204            0 :                                         m_aaVertMarks [vert] = (! vert->is_constrained ())? D_LAYER_INNER : D_LAYER_OUTER;
     205              :                                         // REMARK: Constrained vertices cannot be inner for degenerated layers!
     206              :                                         // We cannot catch this situation somewhere else, so we do it here.
     207              :                                 }
     208              :                         }
     209              :                 }
     210              :         }
     211              :         
     212              : //      Unmark all vertices in the other (not-degenerated-layer) elements:
     213            0 :         for (int si = 0; si < m_spSH->num_subsets (); si++)
     214            0 :         if (DimensionOfSubset (*m_spSH, si) == dim && ! m_layerSsGrp.contains (si))
     215            0 :                 for (size_t lev = 0; lev < pMG->num_levels (); lev++)
     216              :                 {
     217            0 :                         t_elem_iter list_end = m_spSH->template end<element_type> (si, lev);
     218            0 :                         for (t_elem_iter iElem = m_spSH->template begin<element_type> (si, lev);
     219            0 :                                 iElem != list_end; ++iElem)
     220              :                         {
     221              :                                 element_type * elem = *iElem;
     222            0 :                                 for (size_t i = 0; i < elem->num_vertices (); i++)
     223            0 :                                         m_aaVertMarks [elem->vertex(i)] = D_LAYER_OUTER;
     224              :                         }
     225              :                 }
     226              :         
     227              : #ifdef UG_PARALLEL
     228              : //      Make the marking consistent
     229              :         AttachmentAllReduce<Vertex> (*pMG, m_aVertexMarks, PCL_RO_MIN);
     230              : #endif // UG_PARALLEL
     231            0 : }
     232              : 
     233              : /**
     234              :  * The grid adaption callback: Catches the messages about grid refinements, ...
     235              :  */
     236              : template <int dim>
     237            0 : void DegeneratedLayerManager<dim>::grid_adaption_callback
     238              : (
     239              :         const GridMessage_Adaption & msg ///< the message from the message hub
     240              : )
     241              : {
     242            0 :         if (m_bClosed && msg.adaption_ends ())
     243            0 :                 mark_vertices ();
     244            0 : }
     245              : 
     246              : /**
     247              :  * The grid adaption callback: Catches the messages about the distribution of the grid
     248              :  */
     249              : template <int dim>
     250            0 : void DegeneratedLayerManager<dim>::grid_distribution_callback
     251              : (
     252              :         const GridMessage_Distribution & msg ///< the message from the message hub
     253              : )
     254              : {
     255            0 :         if (m_bClosed && msg.msg () == GMDT_DISTRIBUTION_STOPS)
     256            0 :                 mark_vertices ();
     257            0 : }
     258              : 
     259              : /**
     260              :  * For a given element, finds its inner and outer layer sides. For these
     261              :  * sides, gets the correspondence of the vertices in the degenerated element
     262              :  * (i.e. considering all other sides as degenerated).
     263              :  */
     264              : template <int dim>
     265            0 : void DegeneratedLayerManager<dim>::get_layer_sides
     266              : (
     267              :         element_type * elem, ///< [in] the element
     268              :         size_t & num_side_co, ///< [out] number of corners of the inner/outer sides
     269              :         side_type * & inner_side, ///< [out] its fracture inner side
     270              :         size_t & inner_side_idx, ///< [out] index of the inner side in the reference element
     271              :         size_t inner_side_corners [], ///< [out] inner side corner idx -> elem. corner idx (maxLayerSideCorners elements)
     272              :         side_type * & outer_side, ///< [out] its fracture outer side
     273              :         size_t & outer_side_idx, ///< [out] index of the outer side in the reference element
     274              :         size_t outer_side_corners [], ///< [out] outer side corner idx -> elem. corner idx (maxLayerSideCorners elements)
     275              :         size_t ass_co [] ///< [out] correspondence of the corners of the sides (2 * maxLayerSideCorners elements or NULL)
     276              : )
     277              : {
     278              :         size_t n_inner, n_outer;
     279            0 :         size_t n_co = elem->num_vertices ();
     280              :         MultiGrid * pMG = (MultiGrid *) (m_spSH->multi_grid ());
     281              :         typename Grid::traits<Edge>::secure_container edge_list;
     282              :         
     283              : //      First, we check, whether the inner and outer sides are well defined.
     284              : //      Loop over the sides: We look for sides with only inner or only outer corners
     285            0 :         inner_side = NULL; n_inner = 0;
     286            0 :         outer_side = NULL; n_outer = 0;
     287            0 :         for (size_t i = 0; i < elem->num_sides (); i++)
     288              :         {
     289            0 :                 side_type * side = pMG->get_side (elem, i);
     290              :                 bool has_inner = false, has_outer = false;
     291            0 :                 size_t side_n_co = side->num_vertices ();
     292            0 :                 for (size_t co = 0; co < side_n_co; co++)
     293              :                 {
     294            0 :                         int mark = vert_mark (side->vertex (co));
     295            0 :                         if (mark == D_LAYER_OUTER)
     296              :                                 has_outer = true;
     297            0 :                         else if (mark == D_LAYER_INNER)
     298              :                                 has_inner = true;
     299              :                         else
     300            0 :                                 UG_THROW ("DegeneratedLayerManager: Some vertices are not marked!");
     301              :                 }
     302              :                 
     303            0 :                 if (has_inner && has_outer) continue; // this is a 'degenerated' side
     304              :                 
     305            0 :                 if (has_inner)
     306              :                 {       // this is the inner side
     307            0 :                         if (inner_side != NULL)
     308            0 :                                 UG_THROW ("DegeneratedLayerManager: Two inner sides of a degenerated layer element found!");
     309            0 :                         inner_side = side;
     310            0 :                         inner_side_idx = i;
     311              :                         n_inner = side_n_co;
     312              :                 }
     313              :                 else
     314              :                 {       // this is the outer side
     315            0 :                         if (outer_side != NULL)
     316            0 :                                 UG_THROW ("DegeneratedLayerManager: Two outer sides of a degenerated layer element found!");
     317            0 :                         outer_side = side;
     318            0 :                         outer_side_idx = i;
     319              :                         n_outer = side_n_co;
     320              :                 }
     321              :         }
     322            0 :         if (n_inner != n_outer || 2 * n_inner != n_co)
     323            0 :                 UG_THROW ("DegeneratedLayerManager: Unrecognized degenerated layer element!");
     324            0 :         num_side_co = n_inner;
     325              :         
     326              : //      Now: Corner of inner side are exactly those marked as inner, and the same for the outer side
     327              :         Vertex * inner_vert_ptr [maxLayerSideCorners], * outer_vert_ptr [maxLayerSideCorners];
     328              :         size_t inner_corners [maxLayerSideCorners], outer_corners [maxLayerSideCorners];
     329              :         size_t inner_i = 0, outer_i = 0;
     330            0 :         for (size_t co = 0; co < n_co; co++)
     331              :         {
     332            0 :                 Vertex * vrt = elem->vertex (co);
     333            0 :                 if (vert_mark (vrt) == D_LAYER_INNER)
     334              :                 {
     335            0 :                         inner_vert_ptr [inner_i] = vrt;
     336            0 :                         inner_corners [inner_i] = co;
     337            0 :                         inner_i++;
     338              :                 }
     339              :                 else
     340              :                 {
     341            0 :                         outer_vert_ptr [outer_i] = vrt;
     342            0 :                         outer_corners [outer_i] = co;
     343            0 :                         outer_i++;
     344              :                 }
     345              :         }
     346            0 :         if (inner_i != n_inner || outer_i != n_outer)
     347            0 :                 UG_THROW ("DegeneratedLayerManager: Failed to get the vertex-side correspondence!");
     348              :         
     349              : //      Order the corner indices according to the corners of the sides
     350            0 :         for (size_t i = 0; i < n_inner; i++)
     351              :         {
     352              :                 size_t co;
     353              :                 
     354              :                 co = 0;
     355            0 :                 while (inner_side->vertex (co) != inner_vert_ptr [i])
     356            0 :                         if (++co == n_inner)
     357            0 :                                 UG_THROW ("DegeneratedLayerManager: Failed! Missing inner vertex?");
     358            0 :                 inner_side_corners [co] = inner_corners [i];
     359              :                 
     360              :                 co = 0;
     361            0 :                 while (outer_side->vertex (co) != outer_vert_ptr [i])
     362            0 :                         if (++co == n_outer)
     363            0 :                                 UG_THROW ("DegeneratedLayerManager: Failed! Missing outer vertex?");
     364            0 :                 outer_side_corners [co] = outer_corners [i];
     365              :         }
     366              :         
     367              : //      Loop over the edges: Find out the associated corners
     368            0 :         if (ass_co != NULL)
     369              :         {
     370            0 :                 pMG->associated_elements (edge_list, elem);
     371            0 :                 for (size_t i = 0; i < edge_list.size (); i++)
     372              :                 {
     373              :                         Edge * e = edge_list [i];
     374            0 :                         Vertex * v_1 = e->vertex (0); int mark_1 = vert_mark (v_1);
     375            0 :                         Vertex * v_2 = e->vertex (1); int mark_2 = vert_mark (v_2);
     376              :                         Vertex * t;
     377              :                         size_t co_1, co_2;
     378              :                         
     379            0 :                         if (mark_1 == mark_2)
     380            0 :                                 continue; // an edge of the inner or the outer size
     381              :                         
     382            0 :                         if (mark_1 == D_LAYER_OUTER)
     383              :                         {       // Vertex # 1 must be inner, vertex # 2 must be outer
     384              :                                 t = v_1; v_1 = v_2; v_2 = t;
     385              :                         }
     386              :                 
     387              :                         co_1 = 0;
     388            0 :                         while (inner_vert_ptr[co_1] != v_1)
     389            0 :                                 if (++co_1 == n_inner)
     390            0 :                                         UG_THROW ("DegeneratedLayerManager: Cannot find an inner node by vertex!");
     391              :                         
     392              :                         co_2 = 0;
     393            0 :                         while (outer_vert_ptr[co_2] != v_2)
     394            0 :                                 if (++co_2 == n_outer)
     395            0 :                                         UG_THROW ("DegeneratedLayerManager: Cannot find an outer node by vertex!");
     396              :                         
     397            0 :                         ass_co [inner_corners [co_1]] = outer_corners [co_2];
     398            0 :                         ass_co [outer_corners [co_2]] = inner_corners [co_1];
     399              :                 }
     400              :         }
     401            0 : }
     402              : 
     403              : /**
     404              :  * Assigns a different subset index to the inner sides of a layer. (Only to
     405              :  * the sides, not vertices, or edges in 3d!) If -1 passed instead of the index
     406              :  * of the subset to assign, new subset is created. The function returns the
     407              :  * index of the assigned subset.
     408              :  */
     409              : template <int dim>
     410            0 : int DegeneratedLayerManager<dim>::assign_middle_subset
     411              : (
     412              :         int layer_si, ///< subset index of the layer
     413              :         int middle_si ///< the subset index to assign (or -1 to create a new subset)
     414              : )
     415              : {
     416              :         typedef typename geometry_traits<element_type>::const_iterator t_elem_iter;
     417              :         
     418              :         MultiGrid * pMG = (MultiGrid *) (m_spSH->multi_grid ());
     419              :         
     420              : //      Assign the default value of the subset (if necessary)
     421            0 :         if (middle_si < 0) middle_si = m_spSH->num_subsets ();
     422              :         
     423              : //      Loop the elements of the layer in all the grid levels
     424            0 :         pMG->message_hub()->post_message (GridMessage_Creation (GMCT_CREATION_STARTS, 0));
     425            0 :         for (size_t lev = 0; lev < pMG->num_levels (); lev++)
     426              :         {
     427            0 :                 t_elem_iter list_end = m_spSH->template end<element_type> (layer_si, lev);
     428            0 :                 for (t_elem_iter iElem = m_spSH->template begin<element_type> (layer_si, lev);
     429            0 :                                 iElem != list_end; ++iElem)
     430              :                 {
     431              :                         element_type * elem = *iElem;
     432              :                         size_t num_side_co;
     433              :                         side_type * inner_side, * outer_side;
     434              :                         size_t inner_side_idx, outer_side_idx;
     435              :                         size_t inner_side_corners [maxLayerSideCorners], outer_side_corners [maxLayerSideCorners];
     436              :                         
     437              :                 //      get the inner side
     438            0 :                         get_layer_sides (elem, num_side_co,
     439              :                                 inner_side, inner_side_idx, inner_side_corners,
     440              :                                 outer_side, outer_side_idx, outer_side_corners);
     441              :                         
     442              :                 //      assign the subset
     443            0 :                         m_spSH->assign_subset (inner_side, middle_si);
     444              :                 }
     445              :         }
     446            0 :         pMG->message_hub()->post_message (GridMessage_Creation (GMCT_CREATION_STOPS, 0));
     447              :         
     448            0 :         return middle_si;
     449              : }
     450              : 
     451              : /**
     452              :  * Assigns a different subset to the inner sides of a layer. (Only to
     453              :  * the sides, not vertices, or edges in 3d!) If the given subset does not exist,
     454              :  * it is created. The function returns the index of the assigned subset.
     455              :  */
     456              : template <int dim>
     457            0 : int DegeneratedLayerManager<dim>::assign_middle_subset
     458              : (
     459              :         int layer_si, ///< subset index of the layer
     460              :         const char* middle_ss_name ///< name of the subset to assign
     461              : )
     462              : {
     463              : //      Look for the subset to assign
     464              :         int middle_si = -1;
     465              :         bool new_ss = true;
     466            0 :         for (int si = 0; si < m_spSH->num_subsets (); si++)
     467            0 :         if (strcmp (middle_ss_name, m_spSH->get_subset_name (si)) == 0)
     468              :         {
     469              :                 middle_si = si;
     470              :                 new_ss = false;
     471              :                 break;
     472              :         }
     473              :         
     474              : //      Assign the subset
     475            0 :         middle_si = assign_middle_subset (layer_si, middle_si);
     476              :         
     477              : //      Set the name
     478            0 :         if (new_ss)
     479            0 :                 m_spSH->set_subset_name (middle_ss_name, middle_si);
     480              :         
     481            0 :         return middle_si;
     482              : }
     483              : 
     484              : /**
     485              :  * Assigns a different subset to the inner sides of a layer. (Only to
     486              :  * the sides, not vertices, or edges in 3d!) If the given subset does not exist,
     487              :  * it is created. The function returns the index of the assigned subset.
     488              :  */
     489              : template <int dim>
     490            0 : int DegeneratedLayerManager<dim>::assign_middle_subset
     491              : (
     492              :         const char* layer_ss_name, ///< subset name of the layer
     493              :         const char* middle_ss_name ///< name of the subset to assign
     494              : )
     495              : {
     496              : //      Look for the subset of the layer
     497            0 :         for (int si = 0; si < m_spSH->num_subsets (); si++)
     498            0 :         if (strcmp (layer_ss_name, m_spSH->get_subset_name (si)) == 0)
     499            0 :                 return assign_middle_subset (si, middle_ss_name);
     500            0 :         UG_THROW ("DegeneratedLayerManager: Subset '" << layer_ss_name << "' not found");
     501              : }
     502              : 
     503              : } // end namespace ug
     504              : 
     505              : /* End of File */
        

Generated by: LCOV version 2.0-1