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

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2011-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Jan Friebertshäuser
       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              : #include "lib_disc/ordering_strategies/algorithms/downwindorder.h"
      35              : #include "common/common.h"
      36              : #include <iostream>
      37              : 
      38              : #include <utility> // for pair
      39              : #include <map> // for graph structure
      40              : #include "lib_disc/domain.h"
      41              : #include "lib_disc/function_spaces/dof_position_util.h"
      42              : 
      43              : namespace ug{
      44              : /**
      45              :  * For Debugging:
      46              :  */
      47              : DebugID LIB_DISC_ORDER("LIB_DISC_ORDER");
      48              : 
      49              : // Numbers vertices based on a adjacency matrix.
      50            0 : void NumeriereKnoten(const std::vector<std::vector<size_t> > &vvConnections,
      51              :                 std::vector<bool> &vVisited, std::vector<size_t> & vAncestorsCount, std::vector<size_t> & vNewIndex, size_t & N, size_t v)
      52              : {
      53              :         vVisited[v] = true;
      54            0 :         vNewIndex[v] = N;
      55            0 :         N++;
      56            0 :         const std::vector<size_t> connections = vvConnections[v];
      57              :         std::vector<size_t>::const_iterator AdjacencIter;
      58            0 :         for (AdjacencIter = connections.begin(); AdjacencIter != connections.end(); ++AdjacencIter)
      59              :         {
      60            0 :                 vAncestorsCount[*AdjacencIter]--;
      61            0 :                 if (vAncestorsCount[*AdjacencIter] == 0)
      62            0 :                         NumeriereKnoten(vvConnections, vVisited, vAncestorsCount, vNewIndex, N, *AdjacencIter);
      63              :         }
      64            0 : }
      65              : 
      66              : // Calculates Downwind-Numbering for one DofDistribution only.
      67              : template <typename TDomain>
      68            0 : void OrderDownwindForDofDist(SmartPtr<DoFDistribution> dd, ConstSmartPtr<TDomain> domain,
      69              :                 SmartPtr<UserData<MathVector<TDomain::dim>, TDomain::dim> > spVelocity,
      70              :                 number time, int si, number threshold)
      71              : {
      72              :         static const int dim = TDomain::dim;
      73              :         const size_t num_ind = dd->num_indices();
      74              :         typedef typename std::pair<MathVector<dim>, size_t> pos_type;
      75              :         typedef typename std::vector<std::vector<size_t> > adjacency_type;
      76              : 
      77              :         //      get positions of indices
      78              :         typename std::vector<pos_type> vPositions;
      79            0 :         ExtractPositions(domain, dd, vPositions);
      80              : 
      81              :         // get adjacency vector of vectors
      82              :         adjacency_type vvConnections;
      83            0 :         dd->get_connections(vvConnections);
      84              : 
      85              :         // Check vector sizes match
      86            0 :         if (vvConnections.size() != num_ind)
      87            0 :                 UG_THROW("OrderDownstreamForDofDist: "
      88              :                                 "Adjacency list of dimension " << num_ind << " expected, got "<< vvConnections.size());
      89              : 
      90            0 :         if (vPositions.size() != num_ind)
      91            0 :                 UG_THROW("OrderDownstreamForDofDist: "
      92              :                                 "Position list of dimension " << num_ind << " expected, got "<< vPositions.size());
      93              : 
      94              :         // init helper structures
      95            0 :         std::vector<size_t> vNewIndex(num_ind, 0);
      96            0 :         std::vector<size_t> vAncestorsCount(num_ind, 0);
      97            0 :         std::vector<bool> vVisited(num_ind, false);
      98              : 
      99              :         // remove connections that are not in stream direction
     100              :         adjacency_type::iterator VertexIter;
     101              :         std::vector<size_t>::iterator AdjIter;
     102              :         std::vector<size_t> vAdjacency;
     103              : 
     104              :         MathVector<TDomain::dim> vVel1, vPos1, vPos2, vDir1_2;
     105              :         size_t i;
     106            0 :         for (VertexIter = vvConnections.begin(), i=0; VertexIter != vvConnections.end(); VertexIter++, i++)
     107              :         {
     108              :                 UG_DLOG(LIB_DISC_ORDER, 2, "Filtering vertex " << i << " adjacency vector." <<std::endl);
     109              :                 // count how many vertex were kept / removed per adjacency vector
     110              :                 #ifdef UG_ENABLE_DEBUG_LOGS
     111              :                 size_t initialcount = VertexIter->size();
     112              :                 #endif
     113              :                 size_t kept = 0, removed = 0;
     114              :                 // get position and velocity of first trait
     115              :                 vPos1 = vPositions.at(i).first;
     116            0 :                 (*spVelocity)(vVel1, vPos1, time, si);
     117            0 :                 if (VecLengthSq(vVel1) == 0 )
     118              :                 {
     119              :                         // if the velocity is zero at this trait it does not interfere with others
     120              :                         // NOTE: otherwise this trait would be downwind-connected to all of it's neighbors
     121              :                         // NOTE: VertexIter-> will access inner vector functions (*VertexIter) is the inner vector.
     122              :                         removed = VertexIter->size();
     123              :                         VertexIter->clear();
     124              :                 }
     125              :                 else {
     126              :                         AdjIter = VertexIter->begin();
     127            0 :                         while (AdjIter != VertexIter->end())
     128              :                         {
     129              :                                 // get position of second trait
     130            0 :                                 vPos2 = vPositions.at(*AdjIter).first;
     131              : 
     132              :                                 // get difference vector as direction vector
     133              :                                 VecSubtract(vDir1_2, vPos2, vPos1);
     134              : 
     135              :                                 // compute angle between velocity and direction vector
     136            0 :                                 number anglex1_2 = VecAngle(vDir1_2, vVel1);
     137              : 
     138              :                                 // if angle is smaller then threshold continue else remove connection
     139            0 :                                 if (anglex1_2 <= threshold && i != *AdjIter)
     140              :                                 {
     141            0 :                                         vAncestorsCount.at(*AdjIter) += 1;
     142              :                                         ++AdjIter;
     143              :                                         kept++;
     144              :                                 } else {
     145              :                                         AdjIter = VertexIter->erase(AdjIter);
     146              :                                         removed++;
     147              :                                 }
     148              :                         }
     149              :                 }
     150              :                 UG_DLOG(LIB_DISC_ORDER, 2, "Kept: " << kept << ", removed: " << removed << " of " << initialcount
     151              :                                 << " entries in adjacency matrix." << std::endl << std::endl);
     152              :         }
     153              :         // calculate downwindorder
     154              :         // Find vertexes without any ancestors and start NumeriereKnoten on them.
     155              :         size_t v,N;
     156            0 :         for (v=0, N=0; v < vvConnections.size(); v++)
     157              :         {
     158            0 :                 if (vAncestorsCount[v] == 0 && !vVisited[v])
     159              :                 {
     160            0 :                         NumeriereKnoten(vvConnections, vVisited, vAncestorsCount, vNewIndex, N, v);
     161              :                 }
     162              :         }
     163              : 
     164              :         // sanity check
     165            0 :         if (N < vvConnections.size()){
     166              :                 size_t fails = 0;
     167            0 :                 for (v=0; v < vvConnections.size(); v++) {
     168            0 :                         if (!vVisited[v]) {
     169              :                                 UG_DLOG(LIB_DISC_ORDER, 2, v << "was not visited, has unresolved ancestors: " << vAncestorsCount[v] << std::endl);
     170            0 :                                 fails ++;
     171              :                         }
     172              :                 }
     173            0 :                 UG_THROW("OrderDownwindForDist failed, " << fails << " traits unvisited." << std::endl);
     174              :         }
     175              : 
     176              :         //      reorder traits
     177            0 :         dd->permute_indices(vNewIndex);
     178            0 : }
     179              : 
     180              : // Calculates Downwind Numbering for all DofDistributions of one Domain.
     181              : template <typename TDomain>
     182            0 : void OrderDownwind(ApproximationSpace<TDomain>& approxSpace,
     183              :                 SmartPtr<UserData<MathVector<TDomain::dim>, TDomain::dim> > spVelocity, number threshold)
     184              : {
     185              :         UG_LOG ("OrderDownwind: This function is obsolete and may cause problems. Avoid it! Alternatives: Ordering strategies in solvers etc.\n");
     186              :         
     187              :         // TODO: implement for variable time and subset
     188              :         number time = 0.0;
     189              :         int si = 0;
     190            0 :         std::vector<SmartPtr<DoFDistribution> > vDD = approxSpace.dof_distributions();
     191              :         UG_DLOG(LIB_DISC_ORDER, 2, "Starting DownwindOrdering." << std::endl);
     192            0 :         for(size_t i = 0; i < vDD.size(); ++i){
     193              :                 UG_DLOG(LIB_DISC_ORDER, 2, "Ordering Domain Distribution " << i << "." << std::endl);
     194            0 :                 OrderDownwindForDofDist<TDomain>(vDD[i], approxSpace.domain(), spVelocity, time, si, threshold);
     195              :         }
     196            0 : }
     197              : 
     198              : // Calculates Downwind Numbering for all DofDistributions of one Domain.
     199              : template <typename TDomain>
     200            0 : void OrderDownwind(ApproximationSpace<TDomain>& approxSpace,
     201              :                 SmartPtr<UserData<MathVector<TDomain::dim>, TDomain::dim> > spVelocity)
     202              : {
     203            0 :         OrderDownwind<TDomain>(approxSpace, spVelocity, PI/4.0);
     204            0 : }
     205              : 
     206              : // Calculates Downwind Numbering for all DofDistributions of one Domain.
     207              : template <typename TDomain>
     208            0 : void OrderDownwind(ApproximationSpace<TDomain>& approxSpace,
     209              :                                         const std::vector<number>& vVel)
     210              : {
     211              :         static const int dim = TDomain::dim;
     212            0 :         if(vVel.size() != dim){
     213            0 :                 UG_THROW("OrderDownstream: Velocity field of dimension " << dim << " expected, got "<< vVel.size());
     214              :         }
     215              : 
     216            0 :         OrderDownwind<TDomain>(approxSpace,  SmartPtr<ConstUserVector<dim> >(new ConstUserVector<dim>(vVel)) );
     217            0 : }
     218              : 
     219              : // Calculates Downwind Numbering for all DofDistributions of one Domain.
     220              : template <typename TDomain>
     221            0 : void OrderDownwind(ApproximationSpace<TDomain>& approxSpace,
     222              :                                         const std::vector<number>& vVel, number threshold)
     223              : {
     224              :         static const int dim = TDomain::dim;
     225            0 :         if(vVel.size() != dim){
     226            0 :                 UG_THROW("OrderDownstream: Velocity field of dimension " << dim << " expected, got "<< vVel.size());
     227              :         }
     228              : 
     229            0 :         OrderDownwind<TDomain>(approxSpace,  SmartPtr<ConstUserVector<dim> >(new ConstUserVector<dim>(vVel)), threshold );
     230            0 : }
     231              : 
     232              : 
     233              : #ifdef UG_FOR_LUA
     234              : 
     235              : // Calculates Downwind Numbering for all DofDistributions of one Domain.
     236              : template <typename TDomain>
     237            0 : void OrderDownwind(ApproximationSpace<TDomain>& approxSpace, const char* strVelocity)
     238              : {
     239              :         static const int dim = TDomain::dim;
     240              : 
     241            0 :         SmartPtr<UserData<MathVector<dim>, dim> > spVelocity
     242            0 :          = make_sp(new LuaUserData<MathVector<dim>, dim>(strVelocity));
     243              : 
     244            0 :         OrderDownwind<TDomain>(approxSpace, spVelocity);
     245            0 : }
     246              : 
     247              : // Calculates Downwind Numbering for all DofDistributions of one Domain.
     248              : template <typename TDomain>
     249            0 : void OrderDownwind(ApproximationSpace<TDomain>& approxSpace, const char* strVelocity, number threshold)
     250              : {
     251              :         static const int dim = TDomain::dim;
     252              : 
     253            0 :         SmartPtr<UserData<MathVector<dim>, dim> > spVelocity
     254            0 :          = make_sp(new LuaUserData<MathVector<dim>, dim>(strVelocity));
     255              : 
     256            0 :         OrderDownwind<TDomain>(approxSpace, spVelocity, threshold);
     257            0 : }
     258              : 
     259              : #ifdef UG_DIM_1
     260              : template void OrderDownwind<Domain1d>(ApproximationSpace<Domain1d>& approxSpace, const char* strVelocity);
     261              : template void OrderDownwind<Domain1d>(ApproximationSpace<Domain1d>& approxSpace, const char* strVelocity, number threshold);
     262              : #endif
     263              : #ifdef UG_DIM_2
     264              : template void OrderDownwind<Domain2d>(ApproximationSpace<Domain2d>& approxSpace, const char* strVelocity);
     265              : template void OrderDownwind<Domain2d>(ApproximationSpace<Domain2d>& approxSpace, const char* strVelocity, number threshold);
     266              : #endif
     267              : #ifdef UG_DIM_3
     268              : template void OrderDownwind<Domain3d>(ApproximationSpace<Domain3d>& approxSpace, const char* strVelocity);
     269              : template void OrderDownwind<Domain3d>(ApproximationSpace<Domain3d>& approxSpace, const char* strVelocity, number threshold);
     270              : #endif
     271              : 
     272              : #endif
     273              : 
     274              : #ifdef UG_DIM_1
     275              : template void OrderDownwind<Domain1d>(ApproximationSpace<Domain1d>& approxSpace, SmartPtr<UserData<MathVector<Domain1d::dim>, Domain1d::dim> > spVelocity);
     276              : template void OrderDownwind<Domain1d>(ApproximationSpace<Domain1d>& approxSpace, SmartPtr<UserData<MathVector<Domain1d::dim>, Domain1d::dim> > spVelocity, number threshold);
     277              : template void OrderDownwind<Domain1d>(ApproximationSpace<Domain1d>& approxSpace, const std::vector<number>& vVel);
     278              : template void OrderDownwind<Domain1d>(ApproximationSpace<Domain1d>& approxSpace, const std::vector<number>& vVel, number threshold);
     279              : #endif
     280              : 
     281              : #ifdef UG_DIM_2
     282              : template void OrderDownwind<Domain2d>(ApproximationSpace<Domain2d>& approxSpace, SmartPtr<UserData<MathVector<Domain2d::dim>, Domain2d::dim> > spVelocity);
     283              : template void OrderDownwind<Domain2d>(ApproximationSpace<Domain2d>& approxSpace, SmartPtr<UserData<MathVector<Domain2d::dim>, Domain2d::dim> > spVelocity, number threshold);
     284              : template void OrderDownwind<Domain2d>(ApproximationSpace<Domain2d>& approxSpace, const std::vector<number>& vVel);
     285              : template void OrderDownwind<Domain2d>(ApproximationSpace<Domain2d>& approxSpace, const std::vector<number>& vVel, number threshold);
     286              : #endif
     287              : 
     288              : #ifdef UG_DIM_3
     289              : template void OrderDownwind<Domain3d>(ApproximationSpace<Domain3d>& approxSpace, SmartPtr<UserData<MathVector<Domain3d::dim>, Domain3d::dim> > spVelocity);
     290              : template void OrderDownwind<Domain3d>(ApproximationSpace<Domain3d>& approxSpace, SmartPtr<UserData<MathVector<Domain3d::dim>, Domain3d::dim> > spVelocity, number threshold);
     291              : template void OrderDownwind<Domain3d>(ApproximationSpace<Domain3d>& approxSpace, const std::vector<number>& vVel);
     292              : template void OrderDownwind<Domain3d>(ApproximationSpace<Domain3d>& approxSpace, const std::vector<number>& vVel, number threshold);
     293              : #endif
     294              : 
     295              : } // end namespace ug
        

Generated by: LCOV version 2.0-1