8#include <kernel/geometry/unit_cube_patch_generator.hpp> 
    9#include <control/domain/domain_control.hpp> 
   20      template<
typename DomainLevel_>
 
   27        typedef typename BaseClass::LevelType LevelType;
 
   28        typedef typename BaseClass::MeshType MeshType;
 
   30        typedef typename BaseClass::MeshNodeType MeshNodeType;
 
   36          int rank = comm_.
rank();
 
   37          int nprocs = comm_.
size();
 
   39          this->_layers.push_back(std::make_shared<LayerType>(comm_.
comm_dup(), 0));
 
   40          this->_layer_levels.resize(std::size_t(1));
 
   43          std::vector<int> ranks;
 
   46          std::unique_ptr<MeshNodeType> mesh_node;
 
   50          this->_layers.front()->set_neighbor_ranks(ranks);
 
   55            lvl_min = 
Math::max(lvl_max + lvl_min + 1, 0);
 
   60          for(; lvl < lvl_min; ++lvl)
 
   62            mesh_node = mesh_node->refine_unique();
 
   66          this->_layer_levels.front().push_front(std::make_shared<LevelType>(lvl, std::move(mesh_node)));
 
   73            this->_layer_levels.front().push_front(std::make_shared<LevelType>(++lvl,
 
   74              this->_layer_levels.front().front()->get_mesh_node()->refine_unique()));
 
   78          this->compile_virtual_levels();
 
   83      template<
typename DomainLevel_>
 
   90        typedef typename BaseClass::LevelType LevelType;
 
   91        typedef typename BaseClass::MeshType MeshType;
 
   96        static_assert(MeshType::shape_dim == 2, 
"HierarchUnitCubeDomainControl works only for 2D meshes");
 
  108          std::deque<int> ilvls;
 
  111          ilvls.resize(lvls.size());
 
  112          for(std::size_t i(0); i < lvls.size(); ++i)
 
  114            if(!lvls.at(i).parse(ilvls.at(i)))
 
  116              comm_.
print(std::cerr, 
"ERROR: failed to parse '" + lvls.at(i) + 
"' as level");
 
  120          if(ilvls.size() < std::size_t(2))
 
  127        static int _ilog4(
int x)
 
  140        static int _2lvl2lexi(
int rank, 
int size)
 
  142          const int ls = _ilog4(size);
 
  144          for(
int i(0); i < ls; ++i)
 
  146            ix |= (rank >> (i+0)) & (1 << i);
 
  147            iy |= (rank >> (i+1)) & (1 << i);
 
  149          return iy*(1 << ls) + ix;
 
  153        static void _lexi22lvl(std::vector<int>& ranks, std::map<int,int>& reranks, 
int size)
 
  155          const int ls = _ilog4(size);
 
  156          for(
auto& rank : ranks)
 
  158            const int ix = rank % (1 << ls);
 
  159            const int iy = rank / (1 << ls);
 
  161            for(
int i(0); i < ls; ++i)
 
  163              rr |= (ix & (1 << i)) << (i+0);
 
  164              rr |= (iy & (1 << i)) << (i+1);
 
  166            reranks.insert(std::make_pair(rank, rr));
 
  171        void _create(
const std::deque<int>& lvls)
 
  173          const int log4n = _ilog4(this->_comm.
size());
 
  174          XASSERTM(log4n >= 0, 
"number of processes must be a power of 4");
 
  179          _create_layers(log4n, 
int(lvls.size())-1);
 
  181          this->_layer_levels.resize(this->_layers.size());
 
  184          for(std::size_t i(0); i < this->_layers.size(); ++i)
 
  186            auto& layer = *this->_layers.at(i);
 
  187            auto& laylevs = this->_layer_levels.at(i);
 
  189            const int csize = layer.comm().size();
 
  190            const int crank = _2lvl2lexi(layer.comm().rank(), csize);
 
  192            std::vector<int> ranks;
 
  193            std::map<int,int> reranks; 
 
  196            std::unique_ptr<MeshNodeType> mesh_node;
 
  200            _lexi22lvl(ranks, reranks, csize);
 
  203            mesh_node->rename_halos(reranks);
 
  206            layer.set_neighbor_ranks(ranks);
 
  209            laylevs.push_front(std::make_shared<LevelType>(base_lvl, mesh_node));
 
  212            if(i > std::size_t(0))
 
  214              std::shared_ptr<MeshNodeType> ref_node = std::shared_ptr<MeshNodeType>(laylevs.front()->get_mesh_node()->refine());
 
  215              this->_create_child_meshparts(layer, ref_node);
 
  216              laylevs.push_front(std::make_shared<LevelType>(base_lvl+1, ref_node));
 
  219            const int head_lvl = laylevs.front()->get_level_index();
 
  220            const int fin_lvl = lvls.at(i);
 
  221            const int crs_lvl = lvls.at(i+1);
 
  224            for(
int l(head_lvl); l < fin_lvl; ++l)
 
  226              std::shared_ptr<MeshNodeType> ref_node = std::shared_ptr<MeshNodeType>(laylevs.front()->get_mesh_node()->refine());
 
  227              laylevs.push_front(std::make_shared<LevelType>(l+1, ref_node));
 
  231            for(
int l(base_lvl); l < crs_lvl; ++l)
 
  238          this->compile_virtual_levels();
 
  241        void _create_layers(
int , 
int nlayers)
 
  244          this->_layers.push_back(std::make_shared<LayerType>(this->_comm.
comm_dup(), 0));
 
  247          for(
int i(0); (i+1) < nlayers; ++i)
 
  256            const int rank = comm_c.
