Feellgood
mesh.h
Go to the documentation of this file.
1 #ifndef mesh_h
2 #define mesh_h
3 
10 #include <cmath>
11 #include <algorithm>
12 #pragma GCC diagnostic push
13 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
14 #include <execution>
15 #pragma GCC diagnostic pop
16 
17 #include "triangle.h"
18 #include "node.h"
19 #include "tetra.h"
20 #include "settings.h"
21 
22 class BasicTri;
23 
24 namespace Mesh
25  {
27  using Edge = std::pair<int, int>;
28 
33 class mesh
34  {
35 public:
38  mesh(Settings &mySets ,
39  bool simplified = false )
40  : settings(mySets), volumeRegions(settings.paramTetra.size())
41  {
42  readMesh();
43  if (simplified)
44  { return; }
45  if (!controlTriangles())
46  { exit(1); }
47 
48  if (settings.verbose)
49  { std::cout << " reindexed\n"; }
50 
51  double xmin = minNodes(Nodes::IDX_X);
52  double xmax = maxNodes(Nodes::IDX_X);
53 
54  double ymin = minNodes(Nodes::IDX_Y);
55  double ymax = maxNodes(Nodes::IDX_Y);
56 
57  double zmin = minNodes(Nodes::IDX_Z);
58  double zmax = maxNodes(Nodes::IDX_Z);
59 
60  l = Eigen::Vector3d(xmax - xmin, ymax - ymin, zmax - zmin);
61  c = Eigen::Vector3d(0.5 * (xmax + xmin), 0.5 * (ymax + ymin), 0.5 * (zmax + zmin));
62 
63  // Find the longest axis of the sample.
64  Nodes::index long_axis;
65  if (l.x() > l.y())
66  {
67  if (l.x() > l.z())
68  long_axis = Nodes::IDX_X;
69  else
70  long_axis = Nodes::IDX_Z;
71  }
72  else
73  {
74  if (l.y() > l.z())
75  long_axis = Nodes::IDX_Y;
76  else
77  long_axis = Nodes::IDX_Z;
78  }
79  sortNodes(long_axis);
80 
81  totalMagVol = 0;
82  // Compute the per-region volumes and the total volume.
83  std::for_each(tet.begin(), tet.end(),
84  [this](const Tetra::Tet &te)
85  {
86  double vol_tet = te.calc_vol();
87  settings.paramTetra[te.idxPrm].volume += vol_tet;
88  if(isMagnetic(te))
89  totalMagVol += vol_tet;
90  });
91  vol = std::transform_reduce(settings.paramTetra.begin(), settings.paramTetra.end(), 0.0,
92  std::plus<>(), [](const Tetra::prm &region){ return region.volume; });
93 
94  // Build the list of tetrahedrons for each region.
95  std::for_each(tet.begin(), tet.end(), [this](const Tetra::Tet &te)
96  {
97  volumeRegions[te.idxPrm].push_back(te.idx);
98  });
99 
100  // Build the list of all the mesh edges.
101  edges.reserve(tet.size() * 6); // 6 (non-unique) edges per tetrahedron
102  std::for_each(tet.begin(), tet.end(),
103  [this](const Tetra::Tet &te)
104  {
105  for (int i = 0; i < 3; ++i)
106  {
107  for (int j = i + 1; j < 4; ++j)
108  { edges.push_back(std::minmax(te.ind[i], te.ind[j])); }
109  }
110  });
111  std::sort(EXEC_POL, edges.begin(), edges.end());
112  auto last = std::unique(EXEC_POL, edges.begin(), edges.end());
113  edges.erase(last, edges.end());
114  edges.shrink_to_fit(); // save memory, as this could be quite big
115  magNode.resize(node.size());
116  std::fill(magNode.begin(),magNode.end(),false);
117  std::for_each(tet.begin(),tet.end(),[this](Tetra::Tet &te)
118  {
119  if(isMagnetic(te))
120  {
121  magTet.push_back(te.idx);
122  for (int i=0;i<4;i++)
123  { magNode[te.ind[i]] = true; }
124  }
125  });
126 
127  for(unsigned int i=0;i<tri.size();i++)
128  {
129  if (isMagnetic(tri[i]) && !settings.paramTriangle[tri[i].idxPrm].suppress_charges)
130  { magTri.push_back(i); }
131  }
132 
133  if(settings.getFieldType() == R4toR3)
134  { setExtSpaceField(); }
135 
136  if (settings.absorb.enable)
137  { setAbsorbingEnds(); }
138  }
139 
141  mesh(const mesh &) = delete;
142 
144  mesh &operator=(const mesh &) = delete;
145 
147  inline int getNbNodes(void) const { return node.size(); }
148 
150  inline int getNbTris(void) const { return tri.size(); }
151 
153  inline int getNbTets(void) const { return tet.size(); }
154 
156  inline const Eigen::Vector3d getNode_p(const int i) const { return node[i].p; }
157 
159  inline const Eigen::Vector3d getNode_u(const int i) const { return node[i].get_u(Nodes::NEXT); }
160 
162  inline const Eigen::Vector3d getNode_v(const int i) const { return node[i].get_v(Nodes::NEXT); }
163 
165  inline double getProj_ep(const int i) const {return node[i].proj_ep();}
166 
168  inline double getProj_eq(const int i) const {return node[i].proj_eq();}
169 
171  inline void set_node_u0(const int i, const Eigen::Vector3d &val)
172  { node[i].d[Nodes::CURRENT].u = val; }
173 
175  inline void set_node_zero_v(const int i) { node[i].d[Nodes::NEXT].v.setZero(); }
176 
178  void infos(void) const;
179 
181  inline void setBasis(const double r)
182  {
183  std::for_each(EXEC_POL, node.begin(), node.end(),
184  [&r](Nodes::Node &nod) { nod.setBasis(r); });
185  }
186 
188  inline void updateNode(const int i, const double vp, const double vq, const double dt)
189  { node[i].make_evol(vp, vq, dt); }
190 
192  inline void evolution(void)
193  {
194  std::for_each(EXEC_POL, node.begin(), node.end(),
195  [](Nodes::Node &nod) { nod.evolution(); });
196  }
197 
199  Eigen::Vector3d c;
200 
202  Eigen::Vector3d l;
203 
205  double vol;
206 
208  double totalMagVol;
209 
211  std::vector<Triangle::Tri> tri;
212 
214  std::vector<Tetra::Tet> tet;
215 
219  double readSol(bool VERBOSE ,
220  const std::string& fileName );
221 
224  inline void init_distrib()
225  {
226  for (int nodeIdx = 0; nodeIdx < int(node.size()); ++nodeIdx)
227  {
228  Nodes::Node &n = node[nodeIdx];
229  n.d[Nodes::NEXT].phi = 0.;
230  n.d[Nodes::NEXT].phiv = 0.;
231 
232  // A non-magnetic node's magnetization is a vector of NAN.
233  if (!magNode[nodeIdx])
234  {
235  n.d[Nodes::CURRENT].u = Eigen::Vector3d(NAN, NAN, NAN);
236  n.d[Nodes::NEXT].u = n.d[Nodes::CURRENT].u;
237  continue;
238  }
239 
240  // If the initial magnetization depends only on the node position, we do not need to
241  // build the list of region names.
242  if (settings.getMagType() == POSITION_ONLY)
243  {
244  n.d[Nodes::CURRENT].u = settings.getMagnetization(n.p);
245  n.d[Nodes::NEXT].u = n.d[Nodes::CURRENT].u;
246  continue;
247  }
248 
249  // Get the list of region indices this node belongs to.
250  std::set<int> nodeRegions;
251  // skip region 0 (__default__) which should be empty
252  for (size_t regIdx = 1; regIdx < volumeRegions.size(); ++regIdx)
253  {
254  const std::vector<int> &regionTetras = volumeRegions[regIdx];
255  bool node_in_region = std::any_of(EXEC_POL,
256  regionTetras.begin(), regionTetras.end(),
257  [this, nodeIdx](const int tetIdx)
258  {
259  const Tetra::Tet &tetrahedron = tet[tetIdx];
260  for (int i = 0; i < Tetra::N; ++i) // node of tetrahedron tetIdx
261  {
262  if (tetrahedron.ind[i] == nodeIdx)
263  { return true; }
264  }
265  return false;
266  });
267  if (node_in_region)
268  { nodeRegions.insert(regIdx); }
269  }
270 
271  // Get the list of region names this node belongs to.
272  std::vector<std::string> region_names;
273  region_names.resize(nodeRegions.size());
274  std::transform(nodeRegions.begin(), nodeRegions.end(), region_names.begin(),
275  [this](const int regIdx){ return settings.paramTetra[regIdx].regName; });
276 
277  n.d[Nodes::CURRENT].u = settings.getMagnetization(n.p, region_names);
278  n.d[Nodes::NEXT].u = n.d[Nodes::CURRENT].u;
279  }
280  }
281 
288  double thiele(const int region ) const;
289 
293  double avg(const std::function<double(Nodes::Node, Nodes::index)>& getter ,
294  Nodes::index d ,
295  int region = -1 ) const;
296 
298  double max_angle() const
299  {
300  double min_dot_product = std::transform_reduce(EXEC_POL, edges.begin(), edges.end(), 1.0,
301  [](const double a, const double b){ return std::min(a, b); },
302  [this](const Edge &edge)
303  {
304  Eigen::Vector3d m1 = getNode_u(edge.first);
305  Eigen::Vector3d m2 = getNode_u(edge.second);
306  return m1.dot(m2);
307  });
308  return std::acos(min_dot_product);
309  }
310 
317  void savesol(const int precision ,
318  const std::string& fileName ,
319  const std::string &metadata ,
320  bool withSpinAcc ,
321  std::vector<Eigen::Vector3d> &s ) const;
322 
325  inline void set(const int i ,
326  const std::function<void(Nodes::Node &, const double)>& what_to_set ,
327  const double val )
328  { what_to_set(node[i], val); }
329 
331  inline int getNodeIndex(const int i) const { return node_index[i]; }
332 
334  inline bool isMagnetic(const Tetra::Tet &t) const
335  { return (settings.paramTetra[t.idxPrm].Ms > 0); }
336 
338  inline bool isMagnetic(const Triangle::Tri &f)
339  { return (magNode[f.ind[0]] && magNode[f.ind[1]] && magNode[f.ind[2]]); }
340 
352  bool controlTriangles();
353 
356  std::vector<Edge> edges;
357 
361  std::vector<bool> magNode;
362 
364  std::vector<int> magTet;
365 
370  std::vector<int> magTri;
371 
373  std::vector< Eigen::Matrix<double,Nodes::DIM,Tetra::NPI> > extSpaceField;
374 
375 private:
378 
381  std::vector<Nodes::Node> node;
382 
388  std::vector<int> node_index;
389 
391  std::vector<std::vector<int>> volumeRegions;
392 
395  void checkMeshFile();
396 
398  void readNodes();
399 
401  void readTetraedrons();
402 
404  void readTriangles();
405 
407  void readMesh();
408 
410  double doOnNodes(const double init_val ,
411  const Nodes::index coord ,
412  const std::function<bool(double, double)>& whatToDo ) const;
413 
415  inline double minNodes(const Nodes::index coord ) const
416  {
417  return doOnNodes(__DBL_MAX__, coord, [](const double a, const double b)
418  { return a < b; });
419  }
420 
422  inline double maxNodes(const Nodes::index coord ) const
423  {
424  return doOnNodes(__DBL_MIN__, coord, [](const double a, const double b)
425  { return a > b; });
426  }
427 
430  void sortNodes(Nodes::index long_axis );
431 
434  bool diffTriHandler(const size_t inf, const size_t sup, const std::vector<BasicTri> &allTriCtnr,
435  std::vector<size_t> &indNodTriToAdd, std::vector<std::pair<int,int>> &regsTriToAdd);
436 
438  bool assertNoErrInTriangle(const int nbSurfTri, const int nbTetraFaces,
439  const std::pair<int,int> pairIdVolRegs, const int idSurfReg);
440 
444  double surface(std::vector<int> &triIndices) const;
445 
448  void setExtSpaceField();
449 
453  void setAbsorbingEnds();
454  }; // end class mesh
455  } // end namespace Mesh
456 #endif
Definition: mesh.cpp:14
Definition: mesh.h:34
const Eigen::Vector3d getNode_p(const int i) const
Definition: mesh.h:156
Eigen::Vector3d l
Definition: mesh.h:202
std::vector< int > magTet
Definition: mesh.h:364
std::vector< Eigen::Matrix< double, Nodes::DIM, Tetra::NPI > > extSpaceField
Definition: mesh.h:373
bool isMagnetic(const Tetra::Tet &t) const
Definition: mesh.h:334
const Eigen::Vector3d getNode_u(const int i) const
Definition: mesh.h:159
Eigen::Vector3d c
Definition: mesh.h:199
void init_distrib()
Definition: mesh.h:224
void set_node_zero_v(const int i)
Definition: mesh.h:175
void set_node_u0(const int i, const Eigen::Vector3d &val)
Definition: mesh.h:171
void readMesh()
Definition: read.cpp:12
double max_angle() const
Definition: mesh.h:298
std::vector< Edge > edges
Definition: mesh.h:356
int getNbTris(void) const
Definition: mesh.h:150
int getNbNodes(void) const
Definition: mesh.h:147
std::vector< Nodes::Node > node
Definition: mesh.h:381
double minNodes(const Nodes::index coord) const
Definition: mesh.h:415
std::vector< bool > magNode
Definition: mesh.h:361
mesh(Settings &mySets, bool simplified=false)
Definition: mesh.h:38
std::vector< std::vector< int > > volumeRegions
Definition: mesh.h:391
Settings & settings
Definition: mesh.h:377
int getNodeIndex(const int i) const
Definition: mesh.h:331
bool isMagnetic(const Triangle::Tri &f)
Definition: mesh.h:338
double getProj_ep(const int i) const
Definition: mesh.h:165
std::vector< Tetra::Tet > tet
Definition: mesh.h:214
double maxNodes(const Nodes::index coord) const
Definition: mesh.h:422
int getNbTets(void) const
Definition: mesh.h:153
void sortNodes(Nodes::index long_axis)
Definition: mesh.cpp:334
std::vector< int > magTri
Definition: mesh.h:370
void set(const int i, const std::function< void(Nodes::Node &, const double)> &what_to_set, const double val)
Definition: mesh.h:325
mesh(const mesh &)=delete
void setBasis(const double r)
Definition: mesh.h:181
void evolution(void)
Definition: mesh.h:192
double totalMagVol
Definition: mesh.h:208
const Eigen::Vector3d getNode_v(const int i) const
Definition: mesh.h:162
std::vector< int > node_index
Definition: mesh.h:388
double getProj_eq(const int i) const
Definition: mesh.h:168
void updateNode(const int i, const double vp, const double vq, const double dt)
Definition: mesh.h:188
bool controlTriangles()
Definition: mesh.cpp:121
double vol
Definition: mesh.h:205
std::vector< Triangle::Tri > tri
Definition: mesh.h:211
mesh & operator=(const mesh &)=delete
Container for all the settings provided by the user, with conversions to/from YAML.
Definition: settings.h:71
int verbose
Definition: settings.h:134
std::vector< Tetra::prm > paramTetra
Definition: settings.h:210
Definition: tetra.h:135
Definition: triangle.h:109
int idxPrm
Definition: element.h:56
std::array< int, N > ind
Definition: element.h:53
std::pair< int, int > Edge
Definition: mesh.h:27
index
Definition: node.h:33
constexpr double a[N][NPI]
Definition: tetra.h:69
header to define struct Node
many settings to give some parameters to the solver, boundary conditions for the problem,...
@ R4toR3
Definition: settings.h:44
@ POSITION_ONLY
M(x, y, z)
Definition: settings.h:27
Definition: node.h:60
Eigen::Vector3d p
Definition: node.h:61
dataNode d[NB_DATANODE]
Definition: node.h:70
double phi
Definition: node.h:51
double phiv
Definition: node.h:52
Eigen::Vector3d u
Definition: node.h:49
Definition: tetra.h:88
namespace Tetra header containing Tet class, some constants, and integrales
contains namespace Triangle header containing Tri class, and some constants and a less_than operator ...