openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
sf_interface.cc
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // openCARP is an open cardiac electrophysiology simulator.
3 //
4 // Copyright (C) 2020 openCARP project
5 //
6 // This program is licensed under the openCARP Academic Public License (APL)
7 // v1.0: You can use and redistribute it and/or modify it in non-commercial
8 // academic environments under the terms of APL as published by the openCARP
9 // project v1.0, or (at your option) any later version. Commercial use requires
10 // a commercial license (info@opencarp.org).
11 //
12 // This program is distributed without any warranty; see the openCARP APL for
13 // more details.
14 //
15 // You should have received a copy of the openCARP APL along with this program
16 // and can find it online: http://www.opencarp.org/license
17 // ----------------------------------------------------------------------------
18 
27 #include "petsc_utils.h" // TODO: for EXIT
28 #include "sf_interface.h"
29 #include "sim_utils.h"
30 
31 namespace opencarp {
32 
33 sf_mesh & get_mesh(const mesh_t gt)
34 {
35  auto it = user_globals::mesh_reg.find(gt);
36  if(it == user_globals::mesh_reg.end()) {
37  log_msg(0,5,0, "%s error: mesh of type \"%s\" not found! Aborting!",
38  __func__, get_mesh_type_name(gt));
39  EXIT(EXIT_FAILURE);
40  }
41 
42  return it->second;
43 }
44 
45 const char*
47  switch(t) {
48  case intra_elec_msh: return "Intracellular Electric";
49  case extra_elec_msh: return "Extracellular Electric";
50  case eikonal_msh: return "Eikonal";
51  case elasticity_msh: return "Elasticity";
52  case fluid_msh: return "Fluid";
53  case reference_msh: return "Reference";
54  case phie_recv_msh: return "Phie Recovery";
55  default: return NULL;
56  }
57 }
58 
59 bool mesh_is_registered(const mesh_t gt)
60 {
61  return user_globals::mesh_reg.find(gt) != user_globals::mesh_reg.end();
62 }
63 
65 register_scattering(const int from, const int to, const SF::SF_nbr nbr, const int dpn)
66 {
67  int rank = get_rank();
68 
69  sf_mesh & from_mesh = get_mesh(mesh_t(from));
70  // we compute the petsc numbering of only the algebraicly distributed nodes
71  const SF::vector<mesh_int_t> & from_alg_nod = from_mesh.pl.algebraic_nodes();
72  const SF::vector<mesh_int_t> & from_nodal_nbr = from_mesh.get_numbering(nbr);
73  SF::scattering* ret = NULL;
74  SF::quadruple<int> spec = {from, to, nbr, dpn};
75 
76  if(to != ALG_TO_NODAL) {
77  sf_mesh & to_mesh = get_mesh(mesh_t(to));
78  // we set up the inter-domain index mapping in the registry map_reg
80  SF::inter_domain_mapping(from_mesh, to_mesh, nbr, idx_map);
81 
82  SF::vector<mesh_int_t> to_numbering(from_alg_nod.size());
83  SF::vector<mesh_int_t> from_numbering(from_alg_nod.size());
84  int err = 0;
85 
86  for(size_t i=0; i<from_alg_nod.size(); i++) {
87  mesh_int_t from_idx = from_nodal_nbr[from_alg_nod[i]];
88  mesh_int_t to_idx = idx_map.forward_map(from_idx);
89 
90  if(to_idx < 0) {
91  err++;
92  break;
93  }
94 
95  from_numbering[i] = from_idx;
96  to_numbering[i] = to_idx;
97  }
98 
99  if(get_global(err, MPI_SUM)) {
100  log_msg(0,5,0, "%s error: Bad inter-domain mapping. Aborting!", __func__);
101  EXIT(1);
102  }
103 
104  ret = user_globals::scatter_reg.register_scattering(spec, from_mesh.pl.algebraic_layout(),
105  to_mesh.pl.algebraic_layout(), from_numbering, to_numbering, rank, dpn);
106 
107  }
108  else {
109  const SF::vector<mesh_int_t> & nodal_layout = from_mesh.pl.layout();
110  SF::vector<mesh_int_t> to_numbering(from_nodal_nbr.size());
111 
112  SF::interval(to_numbering, nodal_layout[rank], nodal_layout[rank+1]);
113 
114  ret = user_globals::scatter_reg.register_scattering(spec, from_mesh.pl.algebraic_layout(),
115  nodal_layout, from_nodal_nbr, to_numbering, rank, dpn);
116  }
117 
118  return ret;
119 }
120 
121 SF::scattering* get_scattering(const int from, const int to, const SF::SF_nbr nbr, const int dpn)
122 {
123  SF::quadruple<int> spec = {from, to, int(nbr), dpn};
125 
126  if(sc == NULL)
127  return register_scattering(from, to, nbr, dpn);
128  else
129  return sc;
130 }
131 
132 bool have_scattering(const int from, const int to, const SF::SF_nbr nbr, const int dpn)
133 {
134  SF::quadruple<int> spec = {from, to, int(nbr), dpn};
136 
137  return sc != NULL;
138 }
139 
141 register_permutation(const int mesh_id, const int perm_id, const int dpn)
142 {
143  sf_mesh & mesh = get_mesh(mesh_t(mesh_id));
144  const SF::vector<mesh_int_t> & petsc_nbr = mesh.get_numbering(SF::NBR_PETSC);
145  const SF::vector<mesh_int_t> & alg_nod = mesh.pl.algebraic_nodes();
146  SF::quadruple<int> spec = {mesh_id, perm_id, 0, dpn};
147 
148  switch(perm_id) {
149  case PETSC_TO_CANONICAL:
150  {
151  const SF::vector<mesh_int_t> & canon_nbr = mesh.get_numbering(SF::NBR_SUBMESH);
152  SF::vector<mesh_int_t> petsc_alg_nod(alg_nod.size()), canon_alg_nod(alg_nod.size());
153 
154  for(size_t i=0; i<alg_nod.size(); i++)
155  {
156  petsc_alg_nod[i] = petsc_nbr[alg_nod[i]];
157  canon_alg_nod[i] = canon_nbr[alg_nod[i]];
158  }
159 
160  return user_globals::scatter_reg.register_permutation(spec, petsc_alg_nod, canon_alg_nod,
161  mesh.g_numpts, mesh.g_numpts, dpn);
162  }
163 
165  {
167  const SF::vector<mesh_int_t> & elem_layout = mesh.epl.algebraic_layout();
168  const int rank = get_rank();
169 
170  SF::vector<mesh_int_t> petsc_nod(canon_nbr.size()), canon_nod(canon_nbr.size());
171 
172  for(size_t i=0; i<canon_nbr.size(); i++)
173  {
174  petsc_nod[i] = elem_layout[rank] + i;
175  canon_nod[i] = canon_nbr[i];
176  }
177 
178  return user_globals::scatter_reg.register_permutation(spec, petsc_nod, canon_nod,
179  mesh.g_numelem, mesh.g_numelem, dpn);
180  }
181 /*
182  case PETSC_TO_PT:
183  {
184  const SF::vector<mesh_int_t> & pt_nbr = mesh.get_numbering(SF::NBR_SOLVER);
185  SF::vector<mesh_int_t> petsc_alg_nod(alg_nod.size()), pt_alg_nod(alg_nod.size());
186 
187  for(size_t i=0; i<alg_nod.size(); i++)
188  {
189  petsc_alg_nod[i] = petsc_nbr[alg_nod[i]];
190  pt_alg_nod[i] = pt_nbr[alg_nod[i]];
191  }
192 
193  return user_globals::scatter_reg.register_permutation(spec, petsc_alg_nod, pt_alg_nod,
194  mesh.g_numpts, mesh.g_numpts, dpn);
195  }
196 */
197  default:
198  log_msg(0,5,0, "%s error: Unknown permutation id. Aborting!", __func__);
199  EXIT(1);
200  }
201 }
202 
204 get_permutation(const int mesh_id, const int perm_id, const int dpn)
205 {
206  SF::quadruple<int> spec = {mesh_id, perm_id, 0, dpn};
208 
209  if(sc == NULL)
210  return register_permutation(mesh_id, perm_id, dpn);
211  else
212  return sc;
213 }
214 
215 bool have_permutation(const int mesh_id, const int perm_id, const int dpn)
216 {
217  SF::quadruple<int> spec = {mesh_id, perm_id, 0, dpn};
219 
220  return sc != NULL;
221 }
222 
223 } // namespace opencarp
224 
SF::scattering * get_permutation(const int mesh_id, const int perm_id, const int dpn)
Get the PETSC to canonical permutation scattering for a given mesh and number of dpn.
The mesh storage class. It contains both element and vertex data.
Definition: SF_container.h:383
non_overlapping_layout< T > epl
element parallel layout
Definition: SF_container.h:418
vector< T > & get_numbering(SF_nbr nbr_type)
Get the vector defining a certain numbering.
Definition: SF_container.h:452
PETSc numbering of nodes.
Definition: SF_container.h:191
#define PETSC_TO_CANONICAL
Permute algebraic data from PETSC to canonical ordering.
Definition: sf_interface.h:74
scattering * register_permutation(const quadruple< int > spec, const vector< T > &nbr_a, const vector< T > &nbr_b, const size_t gsize_a, const size_t gsize_b, const short dpn)
Register a permutation scattering.
scattering * get_scattering(const quadruple< int > spec)
Access an previously registered scattering.
void interval(vector< T > &vec, size_t start, size_t end)
Create an integer interval between start and end.
Definition: SF_vector.h:350
overlapping_layout< T > pl
nodal parallel layout
Definition: SF_container.h:417
std::map< mesh_t, sf_mesh > mesh_reg
Registry for the different meshes used in a multi-physics simulation.
Definition: main.cc:46
const char * get_mesh_type_name(mesh_t t)
get a char* to the name of a mesh type
Definition: sf_interface.cc:46
mesh_t
The enum identifying the different meshes we might want to load.
Definition: sf_interface.h:58
SF_nbr
Enumeration encoding the different supported numberings.
Definition: SF_container.h:188
#define ELEM_PETSC_TO_CANONICAL
Permute algebraic element data from PETSC to canonical ordering.
Definition: sf_interface.h:76
scattering * register_scattering(const quadruple< int > spec, const vector< T > &layout_a, const vector< T > &layout_b, const vector< T > &idx_a, const vector< T > &idx_b, const int rank, const int dpn)
Register a scattering.
SF::scattering * get_scattering(const int from, const int to, const SF::SF_nbr nbr, const int dpn)
Get a scattering from the global scatter registry.
int mesh_int_t
Definition: SF_container.h:46
Submesh nodal numbering: The globally ascending sorted reference indices are reindexed.
Definition: SF_container.h:190
std::map< SF::quadruple< int >, SF::index_mapping< int > > map_reg
Registriy for the inter domain mappings.
Definition: main.cc:48
sf_mesh & get_mesh(const mesh_t gt)
Get a mesh by specifying the gridID.
Definition: sf_interface.cc:33
Submesh element numbering: The globally ascending sorted reference indices are reindexed.
Definition: SF_container.h:193
SF::scattering * register_permutation(const int mesh_id, const int perm_id, const int dpn)
Register a permutation between two orderings for a mesh.
#define ALG_TO_NODAL
Scatter algebraic to nodal.
Definition: sf_interface.h:72
bool have_scattering(const int from, const int to, const SF::SF_nbr nbr, const int dpn)
T get_global(T in, MPI_Op OP, MPI_Comm comm=PETSC_COMM_WORLD)
Do a global reduction on a variable.
Definition: basics.h:233
Interface to SlimFem.
void inter_domain_mapping(const meshdata< T, S > &mesh_a, const meshdata< T, S > &mesh_b, const SF_nbr snbr, index_mapping< T > &a_to_b)
Submesh index mapping between different domains/meshes.
size_t size() const
The current size of the vector.
Definition: SF_vector.h:104
void log_msg(FILE_SPEC out, int level, unsigned char flag, const char *fmt,...)
Definition: basics.cc:72
bool mesh_is_registered(const mesh_t gt)
check wheter a SF mesh is set
Definition: sf_interface.cc:59
bool have_permutation(const int mesh_id, const int perm_id, const int dpn)
size_t g_numpts
global number of points
Definition: SF_container.h:388
T forward_map(T idx) const
Map one index from a to b.
Definition: SF_container.h:252
size_t g_numelem
global number of elements
Definition: SF_container.h:386
SF::scattering * register_scattering(const int from, const int to, const SF::SF_nbr nbr, const int dpn)
Register a scattering between to grids, or between algebraic and nodal representation of data on the ...
Definition: sf_interface.cc:65
Simulator-level utility execution control functions.
int get_rank(MPI_Comm comm=PETSC_COMM_WORLD)
Definition: basics.h:276
SF::scatter_registry scatter_reg
Registry for the different scatter objects.
Definition: main.cc:44
Container for a PETSc VecScatter.