rank();
 
  263            child.set_parent(std::move(comm_s), 0); 
 
  271            this->_layers.push_back(std::make_shared<DomainLayer>(std::move(comm_p), i+1));
 
  275        void _create_child_meshparts(
const DomainLayer& , std::shared_ptr<MeshNodeType> mesh_node)
 
  277          Index num_elems = mesh_node->get_mesh()->get_num_elements();
 
  280          const Index num_entities[] = {4, 4, 1};
 
  282          const Index ivert[4][4] =
 
  289          const Index iedge[4][4] =
 
  297          for(
int i(0); i < 4; ++i)
 
  302            Index* iv = part->template get_target_set<0>().get_indices();
 
  303            Index* ie = part->template get_target_set<1>().get_indices();
 
  304            Index* iq = part->template get_target_set<2>().get_indices();
 
  305            for(
int j(0); j < 4; ++j)
 
  312            mesh_node->add_patch(i, part);
 
  318      template<
typename DomainLevel_>
 
  325        typedef typename BaseClass::LevelType LevelType;
 
  326        typedef typename BaseClass::MeshType MeshType;
 
  331        static_assert(MeshType::shape_dim == 2, 
"HierarchUnitCubeDomainControl works only for 2D meshes");
 
  343          std::deque<int> ilvls, ilyrs;
 
  346          ilvls.resize(lvls.size());
 
  347          ilyrs.resize(lvls.size(), 1);
 
  348          for(std::size_t i(0); i < lvls.size(); ++i)
 
  350            std::deque<String> parts = lvls.at(i).split_by_string(
":");
 
  351            if(!parts.front().parse(ilvls.at(i)))
 
  353              comm_.
print(std::cerr, 
"ERROR: failed to parse '" + lvls.at(i) + 
"' as level");
 
  356            if((parts.size() > std::size_t(1)) && !parts.back().parse(ilyrs.at(i)))
 
  358              comm_.
print(std::cerr, 
"ERROR: failed to parse '" + lvls.at(i) + 
"' as layer");
 
  362          if(ilvls.size() < std::size_t(2))
 
  368          _create(ilvls, ilyrs);
 
  374          std::deque<int> ilvls, ilyrs;
 
  377          ilvls.resize(lvls.size());
 
  378          ilyrs.resize(lvls.size(), 1);
 
  379          for(std::size_t i(0); i < lvls.size(); ++i)
 
  381            std::deque<String> parts = lvls.at(i).split_by_string(
":");
 
  382            if(!parts.front().parse(ilvls.at(i)))
 
  384              comm_.
print(std::cerr, 
"ERROR: failed to parse '" + lvls.at(i) + 
"' as level");
 
  387            if((parts.size() > std::size_t(1)) && !parts.back().parse(ilyrs.at(i)))
 
  389              comm_.
