openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
SF_mesh_io_emi.h
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 
26 #if WITH_EMI_MODEL
27 
28 #ifndef _SF_MESH_IO_EMI
29 #define _SF_MESH_IO_EMI
30 
31 #include "SF_mesh_io.h"
32 #include "petsc_utils.h"
33 
34 namespace SF {
35 
51 template<class T, class S>
52 inline void insert_points_ptsData_to_dof( const meshdata<T, S> & mesh_original, meshdata<T, S> & mesh,
53  const SF_nbr numbering,
55  hashmap::unordered_map<T,T> & vertex2ptsdata,
56  hashmap::unordered_map<T,T> & dof2ptsData)
57 {
58  MPI_Comm comm = mesh_original.comm;
59 
60  const SF::vector<mesh_int_t> & rnod_original = mesh_original.get_numbering(numbering);
62  g2l_orig.reserve(rnod_original.size());
63  for(size_t i=0; i<rnod_original.size(); i++){
64  g2l_orig[rnod_original[i]] = i;
65  }
66 
67  const SF::vector<mesh_int_t> & rnod = mesh.get_numbering(numbering);
70  g2l.reserve(rnod.size());
71  l2g.reserve(rnod.size());
72  for(size_t i=0; i<rnod.size(); i++){
73  g2l[rnod[i]] = i;
74  l2g[i] = rnod[i];
75  }
76 
77  mesh_int_t gmax = global_max(rnod, comm);
78  mesh.g_numpts = gmax+1;
79 
80  mesh.xyz.resize(mesh.l_numpts*3);
81 
82  for(size_t eidx = 0; eidx < mesh.l_numelem; eidx++) {
83  T tag = mesh.tag[eidx];
84 
85  for (int n = mesh.dsp[eidx]; n < mesh.dsp[eidx+1];n++)
86  {
87  T g = l2g[mesh.con[n]];
88  T old_g = dof2vertex[g];
89 
90  const auto local_idx = g2l[g];
91  const auto orig_idx = g2l_orig[old_g];
92 
93  mesh.xyz[local_idx*3+0] = mesh_original.xyz[orig_idx*3+0];
94  mesh.xyz[local_idx*3+1] = mesh_original.xyz[orig_idx*3+1];
95  mesh.xyz[local_idx*3+2] = mesh_original.xyz[orig_idx*3+2];
96  dof2ptsData[g] = vertex2ptsdata[old_g];
97 
98  if (!std::isfinite(mesh.xyz[local_idx*3+0]) ||
99  !std::isfinite(mesh.xyz[local_idx*3+1]) ||
100  !std::isfinite(mesh.xyz[local_idx*3+2]))
101  {
102  printf("NaN detected in coordinates of the EMI mesh after decoupling interfaces on EMI mesh while recording pts data on the EMI mesh, on Tag=%lld\n",
103  static_cast<long long>(tag));
104  EXIT(EXIT_FAILURE);
105  }
106  }
107  }
108 }
109 
125 template<class T, class S>
126 inline void insert_points_to_surface_mesh( const meshdata<T, S> & mesh_original, meshdata<T, S> & surfmesh,
127  const SF_nbr numbering,
129  hashmap::unordered_set<int> & extra_tags,
130  SF::vector<mesh_int_t> & elemTag_surface)
131 {
132  MPI_Comm comm = mesh_original.comm;
133 
134  const SF::vector<mesh_int_t> & rnod_original = mesh_original.get_numbering(numbering);
136  g2l_orig.reserve(rnod_original.size());
137  for(size_t i=0; i<rnod_original.size(); i++){
138  g2l_orig[rnod_original[i]] = i;
139  }
140 
141  const SF::vector<mesh_int_t> & rnod_surf = surfmesh.get_numbering(numbering);
142 
145  g2l_surf.reserve(rnod_surf.size());
146  l2g_surf.reserve(rnod_surf.size());
147  for(size_t i=0; i<rnod_surf.size(); i++){
148  g2l_surf[rnod_surf[i]] = i;
149  l2g_surf[i] = rnod_surf[i];
150  }
151 
152  mesh_int_t gmax = global_max(rnod_surf, comm);
153  surfmesh.g_numpts = gmax+1;
154 
155  surfmesh.xyz.resize(surfmesh.l_numpts*3);
156 
157  elemTag_surface.resize(surfmesh.l_numelem);
158  for(size_t eidx = 0; eidx < surfmesh.l_numelem; eidx++) {
159  T tag = surfmesh.tag[eidx];
160  elemTag_surface[eidx] = 1; // assigned 1 for for extracellular located on extracellular side
161  if(extra_tags.find(tag) == extra_tags.end())
162  elemTag_surface[eidx] = 2; // assigned 2 for for intracellular located on myocyte
163 
164  for (int n = surfmesh.dsp[eidx]; n < surfmesh.dsp[eidx+1];n++)
165  {
166  T g = l2g_surf[surfmesh.con[n]];
167  T old_g = dof2vertex[g];
168 
169  const auto local_idx = g2l_surf[g];
170  const auto orig_idx = g2l_orig[old_g];
171 
172  surfmesh.xyz[local_idx*3+0] = mesh_original.xyz[orig_idx*3+0];
173  surfmesh.xyz[local_idx*3+1] = mesh_original.xyz[orig_idx*3+1];
174  surfmesh.xyz[local_idx*3+2] = mesh_original.xyz[orig_idx*3+2];
175 
176  if (!std::isfinite(surfmesh.xyz[local_idx*3+0]) ||
177  !std::isfinite(surfmesh.xyz[local_idx*3+1]) ||
178  !std::isfinite(surfmesh.xyz[local_idx*3+2]))
179  {
180  fprintf(stderr, "NaN detected in the surface mesh coordinates! on tag=%lld \n",
181  static_cast<long long>(tag));
182  exit(1);
183  }
184  }
185  }
186 }
187 
199 template<class T, class S>
200 inline void insert_points_to_surface_mesh( const meshdata<T, S> & mesh_original, meshdata<T, S> & surfmesh,
201  const SF_nbr numbering,
203 {
204  MPI_Comm comm = mesh_original.comm;
205 
206  const SF::vector<mesh_int_t> & rnod_original = mesh_original.get_numbering(numbering);
208  g2l_orig.reserve(rnod_original.size());
209  for(size_t i=0; i<rnod_original.size(); i++){
210  g2l_orig[rnod_original[i]] = i;
211  }
212 
213  const SF::vector<mesh_int_t> & rnod_surf = surfmesh.get_numbering(numbering);
214 
217  g2l_surf.reserve(rnod_surf.size());
218  l2g_surf.reserve(rnod_surf.size());
219  for(size_t i=0; i<rnod_surf.size(); i++){
220  g2l_surf[rnod_surf[i]] = i;
221  l2g_surf[i] = rnod_surf[i];
222  }
223 
224  mesh_int_t gmax = global_max(rnod_surf, comm);
225  surfmesh.g_numpts = gmax+1;
226 
227  surfmesh.xyz.resize(surfmesh.l_numpts*3);
228 
229  for(size_t eidx = 0; eidx < surfmesh.l_numelem; eidx++) {
230  T tag = surfmesh.tag[eidx];
231 
232  for (int n = surfmesh.dsp[eidx]; n < surfmesh.dsp[eidx+1];n++)
233  {
234  T g = l2g_surf[surfmesh.con[n]];
235  T old_g = dof2vertex[g];
236 
237  const auto local_idx = g2l_surf[g];
238  const auto orig_idx = g2l_orig[old_g];
239 
240  surfmesh.xyz[local_idx*3+0] = mesh_original.xyz[orig_idx*3+0];
241  surfmesh.xyz[local_idx*3+1] = mesh_original.xyz[orig_idx*3+1];
242  surfmesh.xyz[local_idx*3+2] = mesh_original.xyz[orig_idx*3+2];
243 
244  if (!std::isfinite(surfmesh.xyz[local_idx*3+0]) ||
245  !std::isfinite(surfmesh.xyz[local_idx*3+1]) ||
246  !std::isfinite(surfmesh.xyz[local_idx*3+2]))
247  {
248  fprintf(stderr, "NaN detected in the surface mesh coordinates! on tag=%lld \n",
249  static_cast<long long>(tag));
250  exit(1);
251  }
252  }
253  }
254 }
255 
256 }
257 #endif
258 #endif
opencarp::local_index_t mesh_int_t
Definition: SF_container.h:46
Functions related to mesh IO.
size_t size() const
The current size of the vector.
Definition: SF_vector.h:104
void resize(size_t n)
Resize a vector.
Definition: SF_vector.h:209
void reserve(size_t n)
Definition: hashmap.hpp:734
iterator find(const K &key)
Definition: hashmap.hpp:1096
Definition: dense_mat.hpp:34
T global_max(const vector< T > &vec, MPI_Comm comm)
Compute the global maximum of a distributed vector.
Definition: SF_network.h:156
SF_nbr
Enumeration encoding the different supported numberings.
Definition: SF_container.h:200