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 namespace Mesh
23  {
25  using Edge = std::pair<int, int>;
26 
31 class mesh
32  {
33 public:
36  mesh(Settings &mySets ,
37  bool simplified = false )
38  : paramTetra(mySets.paramTetra), volumeRegions(mySets.paramTetra.size())
39  {
40  readMesh(mySets);
41  if (simplified)
42  { return; }
43  if (!controlTriangles())
44  { exit(1); }
45 
46  if (mySets.verbose)
47  { std::cout << " reindexed\n"; }
48 
49  double xmin = minNodes(Nodes::IDX_X);
50  double xmax = maxNodes(Nodes::IDX_X);
51 
52  double ymin = minNodes(Nodes::IDX_Y);
53  double ymax = maxNodes(Nodes::IDX_Y);
54 
55  double zmin = minNodes(Nodes::IDX_Z);
56  double zmax = maxNodes(Nodes::IDX_Z);
57 
58  l = Eigen::Vector3d(xmax - xmin, ymax - ymin, zmax - zmin);
59  c = Eigen::Vector3d(0.5 * (xmax + xmin), 0.5 * (ymax + ymin), 0.5 * (zmax + zmin));
60 
61  // Find the longest axis of the sample.
62  Nodes::index long_axis;
63  if (l.x() > l.y())
64  {
65  if (l.x() > l.z())
66  long_axis = Nodes::IDX_X;
67  else
68  long_axis = Nodes::IDX_Z;
69  }
70  else
71  {
72  if (l.y() > l.z())
73  long_axis = Nodes::IDX_Y;
74  else
75  long_axis = Nodes::IDX_Z;
76  }
77  sortNodes(long_axis);
78 
79  totalMagVol = 0;
80  // Compute the per-region volumes and the total volume.
81  std::for_each(tet.begin(), tet.end(),
82  [this](const Tetra::Tet &te)
83  {
84  double vol_tet = te.calc_vol();
85  paramTetra[te.idxPrm].volume += vol_tet;
86  if(isMagnetic(te))
87  totalMagVol += vol_tet;
88  });
89  vol = std::transform_reduce(paramTetra.begin(), paramTetra.end(), 0.0,
90  std::plus<>(), [](const Tetra::prm &region){ return region.volume; });
91 
92  // Build the list of tetrahedrons for each region.
93  std::for_each(tet.begin(), tet.end(), [this](const Tetra::Tet &te)
94  {
95  volumeRegions[te.idxPrm].push_back(te.idx);
96  });
97 
98  // Build the list of all the mesh edges.
99  edges.reserve(tet.size() * 6); // 6 (non-unique) edges per tetrahedron
100  std::for_each(tet.begin(), tet.end(),
101  [this](const Tetra::Tet &te)
102  {
103  for (int i = 0; i < 3; ++i)
104  {
105  for (int j = i + 1; j < 4; ++j)
106  { edges.push_back(std::minmax(te.ind[i], te.ind[j])); }
107  }
108  });
109  std::sort(EXEC_POL, edges.begin(), edges.end());
110  auto last = std::unique(EXEC_POL, edges.begin(), edges.end());
111  edges.erase(last, edges.end());
112  edges.shrink_to_fit(); // save memory, as this could be quite big
113  magNode.resize(node.size());
114  std::fill(magNode.begin(),magNode.end(),false);
115  std::for_each(tet.begin(),tet.end(),[this](Tetra::Tet &te)
116  {
117  if(isMagnetic(te))
118  {
119  magTet.push_back(te.idx);
120  for (int i=0;i<4;i++)
121  { magNode[te.ind[i]] = true; }
122  }
123  });
124 
125  for(unsigned int i=0;i<tri.size();i++)
126  {
127  if (isMagnetic(tri[i]) && !mySets.paramTriangle[tri[i].idxPrm].suppress_charges)
128  { magTri.push_back(i); }
129  }
130 
131  if(mySets.getFieldType() == R4toR3)
132  { setExtSpaceField(mySets); }
133  }
134 
136  mesh(const mesh &) = delete;
137 
139  mesh &operator=(const mesh &) = delete;
140 
142  inline int getNbNodes(void) const { return node.size(); }
143 
145  inline int getNbTris(void) const { return tri.size(); }
146 
148  inline int getNbTets(void) const { return tet.size(); }
149 
151  inline const Eigen::Vector3d getNode_p(const int i) const { return node[i].p; }
152 
154  inline const Eigen::Vector3d getNode_u(const int i) const { return node[i].get_u(Nodes::NEXT); }
155 
157  inline const Eigen::Vector3d getNode_v(const int i) const { return node[i].get_v(Nodes::NEXT); }
158 
160  inline double getProj_ep(const int i) const {return node[i].proj_ep();}
161 
163  inline double getProj_eq(const int i) const {return node[i].proj_eq();}
164 
166  inline void set_node_u0(const int i, const Eigen::Vector3d &val)
167  { node[i].d[Nodes::CURRENT].u = val; }
168 
170  inline void set_node_zero_v(const int i) { node[i].d[Nodes::NEXT].v.setZero(); }
171 
173  void infos(void) const;
174 
176  inline void setBasis(const double r)
177  {
178  std::for_each(EXEC_POL, node.begin(), node.end(),
179  [&r](Nodes::Node &nod) { nod.setBasis(r); });
180  }
181 
183  inline void updateNode(const int i, const double vp, const double vq, const double dt)
184  { node[i].make_evol(vp*gamma0, vq*gamma0, dt); }
185 
187  inline void evolution(void)
188  {
189  std::for_each(EXEC_POL, node.begin(), node.end(),
190  [](Nodes::Node &nod) { nod.evolution(); });
191  }
192 
194  Eigen::Vector3d c;
195 
197  Eigen::Vector3d l;
198 
200  double vol;
201 
203  double totalMagVol;
204 
206  std::vector<Triangle::Tri> tri;
207 
209  std::vector<Tetra::Tet> tet;
210 
212  std::vector<Tetra::prm> &paramTetra;
213 
217  double readSol(bool VERBOSE ,
218  const std::string& fileName );
219 
222  inline void init_distrib(const Settings &mySets )
223  {
224  for (int nodeIdx = 0; nodeIdx < int(node.size()); ++nodeIdx)
225  {
226  Nodes::Node &n = node[nodeIdx];
227  n.d[Nodes::NEXT].phi = 0.;
228  n.d[Nodes::NEXT].phiv = 0.;
229 
230  // A non-magnetic node's magnetization is a vector of NAN.
231  if (!magNode[nodeIdx])
232  {
233  n.d[Nodes::CURRENT].u = Eigen::Vector3d(NAN, NAN, NAN);
234  n.d[Nodes::NEXT].u = n.d[Nodes::CURRENT].u;
235  continue;
236  }
237 
238  // If the initial magnetization depends only on the node position, we do not need to
239  // build the list of region names.
240  if (mySets.getMagType() == POSITION_ONLY)
241  {
242  n.d[Nodes::CURRENT].u = mySets.getMagnetization(n.p);
243  n.d[Nodes::NEXT].u = n.d[Nodes::CURRENT].u;
244  continue;
245  }
246 
247  // Get the list of region indices this node belongs to.
248  std::set<int> nodeRegions;
249  // skip region 0 (__default__) which should be empty
250  for (size_t regIdx = 1; regIdx < volumeRegions.size(); ++regIdx)
251  {
252  const std::vector<int> &regionTetras = volumeRegions[regIdx];
253  bool node_in_region = std::any_of(EXEC_POL,
254  regionTetras.begin(), regionTetras.end(),
255  [this, nodeIdx](const int tetIdx)
256  {
257  const Tetra::Tet &tetrahedron = tet[tetIdx];
258  for (int i = 0; i < Tetra::N; ++i) // node of tetrahedron tetIdx
259  {
260  if (tetrahedron.ind[i] == nodeIdx)
261  { return true; }
262  }
263  return false;
264  });
265  if (node_in_region)
266  { nodeRegions.insert(regIdx); }
267  }
268 
269  // Get the list of region names this node belongs to.
270  std::vector<std::string> region_names;
271  region_names.resize(nodeRegions.size());
272  std::transform(nodeRegions.begin(), nodeRegions.end(), region_names.begin(),
273  [this](const int regIdx){ return paramTetra[regIdx].regName; });
274 
275  n.d[Nodes::CURRENT].u = mySets.getMagnetization(n.p, region_names);
276  n.d[Nodes::NEXT].u = n.d[Nodes::CURRENT].u;
277  }
278  }
279 
286  double thiele(const int region ) const;
287 
291  double avg(const std::function<double(Nodes::Node, Nodes::index)>& getter ,
292  Nodes::index d ,
293  int region = -1 ) const;
294 
296  double max_angle() const
297  {
298  double min_dot_product = std::transform_reduce(EXEC_POL, edges.begin(), edges.end(), 1.0,
299  [](const double a, const double b){ return std::min(a, b); },
300  [this](const Edge &edge)
301  {
302  Eigen::Vector3d m1 = getNode_u(edge.first);
303  Eigen::Vector3d m2 = getNode_u(edge.second);
304  return m1.dot(m2);
305  });
306  return std::acos(min_dot_product);
307  }
308 
315  void savesol(const int precision ,
316  const std::string& fileName ,
317  const std::string &metadata ,
318  bool withSpinAcc ,
319  std::vector<Eigen::Vector3d> &s ) const;
320 
323  inline void set(const int i ,
324  const std::function<void(Nodes::Node &, const double)>& what_to_set ,
325  const double val )
326  { what_to_set(node[i], val); }
327 
329  inline int getNodeIndex(const int i) const { return node_index[i]; }
330 
332  inline bool isMagnetic(const Tetra::Tet &t) const { return (paramTetra[t.idxPrm].Ms > 0); }
333 
335  inline bool isMagnetic(const Triangle::Tri &f)
336  { return (magNode[f.ind[0]] && magNode[f.ind[1]] && magNode[f.ind[2]]); }
337 
346  bool controlTriangles();
347 
350  std::vector<Edge> edges;
351 
355  std::vector<bool> magNode;
356 
358  std::vector<int> magTet;
359 
364  std::vector<int> magTri;
365 
367  std::vector< Eigen::Matrix<double,Nodes::DIM,Tetra::NPI> > extSpaceField;
368 
369 private:
372  std::vector<Nodes::Node> node;
373 
379  std::vector<int> node_index;
380 
382  std::vector<std::vector<int>> volumeRegions;
383 
386  void checkMeshFile(const Settings &mySets );
387 
389  void readNodes(const Settings &mySets );
390 
392  void readTetraedrons(const Settings &mySets );
393 
395  void readTriangles(const Settings &mySets );
396 
398  void readMesh(const Settings &mySets );
399 
401  double doOnNodes(const double init_val ,
402  const Nodes::index coord ,
403  const std::function<bool(double, double)>& whatToDo ) const;
404 
406  inline double minNodes(const Nodes::index coord ) const
407  {
408  return doOnNodes(__DBL_MAX__, coord, [](const double a, const double b)
409  { return a < b; });
410  }
411 
413  inline double maxNodes(const Nodes::index coord ) const
414  {
415  return doOnNodes(__DBL_MIN__, coord, [](const double a, const double b)
416  { return a > b; });
417  }
418 
421  void sortNodes(Nodes::index long_axis );
422 
424  bool findErrInTriangle(const int nbSurfTri, const int nbTetraFaces,
425  const std::pair<int,int> pairIdVolRegs, const int idSurfReg);
426 
430  double surface(std::vector<int> &triIndices) const;
431 
434  void setExtSpaceField(Settings &s );
435  }; // end class mesh
436  } // end namespace Mesh
437 #endif
Definition: mesh.h:32
const Eigen::Vector3d getNode_p(const int i) const
Definition: mesh.h:151
Eigen::Vector3d l
Definition: mesh.h:197
std::vector< int > magTet
Definition: mesh.h:358
std::vector< Eigen::Matrix< double, Nodes::DIM, Tetra::NPI > > extSpaceField
Definition: mesh.h:367
bool isMagnetic(const Tetra::Tet &t) const
Definition: mesh.h:332
const Eigen::Vector3d getNode_u(const int i) const
Definition: mesh.h:154
Eigen::Vector3d c
Definition: mesh.h:194
void set_node_zero_v(const int i)
Definition: mesh.h:170
void set_node_u0(const int i, const Eigen::Vector3d &val)
Definition: mesh.h:166
double max_angle() const
Definition: mesh.h:296
std::vector< Edge > edges
Definition: mesh.h:350
int getNbTris(void) const
Definition: mesh.h:145
int getNbNodes(void) const
Definition: mesh.h:142
std::vector< Nodes::Node > node
Definition: mesh.h:372
double minNodes(const Nodes::index coord) const
Definition: mesh.h:406
std::vector< bool > magNode
Definition: mesh.h:355
void init_distrib(const Settings &mySets)
Definition: mesh.h:222
mesh(Settings &mySets, bool simplified=false)
Definition: mesh.h:36
std::vector< std::vector< int > > volumeRegions
Definition: mesh.h:382
int getNodeIndex(const int i) const
Definition: mesh.h:329
bool isMagnetic(const Triangle::Tri &f)
Definition: mesh.h:335
double getProj_ep(const int i) const
Definition: mesh.h:160
void readMesh(const Settings &mySets)
Definition: read.cpp:12
std::vector< Tetra::Tet > tet
Definition: mesh.h:209
double maxNodes(const Nodes::index coord) const
Definition: mesh.h:413
int getNbTets(void) const
Definition: mesh.h:148
void sortNodes(Nodes::index long_axis)
Definition: mesh.cpp:252
std::vector< int > magTri
Definition: mesh.h:364
void set(const int i, const std::function< void(Nodes::Node &, const double)> &what_to_set, const double val)
Definition: mesh.h:323
mesh(const mesh &)=delete
void setBasis(const double r)
Definition: mesh.h:176
void evolution(void)
Definition: mesh.h:187
double totalMagVol
Definition: mesh.h:203
const Eigen::Vector3d getNode_v(const int i) const
Definition: mesh.h:157
std::vector< int > node_index
Definition: mesh.h:379
std::vector< Tetra::prm > & paramTetra
Definition: mesh.h:212
double getProj_eq(const int i) const
Definition: mesh.h:163
void updateNode(const int i, const double vp, const double vq, const double dt)
Definition: mesh.h:183
bool controlTriangles()
Definition: mesh.cpp:121
double vol
Definition: mesh.h:200
std::vector< Triangle::Tri > tri
Definition: mesh.h:206
mesh & operator=(const mesh &)=delete
Container for all the settings provided by the user, with conversions to/from YAML.
Definition: settings.h:70
Eigen::Vector3d getMagnetization(const Eigen::Ref< const Eigen::Vector3d > p) const
Definition: settings.h:267
int verbose
Definition: settings.h:136
mag_exprType getMagType() const
Definition: settings.h:255
Definition: tetra.h:132
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:25
index
Definition: node.h:33
constexpr double a[N][NPI]
Definition: tetra.h:68
header to define struct Node
many settings to give some parameters to the solver, boundary conditions for the problem,...
@ R4toR3
Definition: settings.h:43
@ POSITION_ONLY
M(x, y, z)
Definition: settings.h:26
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:87
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 ...