print(std::cerr, 
"ERROR: failed to parse '" + lvls.at(i) + 
"' as layer");
 
  393          if(ilvls.size() < std::size_t(2))
 
  399          _create(ilvls, ilyrs);
 
  402        std::deque<std::pair<int,int>> get_level_indices()
 const 
  404          std::deque<std::pair<int,int>> lvs;
 
  405          for(std::size_t i(0); i < this->_layer_levels.size(); ++i)
 
  408                this->_layer_levels.at(i).front()->get_level_index(),
 
  409                this->_layers.at(i)->comm().size()));
 
  412              this->_layer_levels.back().back()->get_level_index(),
 
  413              this->_layers.back()->comm().size()));
 
  418        static int _ilog4(
int x)
 
  431        static int _2lvl2lexi(
int rank, 
int size)
 
  433          const int ls = _ilog4(size);
 
  435          for(
int i(0); i < ls; ++i)
 
  437            ix |= (rank >> (i+0)) & (1 << i);
 
  438            iy |= (rank >> (i+1)) & (1 << i);
 
  440          return iy*(1 << ls) + ix;
 
  444        static void _lexi22lvl(std::vector<int>& ranks, std::map<int,int>& reranks, 
int size)
 
  446          const int ls = _ilog4(size);
 
  447          for(
auto& rank : ranks)
 
  449            const int ix = rank % (1 << ls);
 
  450            const int iy = rank / (1 << ls);
 
  452            for(
int i(0); i < ls; ++i)
 
  454              rr |= (ix & (1 << i)) << (i+0);
 
  455              rr |= (iy & (1 << i)) << (i+1);
 
  457            reranks.insert(std::make_pair(rank, rr));
 
  462        void _create(
const std::deque<int>& lvls, 
const std::deque<int>& lyrs)
 
  464          const int log4n = _ilog4(this->_comm.
size());
 
  465          XASSERTM(log4n >= 0, 
"number of processes must be a power of 4");
 
  468          XASSERT(lvls.size() == lyrs.size());
 
  471          _create_layers(lyrs);
 
  473          this->_layer_levels.resize(this->_layers.size());
 
  476          for(std::size_t i(0); i < this->_layers.size(); ++i)
 
  478            auto& layer = *this->_layers.at(i);
 
  479            auto& laylevs = this->_layer_levels.at(i);
 
  481            const int csize = layer.comm().size();
 
  482            const int crank = _2lvl2lexi(layer.comm().rank(), csize);
 
  484            std::vector<int> ranks;
 
  485            std::map<int,int> reranks; 
 
  488            std::unique_ptr<MeshNodeType> mesh_node;
 
  492            _lexi22lvl(ranks, reranks, csize);
 
  495            mesh_node->rename_halos(reranks);
 
  498            layer.set_neighbor_ranks(ranks);
 
  501            laylevs.push_front(std::make_shared<LevelType>(base_lvl, std::move(mesh_node)));
 
  504            if(i > std::size_t(0))
 
  506              int children = this->_layers.at(i-1)->comm().size() / csize;
 
  507              int crs_lvl = base_lvl;
 
  508              for(
int nel(1); nel < children; nel *= 4)
 
  513                laylevs.push_front(std::make_shared<LevelType>(++crs_lvl, laylevs.front()->get_mesh_node()->refine_unique()));
 
  515              this->_create_child_meshparts(*laylevs.front()->get_mesh_node());
 
  518            const int head_lvl = laylevs.front()->get_level_index();
 
  519            const int fin_lvl = lvls.at(i);
 
  520            const int crs_lvl = lvls.at(i+1);
 
  523            for(
int l(head_lvl); l < fin_lvl; ++l)
 
  527              laylevs.push_front(std::make_shared<LevelType>(l+1, laylevs.front()->get_mesh_node()->refine_unique()));
 
  531            for(
int l(base_lvl); l < crs_lvl; ++l)
 
  538          this->compile_virtual_levels();
 
  541        void _create_layers(
const std::deque<int>& lyrs)
 
  544          this->_layers.push_back(std::make_shared<LayerType>(this->_comm.
comm_dup(), 0));
 
  547          for(
int ilay(1); (ilay+1) < 
int(lyrs.size()); ++ilay)
 
  556            const int rank = comm_c.
rank();
 
  559            const int nsib = 
Math::sqr(1 << lyrs.at(std::size_t(ilay)));
 
  567            child.set_parent(std::move(comm_s), 0); 
 
  575            this->_layers.push_back(std::make_shared<DomainLayer>(std::move(comm_p), ilay));
 
  581          const Index num_elems = mesh_node.
get_mesh()->get_num_elements();
 
  583          const Index num_entities[] = {4, 4, 1};
 
  584          const auto& ivert = mesh_node.
get_mesh()->template get_index_set<2,0>();
 
  585          const auto& iedge = mesh_node.
get_mesh()->template get_index_set<2,1>();
 
  587          for(
Index i(0); i < num_elems; ++i)
 
  589            std::unique_ptr<MeshPartType> part(
new MeshPartType(num_entities, 
false));
 
  592            Index* iv = part->template get_target_set<0>().get_indices();
 
  593            Index* ie = part->template get_target_set<1>().get_indices();
 
  594            Index* iq = part->template get_target_set<2>().get_indices();
 
  596            for(
int j(0); j < 4; ++j)
 
  603            mesh_node.
add_patch(
int(i), std::move(part));
 
#define XASSERT(expr)
Assertion macro definition.
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Domain control base-class template.
Comm comm_create_range_incl(int count, int first=0, int stride=1) const
Creates a new sub-communicator from a strided range of ranks.
int size() const
Returns the size of this communicator.
Comm comm_dup() const
Creates a copy of this communicator.
int rank() const
Returns the rank of this process in this communicator.
bool is_null() const
Checks whether this communicator is a null communicator.
void print(std::ostream &os, const String &msg, int root=0) const
Prints a message line to an output stream.
MeshType * get_mesh()
Returns the mesh of this node.
Class template for partial meshes.
Root mesh node class template.
MeshPartType * add_patch(int rank, std::unique_ptr< MeshPartType > patch_part)
Adds a patch mesh part to this mesh node.
static void abort(bool dump_call_stack=true)
FEAT abortion.
@ child
indicates that the level is a child level
T_ sqr(T_ x)
Returns the square of a value.
T_ min(T_ a, T_ b)
Returns the minimum of two values.
T_ max(T_ a, T_ b)
Returns the maximum of two values.
std::uint64_t Index
Index data type.