LCOV - code coverage report
Current view: top level - ugbase/lib_disc/ordering_strategies/algorithms - lexorder.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 111 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 9 0

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2011-2022:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Andreas Vogel, Lukas Larisch
       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 <algorithm>
      34              : #include <vector>
      35              : #include <queue>
      36              : #include <utility>
      37              : 
      38              : #include "common/common.h"
      39              : #include "lib_disc/function_spaces/dof_position_util.h"
      40              : #include "lib_disc/reference_element/reference_element_util.h"
      41              : #include "lib_disc/local_finite_element/local_finite_element_provider.h"
      42              : #include "lib_disc/domain.h"
      43              : 
      44              : #include "lib_disc/ordering_strategies/algorithms/lexorder_comparators.cpp"
      45              : #include "lib_disc/ordering_strategies/algorithms/lexorder.h"
      46              : 
      47              : namespace ug{
      48              : 
      49              : template<int dim>
      50            0 : void ComputeLexicographicOrder(std::vector<size_t>& vNewIndex,
      51              :                                std::vector<std::pair<MathVector<dim>, size_t> >& vPos,
      52              :                                                            size_t orderDim, bool increasing)
      53              : {
      54              : //      a) order all indices
      55            0 :         if(vNewIndex.size() == vPos.size()){
      56              :         //  sort indices based on their position
      57            0 :                 if(increasing){
      58            0 :                         if (orderDim == 0)
      59            0 :                                 std::sort(vPos.begin(), vPos.end(), ComparePosDim<dim, 0>);
      60            0 :                         else if (orderDim == 1)
      61            0 :                                 std::sort(vPos.begin(), vPos.end(), ComparePosDim<dim, 1>);
      62            0 :                         else if (orderDim == 2)
      63            0 :                                 std::sort(vPos.begin(), vPos.end(), ComparePosDim<dim, 2>);
      64            0 :                         else UG_THROW("Invalid sorting direction.");
      65              :                 }
      66              :                 else{
      67            0 :                         if (orderDim == 0)
      68            0 :                                 std::sort(vPos.begin(), vPos.end(), ComparePosDimDec<dim, 0>);
      69            0 :                         else if (orderDim == 1)
      70            0 :                                 std::sort(vPos.begin(), vPos.end(), ComparePosDimDec<dim, 1>);
      71            0 :                         else if (orderDim == 2)
      72            0 :                                 std::sort(vPos.begin(), vPos.end(), ComparePosDimDec<dim, 2>);
      73            0 :                         else UG_THROW("Invalid sorting direction.");
      74              :                 }
      75              : 
      76              :         //      write mapping
      77            0 :                 for (size_t i=0; i < vPos.size(); ++i)
      78            0 :                         vNewIndex[vPos[i].second] = i;
      79              :         }
      80              : //      b) only some indices to order
      81              :         else{
      82              :         //      create copy of pos
      83            0 :                 std::vector<std::pair<MathVector<dim>, size_t> > vPosOrig(vPos);
      84              : 
      85              :         //  sort indices based on their position
      86            0 :                 if(increasing){
      87            0 :                         if (orderDim == 0){
      88            0 :                                 std::sort(vPos.begin(), vPos.end(), ComparePosDim<dim, 0>);
      89              :                         }
      90            0 :                         else if (orderDim == 1)
      91            0 :                                 std::sort(vPos.begin(), vPos.end(), ComparePosDim<dim, 1>);
      92            0 :                         else if (orderDim == 2)
      93            0 :                                 std::sort(vPos.begin(), vPos.end(), ComparePosDim<dim, 2>);
      94            0 :                         else UG_THROW("Invalid sorting direction.");
      95              :                 }
      96              :                 else{
      97            0 :                         if (orderDim == 0){
      98            0 :                                 std::sort(vPos.begin(), vPos.end(), ComparePosDimDec<dim, 0>);
      99              :                         }
     100            0 :                         else if (orderDim == 1)
     101            0 :                                 std::sort(vPos.begin(), vPos.end(), ComparePosDimDec<dim, 1>);
     102            0 :                         else if (orderDim == 2)
     103            0 :                                 std::sort(vPos.begin(), vPos.end(), ComparePosDimDec<dim, 2>);
     104            0 :                         else UG_THROW("Invalid sorting direction.");
     105              :                 }
     106              : 
     107              :         //      write mapping
     108            0 :                 for (size_t i=0; i < vNewIndex.size(); ++i)
     109            0 :                         vNewIndex[i] = i;
     110            0 :                 for (size_t i=0; i < vPos.size(); ++i)
     111            0 :                         vNewIndex[vPos[i].second] = vPosOrig[i].second;
     112            0 :         }
     113            0 : }
     114              : 
     115              : /// orders the dof distribution using Cuthill-McKee
     116              : template <typename TDomain>
     117            0 : void OrderLexForDofDist(SmartPtr<DoFDistribution> dd, ConstSmartPtr<TDomain> domain, size_t orderDim, bool increasing)
     118              : {
     119              : //      Lex Ordering is only possible in this cases:
     120              : //      b) Same number of DoFs on each geometric object (or no DoFs on object)
     121              : //              --> in this case we can order all dofs
     122              : //      a) different trial spaces, but DoFs for each trial spaces only on separate
     123              : //         geometric objects. (e.g. one space only vertices, one space only on edges)
     124              : //              --> in this case we can order all geometric objects separately
     125              : 
     126              : //      a) check for same number of DoFs on every geometric object
     127              :         bool bEqualNumDoFOnEachGeomObj = true;
     128              :         int numDoFOnGeomObj = -1;
     129            0 :         for(int si = 0; si < dd->num_subsets(); ++si){
     130            0 :                 for(int roid = 0; roid < NUM_REFERENCE_OBJECTS; ++roid){
     131            0 :                         const int numDoF = dd->num_dofs((ReferenceObjectID)roid, si);
     132              : 
     133            0 :                         if(numDoF == 0) continue;
     134              : 
     135            0 :                         if(numDoFOnGeomObj == -1){
     136              :                                 numDoFOnGeomObj = numDoF;
     137              :                         }
     138              :                         else{
     139            0 :                                 if(numDoFOnGeomObj != numDoF)
     140              :                                         bEqualNumDoFOnEachGeomObj = false;
     141              :                         }
     142              :                 }
     143              :         }
     144              : 
     145              : //      b) check for non-mixed spaces
     146            0 :         std::vector<bool> bSingleSpaceUsage(NUM_REFERENCE_OBJECTS, true);
     147            0 :         std::vector<bool> vHasDoFs(NUM_REFERENCE_OBJECTS, false);
     148            0 :         for(size_t fct = 0; fct < dd->num_fct(); ++fct){
     149              : 
     150            0 :                 LFEID lfeID = dd->local_finite_element_id(fct);
     151            0 :                 const CommonLocalDoFSet& locDoF = LocalFiniteElementProvider::get_dofs(lfeID);
     152              : 
     153            0 :                 for(int roid = 0; roid < NUM_REFERENCE_OBJECTS; ++roid){
     154              :                         const int numDoF = locDoF.num_dof((ReferenceObjectID)roid);
     155              : 
     156            0 :                         if(numDoF <= 0) continue;
     157              : 
     158            0 :                         if(vHasDoFs[roid] == false){
     159              :                                 vHasDoFs[roid] = true;
     160              :                         }
     161              :                         else{
     162              :                                 bSingleSpaceUsage[roid] = false;
     163              :                         }
     164              :                 }
     165              :         }
     166            0 :         std::vector<bool> bSortableComp(dd->num_fct(), true);
     167            0 :         for(size_t fct = 0; fct < dd->num_fct(); ++fct){
     168              : 
     169            0 :                 LFEID lfeID = dd->local_finite_element_id(fct);
     170            0 :                 const CommonLocalDoFSet& locDoF = LocalFiniteElementProvider::get_dofs(lfeID);
     171              : 
     172            0 :                 for(int roid = 0; roid < NUM_REFERENCE_OBJECTS; ++roid){
     173            0 :                         if(locDoF.num_dof((ReferenceObjectID)roid) != 0){
     174            0 :                                 if(bSingleSpaceUsage[roid] == false)
     175              :                                         bSortableComp[fct] = false;
     176              :                         }
     177              :                 }
     178              :         }
     179              : 
     180              : //      get position attachment
     181              :         typedef typename std::pair<MathVector<TDomain::dim>, size_t> pos_type;
     182              : 
     183              : //      get positions of indices
     184              :         std::vector<pos_type> vPositions;
     185              : 
     186              : //      a) we can order globally
     187            0 :         if(bEqualNumDoFOnEachGeomObj)
     188              :         {
     189            0 :                 ExtractPositions(domain, dd, vPositions);
     190              : 
     191              :         //      get mapping: old -> new index
     192            0 :                 std::vector<size_t> vNewIndex(dd->num_indices());
     193            0 :                 ComputeLexicographicOrder<TDomain::dim>(vNewIndex, vPositions, orderDim, increasing);
     194              : 
     195              : /*
     196              :                 std::vector<bool> vCheck(dd->num_indices(), false);
     197              :                 for (size_t i = 0; i < vNewIndex.size(); ++i)
     198              :                 {
     199              :                         UG_COND_THROW(vCheck.at(vNewIndex[i]), "Double mapping to index " << vNewIndex[i] << ".");
     200              :                         vCheck.at(vNewIndex[i]) = true;
     201              :                 }
     202              :                 for (size_t i = 0; i < vCheck.size(); ++i)
     203              :                         UG_COND_THROW(!vCheck[i], "Nothing maps to index " << i << ".");
     204              : */
     205              : 
     206              :         //      reorder indices
     207            0 :                 dd->permute_indices(vNewIndex);
     208            0 :         }
     209              : //      b) we can only order some spaces
     210              :         else
     211              :         {
     212              :                 UG_LOG("OrderLex: Cannot order globally, trying to order some components:\n");
     213            0 :                 for(size_t fct = 0; fct < dd->num_fct(); ++fct){
     214            0 :                         if(bSortableComp[fct] == false){
     215            0 :                                 UG_LOG("OrderLex: '"<<dd->name(fct)<<" NOT SORTED.\n");
     216            0 :                                 continue;
     217              :                         }
     218              : 
     219            0 :                         ExtractPositions(domain, dd, fct, vPositions);
     220              : 
     221              :                 //      get mapping: old -> new index
     222            0 :                         std::vector<size_t> vNewIndex(dd->num_indices());
     223            0 :                         ComputeLexicographicOrder<TDomain::dim>(vNewIndex, vPositions, orderDim, increasing);
     224              : 
     225              :                 //      reorder indices
     226            0 :                         dd->permute_indices(vNewIndex);
     227              : 
     228            0 :                         UG_LOG("OrderLex: '"<<dd->name(fct)<<" SORTED.\n");
     229              :                 }
     230              :         }
     231            0 : }
     232              : 
     233              : 
     234              : /// orders the all DofDistributions of the ApproximationSpace using lexicographic order
     235              : template <typename TDomain>
     236            0 : void OrderLex(ApproximationSpace<TDomain>& approxSpace, const char *order)
     237              : {
     238            0 :         std::vector<SmartPtr<DoFDistribution> > vDD = approxSpace.dof_distributions();
     239              : 
     240            0 :         size_t len = strlen(order);
     241              : 
     242            0 :         if(len == 0){
     243            0 :                 UG_THROW("OrderLex: Empty direction!");
     244              :         }
     245              : 
     246              :         size_t pos = 0;
     247              :         bool increasing = true;
     248              :         char sign;
     249            0 :         while(pos < len){
     250            0 :                 if(increasing){
     251              :                         sign = '+';
     252              :                 }
     253              :                 else{
     254              :                         sign = '-';
     255              :                 }
     256              : 
     257            0 :                 switch(order[pos]){
     258            0 :                         case '+':
     259            0 :                                 ++pos;
     260              :                                 increasing = true;
     261            0 :                                 break;
     262            0 :                         case '-':
     263            0 :                                 ++pos;
     264              :                                 increasing = false;
     265            0 :                                 break;
     266              :                         case 'x':
     267            0 :                                 UG_LOG("OrderLex: LexOrdering in " << sign << "x direction.\n")
     268            0 :                                 for (size_t i = 0; i < vDD.size(); ++i)
     269            0 :                                         OrderLexForDofDist<TDomain>(vDD[i], approxSpace.domain(), 0, increasing);
     270            0 :                                 ++pos;
     271              :                                 increasing = true;
     272            0 :                                 break;
     273              :                         case 'y':
     274            0 :                                 UG_LOG("OrderLex: LexOrdering in " << sign << "y direction.\n")
     275            0 :                                 for (size_t i = 0; i < vDD.size(); ++i)
     276            0 :                                         OrderLexForDofDist<TDomain>(vDD[i], approxSpace.domain(), 1, increasing);
     277            0 :                                 ++pos;
     278              :                                 increasing = true;
     279            0 :                                 break;
     280              :                         case 'z':
     281            0 :                                 UG_LOG("OrderLex: LexOrdering in " << sign << "z direction.\n")
     282            0 :                                 for (size_t i = 0; i < vDD.size(); ++i)
     283            0 :                                         OrderLexForDofDist<TDomain>(vDD[i], approxSpace.domain(), 2, increasing);
     284            0 :                                 ++pos;
     285              :                                 increasing = true;
     286            0 :                                 break;
     287            0 :                         default:
     288            0 :                                 UG_THROW("OrderLex: Invalid token in direction string, valid tokens: +, -, x, y, z");
     289              :                 }
     290              :         }
     291            0 : }
     292              : 
     293              : #ifdef UG_DIM_1
     294              : template void ComputeLexicographicOrder<1>(std::vector<size_t>& vNewIndex, std::vector<std::pair<MathVector<1>, size_t> >& vPos, size_t, bool);
     295              : template void OrderLexForDofDist<Domain1d>(SmartPtr<DoFDistribution> dd, ConstSmartPtr<Domain1d> domain, size_t, bool);
     296              : template void OrderLex<Domain1d>(ApproximationSpace<Domain1d>& approxSpace, const char *order);
     297              : #endif
     298              : #ifdef UG_DIM_2
     299              : template void ComputeLexicographicOrder<2>(std::vector<size_t>& vNewIndex, std::vector<std::pair<MathVector<2>, size_t> >& vPos, size_t, bool);
     300              : template void OrderLexForDofDist<Domain2d>(SmartPtr<DoFDistribution> dd, ConstSmartPtr<Domain2d> domain, size_t, bool);
     301              : template void OrderLex<Domain2d>(ApproximationSpace<Domain2d>& approxSpace, const char *order);
     302              : #endif
     303              : #ifdef UG_DIM_3
     304              : template void ComputeLexicographicOrder<3>(std::vector<size_t>& vNewIndex, std::vector<std::pair<MathVector<3>, size_t> >& vPos, size_t, bool);
     305              : template void OrderLexForDofDist<Domain3d>(SmartPtr<DoFDistribution> dd, ConstSmartPtr<Domain3d> domain, size_t, bool);
     306              : template void OrderLex<Domain3d>(ApproximationSpace<Domain3d>& approxSpace, const char *order);
     307              : #endif
     308              : 
     309              : }
        

Generated by: LCOV version 2.0-1