18 #if !defined(__FLECSI_PRIVATE__) 19 #error Do not include this file directly! 22 #include "flecsi/topo/core.hh" 47 namespace verify_mesh {
111 template<
typename POLICY_TYPE>
118 static_assert(verify_mesh::has_member_num_dimensions<POLICY_TYPE>::value,
119 "mesh policy missing num_dimensions size_t");
122 std::is_convertible<decltype(POLICY_TYPE::num_dimensions),
size_t>::value,
123 "mesh policy num_dimensions must be size_t");
125 static_assert(verify_mesh::has_member_num_domains<POLICY_TYPE>::value,
126 "mesh policy missing num_domains size_t");
129 std::is_convertible<decltype(POLICY_TYPE::num_domains),
size_t>::value,
130 "mesh policy num_domains must be size_t");
132 static_assert(verify_mesh::has_member_entity_types<POLICY_TYPE>::value,
133 "mesh policy missing entity_types tuple");
136 "mesh policy entity_types is not a tuple");
138 static_assert(verify_mesh::has_member_connectivities<POLICY_TYPE>::value,
139 "mesh policy missing connectivities tuple");
142 "mesh policy connectivities is not a tuple");
144 static_assert(verify_mesh::has_member_bindings<POLICY_TYPE>::value,
145 "mesh policy missing bindings tuple");
148 "mesh policy bindings is not a tuple");
150 static_assert(verify_mesh::has_member_create_entity<POLICY_TYPE>::value,
151 "mesh policy missing create_entity()");
153 template<std::
size_t>
159 std::vector<base_data_t> entities;
160 std::vector<base_data_t> adjacencies;
161 std::vector<data::partition> exclusive;
162 std::vector<data::partition> shared;
163 std::vector<data::partition> ghost;
164 std::vector<data::partition> ghost_owners;
168 template<
class POLICY_TYPE>
169 template<std::
size_t Priv>
173 POLICY_TYPE::num_domains,
184 template<
class POLICY_TYPE>
186 :
mesh_base<mesh_storage<POLICY_TYPE::num_dimensions,
187 POLICY_TYPE::num_domains,
188 num_index_subspaces<POLICY_TYPE>::value>>
192 using storage_t =
mesh_storage<POLICY_TYPE::num_dimensions,
193 POLICY_TYPE::num_domains,
206 template<
size_t DIM,
size_t DOM = 0>
217 override default move assignement
unstructured & operator=(
220 Constructor, takes as input a mesh storage or
222 storage_t * ms =
nullptr)
225 initialize_storage();
229 Copy constructor : alias another mesh unstructured(
230 const unstructured & m)
235 virtual ~unstructured() {}
242 void initialize_storage() {
244 for(
size_t from_domain = 0; from_domain < POLICY_TYPE::num_domains;
246 for(
size_t to_domain = 0; to_domain < POLICY_TYPE::num_domains;
248 base_t::ms_->topology[from_domain][to_domain].init_(
249 from_domain, to_domain);
253 for(
size_t to_domain = 0; to_domain < POLICY_TYPE::num_domains; ++to_domain) {
254 for(
size_t to_dim = 0; to_dim <= POLICY_TYPE::num_dimensions; ++to_dim) {
255 auto & master = base_t::ms_->index_spaces[to_domain][to_dim];
257 for(
size_t from_domain = 0; from_domain < POLICY_TYPE::num_domains;
259 for(
size_t from_dim = 0; from_dim <= POLICY_TYPE::num_dimensions;
261 get_connectivity_(from_domain, to_domain, from_dim, to_dim)
279 template<
size_t DOM,
class CELL_TYPE,
typename VERT_TYPE>
280 void init_cell(CELL_TYPE * cell, VERT_TYPE && verts) {
281 init_cell_<DOM>(cell, std::forward<VERT_TYPE>(verts));
293 template<
size_t DOM,
class CELL_TYPE,
typename VERT_TYPE>
294 void init_cell(CELL_TYPE * cell, std::initializer_list<VERT_TYPE *> verts) {
295 init_cell_<DOM>(cell, verts);
316 void init_entity(ENT_TYPE1 * super, ENT_TYPE2 && subs) {
317 init_entity_<DOM, FROM_DIM, TO_DIM>(super, std::forward<ENT_TYPE2>(subs));
338 void init_entity(ENT_TYPE1 * super, std::initializer_list<ENT_TYPE2 *> subs) {
339 init_entity_<DOM, FROM_DIM, TO_DIM>(super, subs);
350 size_t num_entities(
size_t dim,
size_t domain = 0)
const override {
351 return num_entities_(dim, domain);
361 template<
size_t DOM = 0>
364 using TP =
typename POLICY_TYPE::connectivities;
367 using BT =
typename POLICY_TYPE::bindings;
379 template<
size_t DOM = 0>
380 void init_bindings() {
381 using BT =
typename POLICY_TYPE::bindings;
393 template<
size_t DIM,
size_t DOM = 0>
394 decltype(
auto) num_entities()
const {
395 return base_t::ms_->index_spaces[DOM][DIM].size();
408 template<
size_t DIM,
size_t DOM = 0>
409 decltype(
auto) num_entities(partition_t partition)
const {
410 return base_t::ms_->partition_index_spaces[partition][DOM][DIM].size();
421 size_t to_dim)
const override {
422 return get_connectivity_(from_domain, to_domain, from_dim, to_dim);
433 size_t to_dim)
override {
434 return get_connectivity_(from_domain, to_domain, from_dim, to_dim);
444 size_t to_dim)
const override {
445 return get_connectivity_(domain, domain, from_dim, to_dim);
454 get_connectivity(
size_t domain,
size_t from_dim,
size_t to_dim)
override {
455 return get_connectivity_(domain, domain, from_dim, to_dim);
463 return POLICY_TYPE::num_dimensions;
474 template<
size_t DOM = 0>
475 const auto & get_index_space_(
size_t dim)
const {
476 return base_t::ms_->index_spaces[DOM][dim];
487 template<
size_t DOM = 0>
488 auto & get_index_space_(
size_t dim) {
489 return base_t::ms_->index_spaces[DOM][dim];
503 template<
size_t DOM = 0>
504 const auto & get_index_space_(
size_t dim, partition_t partition)
const {
505 return base_t::ms_->partition_index_spaces[partition][DOM][dim];
519 template<
size_t DOM = 0>
520 auto & get_index_space_(
size_t dim, partition_t partition) {
521 return base_t::ms_->partition_index_spaces[partition][DOM][dim];
532 template<
size_t DIM,
size_t DOM = 0>
533 auto get_entity(id_t global_id)
const {
534 using etype = entity_type<DIM, DOM>;
535 return static_cast<etype *
>(
536 base_t::ms_->index_spaces[DOM][DIM][global_id.entity()]);
551 template<
size_t DOM = 0>
552 auto get_entity(
size_t dim, id_t global_id) {
553 return base_t::ms_->index_spaces[DOM][dim][global_id.entity()];
569 template<
size_t DIM,
size_t DOM = 0>
570 auto get_entity(id_t global_id, partition_t partition)
const {
571 using etype = entity_type<DIM, DOM>;
572 return static_cast<etype *
>(
574 ->partition_index_spaces[partition][DOM][DIM][global_id.entity()]);
589 template<
size_t DOM = 0>
590 auto get_entity(
size_t dim, id_t global_id, partition_t partition) {
592 ->partition_index_spaces[partition][DOM][dim][global_id.entity()];
609 size_t TO_DOM = FROM_DOM,
611 const auto entities(
const ENT_TYPE * e)
const {
614 get_connectivity(FROM_DOM, TO_DOM, ENT_TYPE::dimension, DIM);
617 using etype = entity_type<DIM, TO_DOM>;
620 return c.get_index_space().slice<dtype>(
621 c.range(e->template id<FROM_DOM>()));
638 size_t TO_DOM = FROM_DOM,
640 auto entities(ENT_TYPE * e) {
642 get_connectivity(FROM_DOM, TO_DOM, ENT_TYPE::dimension, DIM);
645 using etype = entity_type<DIM, TO_DOM>;
648 return c.get_index_space().slice<dtype>(
649 c.range(e->template id<FROM_DOM>()));
666 size_t TO_DOM = FROM_DOM,
669 return entities<DIM, FROM_DOM, TO_DOM>(e.entity());
686 size_t TO_DOM = FROM_DOM,
689 return entities<DIM, FROM_DOM, TO_DOM>(e.entity());
700 template<
size_t DIM,
size_t DOM = 0>
701 auto entities()
const {
702 using etype = entity_type<DIM, DOM>;
704 return base_t::ms_->index_spaces[DOM][DIM].template slice<dtype>();
718 template<
size_t DIM,
size_t DOM = 0>
719 auto entities(partition_t partition)
const {
720 using etype = entity_type<DIM, DOM>;
722 return base_t::ms_->partition_index_spaces[partition][DOM][DIM]
723 .template slice<dtype>();
734 template<
size_t DIM,
size_t DOM = 0>
735 auto entity_ids()
const {
736 return base_t::ms_->index_spaces[DOM][DIM].ids();
749 template<
size_t DIM,
size_t DOM = 0>
750 auto entity_ids(partition_t partition)
const {
751 return base_t::ms_->partition_index_spaces[partition][DOM][DIM].ids();
769 size_t TO_DOM = FROM_DOM,
772 return entity_ids<DIM, FROM_DOM, TO_DOM>(e.entity());
790 size_t TO_DOM = FROM_DOM,
792 auto entity_ids(
const ENT_TYPE * e)
const {
794 get_connectivity(FROM_DOM, TO_DOM, ENT_TYPE::dimension, DIM);
796 return c.get_index_space().ids(c.range(e->template id<FROM_DOM>()));
813 size_t TO_DOM = FROM_DOM,
815 void reverse_entities(ENT_TYPE * e) {
816 auto & c = get_connectivity(FROM_DOM, TO_DOM, ENT_TYPE::dimension, DIM);
818 c.reverse_entities(e->template id<FROM_DOM>());
835 size_t TO_DOM = FROM_DOM,
838 return reverse_entities<DIM, FROM_DOM, TO_DOM>(e.entity());
856 size_t TO_DOM = FROM_DOM,
859 void reorder_entities(ENT_TYPE * e, U && order) {
860 auto & c = get_connectivity(FROM_DOM, TO_DOM, ENT_TYPE::dimension, DIM);
862 c.reorder_entities(e->template id<FROM_DOM>(), std::forward<U>(order));
880 size_t TO_DOM = FROM_DOM,
884 return reorder_entities<DIM, FROM_DOM, TO_DOM>(
885 e.entity(), std::forward<U>(order));
894 template<
size_t INDEX_SUBSPACE>
895 auto & subentities() {
896 return get_index_subspace<INDEX_SUBSPACE>();
905 template<
size_t INDEX_SUBSPACE>
906 const auto & subentities()
const {
907 return get_index_subspace<INDEX_SUBSPACE>();
916 template<
size_t INDEX_SUBSPACE>
917 auto num_subentities()
const {
918 return base_t::ms_->index_subspaces[INDEX_SUBSPACE].size();
928 std::ostream & dump(std::ostream & stream) {
929 for(
size_t from_domain = 0; from_domain < POLICY_TYPE::num_domains;
931 stream <<
"=================== from domain: " << from_domain << std::endl;
932 for(
size_t to_domain = 0; to_domain < POLICY_TYPE::num_domains;
934 stream <<
"========== to domain: " << to_domain << std::endl;
935 base_t::ms_->topology[from_domain][to_domain].dump(stream);
955 void save(A & archive)
const {
957 char * data = serialize_(size);
958 archive.saveBinary(&size,
sizeof(size));
960 archive.saveBinary(data, size);
969 void load(A & archive) {
971 archive.loadBinary(&size,
sizeof(size));
973 char * data =
new char[size];
974 archive.loadBinary(data, size);
983 char * serialize_(uint64_t & size)
const {
984 const size_t alloc_size = 1048576;
987 char * buf =
new char[alloc_size];
990 uint32_t num_domains = POLICY_TYPE::num_domains;
991 std::memcpy(buf + pos, &num_domains,
sizeof(num_domains));
992 pos +=
sizeof(num_domains);
994 uint32_t num_dimensions = POLICY_TYPE::num_dimensions;
995 std::memcpy(buf + pos, &num_dimensions,
sizeof(num_dimensions));
996 pos +=
sizeof(num_dimensions);
998 for(
size_t domain = 0; domain < POLICY_TYPE::num_domains; ++domain) {
999 for(
size_t dimension = 0; dimension <= POLICY_TYPE::num_dimensions;
1001 uint64_t num_entities = base_t::ms_->entities[domain][dimension].size();
1002 std::memcpy(buf + pos, &num_entities,
sizeof(num_entities));
1003 pos +=
sizeof(num_entities);
1007 for(
size_t from_domain = 0; from_domain < POLICY_TYPE::num_domains;
1009 for(
size_t to_domain = 0; to_domain < POLICY_TYPE::num_domains;
1012 auto & dc = base_t::ms_->topology[from_domain][to_domain];
1014 for(
size_t from_dim = 0; from_dim <= POLICY_TYPE::num_dimensions;
1016 for(
size_t to_dim = 0; to_dim <= POLICY_TYPE::num_dimensions;
1020 auto & tv = c.to_id_storage();
1021 uint64_t num_to = tv.size();
1022 std::memcpy(buf + pos, &num_to,
sizeof(num_to));
1023 pos +=
sizeof(num_to);
1025 size_t bytes = num_to *
sizeof(id_vector_t::value_type);
1027 if(size - pos < bytes) {
1028 size += bytes + alloc_size;
1029 buf = (
char *)std::realloc(buf, size);
1032 std::memcpy(buf + pos, tv.data(), bytes);
1035 uint64_t num_offsets = c.offsets().size();
1036 std::memcpy(buf + pos, &num_offsets,
sizeof(num_offsets));
1037 pos +=
sizeof(num_offsets);
1039 bytes = num_offsets *
sizeof(offset_t);
1041 if(size - pos < bytes) {
1042 size += bytes + alloc_size;
1043 buf = (
char *)std::realloc(buf, size);
1046 std::memcpy(buf + pos, c.offsets().storage().buffer(), bytes);
1062 void unserialize_(
char * buf) {
1065 uint32_t num_domains;
1066 std::memcpy(&num_domains, buf + pos,
sizeof(num_domains));
1067 pos +=
sizeof(num_domains);
1068 flog_assert(num_domains == POLICY_TYPE::num_domains,
"domain size mismatch");
1070 uint32_t num_dimensions;
1071 std::memcpy(&num_dimensions, buf + pos,
sizeof(num_dimensions));
1072 pos +=
sizeof(num_dimensions);
1074 num_dimensions == POLICY_TYPE::num_dimensions,
"dimension size mismatch");
1078 POLICY_TYPE::num_domains,
1079 POLICY_TYPE::num_dimensions,
1080 0>::unserialize(*
this, buf, pos);
1082 for(
size_t from_domain = 0; from_domain < POLICY_TYPE::num_domains;
1084 for(
size_t to_domain = 0; to_domain < POLICY_TYPE::num_domains;
1087 auto & dc = base_t::ms_->topology[from_domain][to_domain];
1089 for(
size_t from_dim = 0; from_dim <= POLICY_TYPE::num_dimensions;
1091 for(
size_t to_dim = 0; to_dim <= POLICY_TYPE::num_dimensions;
1095 auto & tv = c.to_id_storage();
1097 std::memcpy(&num_to, buf + pos,
sizeof(num_to));
1098 pos +=
sizeof(num_to);
1099 auto ta = (id_vector_t::value_type *)(buf + pos);
1101 tv.assign(ta, ta + num_to);
1102 pos += num_to *
sizeof(id_vector_t::value_type);
1104 auto offsets_buf = c.offsets().storage().buffer();
1105 uint64_t num_offsets;
1106 std::memcpy(&num_offsets, buf + pos,
sizeof(num_offsets));
1107 pos +=
sizeof(num_offsets);
1108 std::memcpy(offsets_buf, buf + pos, num_offsets *
sizeof(offset_t));
1109 pos += num_offsets *
sizeof(offset_t);
1120 void append_to_index_space_(
size_t domain,
1122 std::vector<mesh_entity_base_ *> & ents,
1123 std::vector<id_t> & ids)
override {
1124 auto & is = base_t::ms_->index_spaces[domain][dim];
1125 is.append_(ents, ids);
1128 template<
size_t INDEX_SUBSPACE>
1129 auto & get_index_subspace() {
1130 using entity_types_t =
typename POLICY_TYPE::entity_types;
1132 using index_subspaces =
typename get_index_subspaces<POLICY_TYPE>::type;
1134 constexpr
size_t subspace_index =
1137 INDEX_SUBSPACE>::find();
1139 static_assert(subspace_index != -1,
"invalid index subspace");
1141 using subspace_entry_t =
1144 using index_space_t =
1147 constexpr
size_t index =
1150 index_space_t::value>::find();
1153 static_assert(index != -1,
"invalid index space");
1161 return base_t::ms_->index_subspaces[INDEX_SUBSPACE]
1162 .template cast<domain_entity<domain_t::value, entity_t>>();
1165 template<
size_t INDEX_SUBSPACE>
1166 const auto & get_index_subspace()
const {
1167 using entity_types_t =
typename POLICY_TYPE::entity_types;
1169 using index_subspaces =
typename get_index_subspaces<POLICY_TYPE>::type;
1171 constexpr
size_t subspace_index =
1174 INDEX_SUBSPACE>::find();
1176 static_assert(subspace_index != -1,
"invalid index subspace");
1178 using subspace_entry_t =
1181 using index_space_t =
1184 constexpr
size_t index =
1187 index_space_t::value>::find();
1190 static_assert(index != -1,
"invalid index space");
1198 return base_t::ms_->index_subspaces[INDEX_SUBSPACE]
1199 .template cast<domain_entity<domain_t::value, entity_t>>();
1203 return base_t::ms_->index_subspaces[index_subspace].size();
1207 template<
size_t,
size_t,
class>
1210 template<
size_t,
size_t,
class>
1213 template<
size_t DOM,
typename VERT_TYPE>
1214 void init_cell_(entity_type<POLICY_TYPE::num_dimensions, DOM> * cell,
1215 VERT_TYPE && verts) {
1216 auto & c = get_connectivity_(DOM, POLICY_TYPE::num_dimensions, 0);
1218 flog_assert(cell->template id<DOM>() == c.from_size(),
"id mismatch");
1220 for(entity_type<0, DOM> * v : std::forward<VERT_TYPE>(verts)) {
1221 c.push(v->template global_id<DOM>());
1224 c.add_count(static_cast<std::uint32_t>(verts.size()));
1227 template<
size_t DOM,
size_t FROM_DIM,
size_t TO_DIM,
class ENT_TYPE2>
1228 void init_entity_(entity_type<FROM_DIM, DOM> * super, ENT_TYPE2 && subs) {
1229 auto & c = get_connectivity_(DOM, FROM_DIM, TO_DIM);
1231 flog_assert(super->template id<DOM>() == c.from_size(),
"id mismatch");
1233 for(
auto e : std::forward<ENT_TYPE2>(subs)) {
1234 c.push(e->template global_id<DOM>());
1237 c.add_count(subs.size());
1241 size_t num_entities_(
size_t dim,
size_t domain = 0)
const {
1242 return base_t::ms_->index_spaces[domain][dim].size();
1246 size_t num_entities_(
size_t dim,
size_t domain, partition_t partition)
const {
1247 return base_t::ms_->partition_index_spaces[partition][domain][dim].size();
1258 template<
size_t Domain,
size_t DimensionToBuild,
size_t UsingDimension>
1259 typename std::enable_if<(
1260 UsingDimension <= 1 || UsingDimension > POLICY_TYPE::num_dimensions)>::
type 1261 build_connectivity() {
1278 template<
size_t Domain,
size_t DimensionToBuild,
size_t UsingDimension>
1279 typename std::enable_if<(
1281 build_connectivity() {
1286 static_assert(DimensionToBuild <= POLICY_TYPE::num_dimensions,
1287 "DimensionToBuild must be <= total number of dimensions");
1288 static_assert(UsingDimension <= POLICY_TYPE::num_dimensions,
1289 "UsingDimension must be <= total number of dimensions");
1290 static_assert(Domain < POLICY_TYPE::num_domains,
1291 "Domain must be < total number of domains");
1295 get_connectivity_(Domain, UsingDimension, DimensionToBuild);
1298 connection_vector_t entity_vertex_conn;
1301 size_t max_cell_entity_conns = 1;
1304 std::vector<size_t> entity_ids;
1307 base_t::ms_->topology[Domain][Domain];
1310 connectivity_t & cell_to_vertex = dc.template get<UsingDimension>(0);
1313 const size_t _num_cells = num_entities<UsingDimension, Domain>();
1316 connection_vector_t cell_entity_conn(_num_cells);
1322 id_vector_map_t entity_vertices_map;
1326 std::array<id_t, 4096> entity_vertices;
1328 using cell_type = entity_type<UsingDimension, Domain>;
1329 using entity_type = entity_type<DimensionToBuild, Domain>;
1331 auto & is = base_t::ms_->index_spaces[Domain][DimensionToBuild]
1332 .template cast<domain_entity<Domain, entity_type>>();
1334 auto & cis = base_t::ms_->index_spaces[Domain][UsingDimension]
1335 .template cast<domain_entity<Domain, cell_type>>();
1339 std::tuple_size<typename POLICY_TYPE::entity_types>::value,
1340 typename POLICY_TYPE::entity_types,
1347 std::tuple_size<typename POLICY_TYPE::entity_types>::value,
1348 typename POLICY_TYPE::entity_types,
1354 std::tuple_size<typename POLICY_TYPE::entity_types>::value,
1355 typename POLICY_TYPE::entity_types,
1360 auto & context_ = run::context::instance();
1361 size_t color = context_.color();
1362 auto & gis_to_cis = context_.reverse_index_map(cell_index_space);
1366 auto & reverse_intermediate_map =
1367 context_.reverse_intermediate_map(DimensionToBuild, Domain);
1368 auto has_intermediate_map = !reverse_intermediate_map.empty();
1371 auto & entity_index_map = context_.reverse_index_map(entity_index_space);
1376 auto & vertex_map = context_.index_map(vertex_index_space);
1379 size_t entity_counter{0};
1381 for(
auto & citr : gis_to_cis) {
1382 size_t c = citr.second;
1385 auto cell =
static_cast<cell_type *
>(cis[c]);
1386 id_t cell_id = cell->template global_id<Domain>();
1389 id_vector_t & conns = cell_entity_conn[c];
1392 conns.reserve(max_cell_entity_conns);
1400 auto sv = cell->create_entities(
1401 cell_id, DimensionToBuild, dc, entity_vertices.data());
1403 size_t n = sv.size();
1406 for(
size_t i = 0, pos = 0; i < n; ++i) {
1412 id_t * a = &entity_vertices[pos];
1413 id_vector_t ev(a, a + m);
1419 std::sort(ev.begin(), ev.end());
1440 if(has_intermediate_map) {
1442 std::vector<size_t> vertices_mis;
1443 vertices_mis.reserve(m);
1447 for(id_t * aptr{a}; aptr < (a + m); ++aptr) {
1448 vertices_mis.push_back(vertex_map[aptr->entity()]);
1452 std::sort(vertices_mis.begin(), vertices_mis.end());
1453 const auto entity_id_mis = reverse_intermediate_map.at(vertices_mis);
1456 entity_id = entity_index_map.at(entity_id_mis);
1460 entity_id = entity_counter;
1464 id_t
id = id_t::make<DimensionToBuild, Domain>(entity_id,
color);
1467 auto itr = entity_vertices_map.emplace(std::move(ev),
1468 id_t::make<DimensionToBuild, Domain>(entity_id, cell_id.partition()));
1471 conns.push_back(itr.first->second);
1477 id_vector_t ev2 = id_vector_t(a, a + m);
1478 entity_vertex_conn.emplace_back(std::move(ev2));
1479 entity_ids.emplace_back(entity_id);
1481 max_cell_entity_conns = std::max(max_cell_entity_conns, conns.size());
1484 POLICY_TYPE::template create_entity<Domain, DimensionToBuild>(
1500 if(has_intermediate_map)
1501 util::reorder_destructive(
1502 entity_ids.begin(), entity_ids.end(), entity_vertex_conn.begin());
1506 connectivity_t & entity_to_vertex = dc.template get<DimensionToBuild>(0);
1507 entity_to_vertex.init(entity_vertex_conn);
1508 cell_to_entity.
init(cell_entity_conn);
1522 template<
size_t FROM_DOM,
size_t TO_DOM,
size_t FROM_DIM,
size_t TO_DIM>
1528 auto & out_conn = get_connectivity_(FROM_DOM, TO_DOM, FROM_DIM, TO_DIM);
1529 if(!out_conn.empty()) {
1534 const auto & to_entities = entities<TO_DIM, TO_DOM>();
1536 index_vector_t pos(num_entities_(FROM_DIM, FROM_DOM), 0);
1539 for(
auto to_entity : to_entities) {
1540 for(id_t from_id : entity_ids<FROM_DIM, TO_DOM, FROM_DOM>(to_entity)) {
1541 ++pos[from_id.entity()];
1545 out_conn.resize(pos);
1547 std::fill(pos.begin(), pos.end(), 0);
1550 for(
auto to_entity : to_entities) {
1551 for(
auto from_id : entity_ids<FROM_DIM, TO_DOM, FROM_DOM>(to_entity)) {
1552 auto from_lid = from_id.entity();
1554 from_lid, to_entity->template global_id<TO_DOM>(), pos[from_lid]++);
1563 const auto & context_ = run::context::instance();
1567 std::tuple_size<typename POLICY_TYPE::entity_types>::value,
1568 typename POLICY_TYPE::entity_types,
1572 const auto & to_cis_to_gis = context_.index_map(to_index_space);
1575 for(
auto from_id : entity_ids<FROM_DIM, FROM_DOM>()) {
1578 auto conn = out_conn.get_entities(from_id.entity(), count);
1580 std::vector<std::pair<size_t, id_t>> gids(count);
1581 std::transform(conn, conn + count, gids.begin(), [&](
auto id) {
1582 return std::make_pair(to_cis_to_gis.at(
id.entity()),
id);
1585 std::sort(gids.begin(), gids.end(), [](
auto a,
auto b) {
1586 return a.first < b.first;
1589 std::transform(gids.begin(), gids.end(), conn, [](
auto id_pair) {
1590 return id_pair.second;
1608 template<
size_t FROM_DOM,
1618 get_connectivity_(FROM_DOM, TO_DOM, FROM_DIM, TO_DIM);
1619 if(!out_conn.
empty()) {
1624 auto num_from_ent = num_entities_(FROM_DIM, FROM_DOM);
1625 auto num_to_ent = num_entities_(TO_DIM, FROM_DOM);
1628 connection_vector_t conns(num_from_ent);
1631 using visited_vec = std::vector<bool>;
1632 visited_vec visited(num_to_ent);
1634 size_t max_size = 1;
1644 for(
auto from_entity : entities<FROM_DIM, FROM_DOM>()) {
1646 id_t from_id = from_entity->template global_id<FROM_DOM>();
1647 id_vector_t & ents = conns[from_id.entity()];
1648 ents.reserve(max_size);
1654 id_vector_t from_verts(ep, ep + count);
1656 std::sort(from_verts.begin(), from_verts.end());
1659 for(
auto from_ent2 : entities<DIM, FROM_DOM>(from_entity)) {
1660 for(id_t to_id : entity_ids<TO_DIM, TO_DOM>(from_ent2)) {
1661 visited[to_id.entity()] =
false;
1666 for(
auto from_ent2 : entities<DIM, FROM_DOM>(from_entity)) {
1667 for(id_t to_id : entity_ids<TO_DIM, TO_DOM>(from_ent2)) {
1670 if(visited[to_id.entity()]) {
1674 visited[to_id.entity()] =
true;
1677 if(FROM_DIM == TO_DIM) {
1678 if(from_id != to_id) {
1679 ents.push_back(to_id);
1684 id_t * ep = c2.get_entities(to_id.entity(), count);
1687 id_vector_t to_verts(ep, ep + count);
1689 std::sort(to_verts.begin(), to_verts.end());
1694 if(std::includes(from_verts.begin(),
1698 ents.emplace_back(to_id);
1704 if(util::intersects(from_verts.begin(),
1708 ents.emplace_back(to_id);
1715 max_size = std::max(ents.size(), max_size);
1719 out_conn.
init(conns);
1731 template<
size_t DOM,
size_t FROM_DIM,
size_t TO_DIM>
1736 connectivity_t & out_conn = get_connectivity_(DOM, FROM_DIM, TO_DIM);
1739 if(!out_conn.
empty()) {
1746 static_assert(POLICY_TYPE::num_dimensions <= 3,
1747 "this needs to be re-thought for higher dimensions");
1749 if(get_connectivity_(DOM, POLICY_TYPE::num_dimensions, 0).empty()) {
1751 !get_connectivity_(DOM, POLICY_TYPE::num_dimensions - 1, 0).empty(),
1752 " need at least edges(2d)/faces(3) -> vertex connectivity");
1756 POLICY_TYPE::num_dimensions - 1,
1757 POLICY_TYPE::num_dimensions>();
1759 transpose<DOM, DOM, 0, POLICY_TYPE::num_dimensions - 1>();
1763 POLICY_TYPE::num_dimensions,
1765 POLICY_TYPE::num_dimensions - 1>();
1769 if(num_entities_(FROM_DIM, DOM) == 0) {
1770 if(get_connectivity_(DOM, FROM_DIM + 1, 0).empty())
1771 build_connectivity<DOM, FROM_DIM, POLICY_TYPE::num_dimensions>();
1773 build_connectivity<DOM, FROM_DIM, FROM_DIM + 1>();
1776 if(num_entities_(TO_DIM, DOM) == 0) {
1777 if(get_connectivity_(DOM, TO_DIM + 1, 0).empty())
1778 build_connectivity<DOM, TO_DIM, POLICY_TYPE::num_dimensions>();
1780 build_connectivity<DOM, TO_DIM, TO_DIM + 1>();
1783 if(num_entities_(FROM_DIM, DOM) == 0 && num_entities_(TO_DIM, DOM) == 0) {
1789 if(FROM_DIM < TO_DIM) {
1791 transpose<DOM, DOM, FROM_DIM, TO_DIM>();
1794 if(FROM_DIM == 0 && TO_DIM == 0) {
1798 intersect<DOM, DOM, FROM_DIM, TO_DIM, POLICY_TYPE::num_dimensions>();
1804 intersect<DOM, DOM, FROM_DIM, TO_DIM, 0>();
1819 template<
size_t FROM_DOM,
1824 void compute_bindings_() {
1827 if(!get_connectivity_(TO_DOM, FROM_DOM, TO_DIM, FROM_DIM).empty())
1828 transpose<FROM_DOM, TO_DOM, FROM_DIM, TO_DIM>();
1831 else if(num_entities_(TO_DIM, TO_DOM) == 0)
1832 build_bindings<FROM_DOM, TO_DOM, TO_DIM>();
1846 template<
size_t FROM_DOM,
1850 typename =
typename std::enable_if<(FROM_DOM > TO_DOM)>::
type>
1851 void compute_bindings_() {
1854 compute_bindings_<TO_DOM, FROM_DOM, TO_DIM, FROM_DIM>();
1857 transpose<FROM_DOM, TO_DOM, FROM_DIM, TO_DIM>();
1871 template<
size_t FROM_DOM,
size_t TO_DOM,
size_t FROM_DIM,
size_t TO_DIM>
1876 compute_bindings_<0, TO_DOM, 0, FROM_DIM>();
1877 compute_bindings_<0, TO_DOM, 0, TO_DIM>();
1880 auto & trans_conn = get_connectivity_(TO_DOM, FROM_DOM, TO_DIM, FROM_DIM);
1881 if(!trans_conn.empty())
1882 transpose<FROM_DOM, TO_DOM, FROM_DIM, TO_DIM>();
1895 template<
size_t FROM_DOM,
size_t TO_DOM,
size_t FROM_DIM,
size_t TO_DIM>
1902 get_connectivity_(FROM_DOM, TO_DOM, FROM_DIM, TO_DIM);
1904 if(!out_conn.
empty())
1907 compute_bindings_<FROM_DOM, TO_DOM, FROM_DIM, TO_DIM>();
1920 template<
size_t FROM_DOM,
size_t TO_DOM,
size_t TO_DIM>
1921 void build_bindings() {
1927 static_assert(TO_DIM <= POLICY_TYPE::num_dimensions,
"invalid dimension");
1929 constexpr
auto num_dims = POLICY_TYPE::num_dimensions;
1930 constexpr
auto cell_dim = POLICY_TYPE::num_dimensions;
1933 using cell_type = entity_type<cell_dim, FROM_DOM>;
1935 using binding_type = entity_type<TO_DIM, TO_DOM>;
1938 auto & cell_storage =
1939 base_t::ms_->index_spaces[FROM_DOM][cell_dim]
1940 .template cast<domain_entity<FROM_DOM, cell_type>>();
1943 auto & binding_storage =
1944 base_t::ms_->index_spaces[TO_DOM][TO_DIM]
1945 .template cast<domain_entity<TO_DOM, binding_type>>();
1949 std::tuple_size<typename POLICY_TYPE::entity_types>::value,
1950 typename POLICY_TYPE::entity_types,
1955 auto entity_index_spaces =
1956 find_all_index_spaces_in_domain<POLICY_TYPE, FROM_DOM>();
1960 std::tuple_size<typename POLICY_TYPE::entity_types>::value,
1961 typename POLICY_TYPE::entity_types,
1967 base_t::ms_->topology[FROM_DOM][FROM_DOM];
1969 base_t::ms_->topology[FROM_DOM][TO_DOM];
1972 auto & context_ = run::context::instance();
1973 auto color = context_.color();
1974 const auto & cell_gis_to_cis = context_.reverse_index_map(cell_index_space);
1975 const auto & binding_gis_to_cis =
1976 context_.reverse_index_map(binding_index_space);
1981 using entity_map_t = std::decay_t<decltype(context_.index_map(0))>;
1982 std::map<size_t, entity_map_t *> entity_cis_to_mis;
1983 for(
int dim = 0; dim <= num_dims; ++dim) {
1984 entity_cis_to_mis[dim] = &context_.index_map(entity_index_spaces[dim]);
1989 const auto & reverse_intermediate_map =
1990 context_.reverse_intermediate_binding_map(TO_DIM, TO_DOM);
1992 auto has_intermediate_map = (!reverse_intermediate_map.empty());
1994 using simple_id_vector_t =
1995 typename std::decay_t<decltype(reverse_intermediate_map)>::key_type;
1999 std::array<id_t, 4096> new_binding_connection_ids;
2004 std::map<size_t, connection_vector_t> binding_to_entity_conn;
2006 auto key = [](
auto dom,
auto dim) {
2007 return POLICY_TYPE::num_dimensions * dom + dim;
2011 const auto num_cells = num_entities<cell_dim, FROM_DOM>();
2012 connection_vector_t cell_to_binding_conn(num_cells);
2015 size_t binding_counter{0};
2019 for(
auto & cell_itr : cell_gis_to_cis) {
2022 auto c = cell_itr.second;
2023 auto cell =
static_cast<cell_type *
>(cell_storage[c]);
2024 auto cell_id = cell->template global_id<FROM_DOM>();
2033 auto new_binding_connection_sizes = cell->create_bound_entities(FROM_DOM,
2039 new_binding_connection_ids.data());
2041 auto num_new_bindings = new_binding_connection_sizes.size();
2044 auto & this_cell_to_binding_conn = cell_to_binding_conn[c];
2045 this_cell_to_binding_conn.reserve(num_new_bindings);
2048 size_t new_binding_pos = 0;
2049 for(
auto num_connections : new_binding_connection_sizes) {
2060 uint32_t dim_flags = 0;
2061 uint32_t dom_flags = 0;
2062 size_t num_new_binding_vertices = 0;
2066 simple_id_vector_t connected_entities_mis;
2067 connected_entities_mis.reserve(num_connections + 1);
2068 connected_entities_mis.emplace_back(
2069 0, cell_dim, entity_cis_to_mis[cell_dim]->at(cell_id.entity()));
2074 id_vector_t connected_entities;
2075 connected_entities.reserve(num_connections);
2077 for(
size_t k = 0; k < num_connections; ++k) {
2080 auto connection_id = new_binding_connection_ids[new_binding_pos + k];
2081 auto dim = connection_id.dimension();
2082 auto dom = connection_id.domain();
2085 connected_entities.push_back(connection_id);
2089 if(dom == FROM_DOM) {
2090 dim_flags |= 1U << dim;
2091 num_new_binding_vertices += dim == 0 ? 1 : 0;
2093 auto entity_cis = connection_id.entity();
2094 auto entity_mis = entity_cis_to_mis[dim]->at(entity_cis);
2095 connected_entities_mis.emplace_back(dom, dim, entity_mis);
2099 dom_flags |= 1U << dim;
2110 size_t new_binding_id_cis;
2111 if(has_intermediate_map) {
2114 connected_entities_mis.begin(), connected_entities_mis.end());
2116 auto new_binding_id_gis =
2117 reverse_intermediate_map.at(connected_entities_mis);
2119 new_binding_id_cis = binding_gis_to_cis.at(new_binding_id_gis);
2123 new_binding_id_cis = binding_counter;
2128 auto new_binding_id =
2129 id_t::make<TO_DIM, TO_DOM>(new_binding_id_cis,
color);
2132 this_cell_to_binding_conn.push_back(new_binding_id);
2135 auto ent = POLICY_TYPE::template create_entity<TO_DOM, TO_DIM>(
2136 this, num_new_binding_vertices, new_binding_id);
2143 for(
auto connection_id : connected_entities) {
2146 auto dim = connection_id.dimension();
2147 auto dom = connection_id.domain();
2151 auto map_key = key(dom, dim);
2152 auto bit = binding_to_entity_conn.find(map_key);
2153 if(bit == binding_to_entity_conn.end()) {
2154 bit = binding_to_entity_conn
2155 .emplace(std::make_pair(map_key, connection_vector_t{}))
2160 auto & this_binding_to_entities = bit->second;
2161 if(this_binding_to_entities.size() <= new_binding_id_cis)
2162 this_binding_to_entities.resize(new_binding_id_cis + 1);
2163 this_binding_to_entities[new_binding_id_cis].push_back(connection_id);
2172 new_binding_pos += num_connections;
2178 get_connectivity_(FROM_DOM, TO_DOM, cell_dim, TO_DIM)
2179 .init(std::move(cell_to_binding_conn));
2182 for(
const auto & binding_pair : binding_to_entity_conn) {
2184 auto & binding_to_entity = binding_pair.second;
2186 const auto & first = binding_to_entity.at(0).at(0);
2187 auto dom = first.domain();
2188 auto dim = first.dimension();
2190 get_connectivity_(TO_DOM, dom, TO_DIM, dim)
2191 .init(std::move(binding_to_entity));
2204 size_t to_dim)
const {
2205 flog_assert(from_domain < POLICY_TYPE::num_domains,
"invalid from domain");
2206 flog_assert(to_domain < POLICY_TYPE::num_domains,
"invalid to domain");
2207 return base_t::ms_->topology[from_domain][to_domain].get(from_dim, to_dim);
2219 flog_assert(from_domain < POLICY_TYPE::num_domains,
"invalid from domain");
2220 flog_assert(to_domain < POLICY_TYPE::num_domains,
"invalid to domain");
2221 return base_t::ms_->topology[from_domain][to_domain].get(from_dim, to_dim);
2233 template<
size_t FROM_DOM,
size_t TO_DOM,
size_t FROM_DIM>
2235 return base_t::ms_->topology[FROM_DOM][TO_DOM].template get<FROM_DIM>(
2249 template<
size_t FROM_DOM,
size_t TO_DOM,
size_t FROM_DIM,
size_t TO_DIM>
2251 return base_t::ms_->topology[FROM_DOM][TO_DOM]
2252 .template get<FROM_DIM, TO_DIM>();
2261 get_connectivity_(
size_t domain,
size_t from_dim,
size_t to_dim)
const {
2262 return get_connectivity_(domain, domain, from_dim, to_dim);
2271 get_connectivity_(
size_t domain,
size_t from_dim,
size_t to_dim) {
2272 return get_connectivity_(domain, domain, from_dim, to_dim);
contains methods and data about the mesh topology that do not depend on type parameterization, e.g: entity types, domains, etc.
Definition: types.hh:43
compute_connectivity provides static recursion to process connectivity computation of mesh entity typ...
Definition: utils.hh:358
Definition: typeify.hh:31
offset represents an offset range (a start index plus a count of elements) in a single uint64_t...
Definition: offset.hh:34
bool empty() const
True if the connectivity is empty (hasn't been populated).
Definition: connectivity.hh:220
#define flog_assert(test, message)
Definition: flog.hh:411
std::string type()
Definition: demangle.hh:44
void init(const connection_vector_t &cv)
Definition: connectivity.hh:81
compute_bindings provides static recursion to process binding computation of mesh entity types...
Definition: utils.hh:416
Definition: storage.hh:41
domain_entity is a simple wrapper to mesh entity that associates with its a domain id ...
Definition: array_buffer.hh:24
const auto & get_entities() const
Get the to id's vector.
Definition: connectivity.hh:165
typename std::tuple_element< 2, pair_ >::type type
Definition: utils.hh:101
Definition: interface.hh:112
size_t color()
Definition: execution.hh:326
#define FLECSI_MEMBER_CHECKER(X)
Macro to check if the object has a member _*.
Definition: static_verify.hh:27
connectivity_t provides basic connectivity information in a compressed storage format.
Definition: connectivity.hh:41
Definition: interface.hh:154
Check if the object is a tuple.
Definition: static_verify.hh:52
Definition: control.hh:31