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 "facette.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  : paramTetra(mySets.paramTetra), volumeRegions(mySets.paramTetra.size())
38  {
39  readMesh(mySets);
40  indexReorder();
41 
42  if (mySets.verbose)
43  { std::cout << " reindexed\n"; }
44 
45  double xmin = minNodes(Nodes::IDX_X);
46  double xmax = maxNodes(Nodes::IDX_X);
47 
48  double ymin = minNodes(Nodes::IDX_Y);
49  double ymax = maxNodes(Nodes::IDX_Y);
50 
51  double zmin = minNodes(Nodes::IDX_Z);
52  double zmax = maxNodes(Nodes::IDX_Z);
53 
54  l = Eigen::Vector3d(xmax - xmin, ymax - ymin, zmax - zmin);
55  c = Eigen::Vector3d(0.5 * (xmax + xmin), 0.5 * (ymax + ymin), 0.5 * (zmax + zmin));
56 
57  // Find the longest axis of the sample.
58  Nodes::index long_axis;
59  if (l.x() > l.y())
60  {
61  if (l.x() > l.z())
62  long_axis = Nodes::IDX_X;
63  else
64  long_axis = Nodes::IDX_Z;
65  }
66  else
67  {
68  if (l.y() > l.z())
69  long_axis = Nodes::IDX_Y;
70  else
71  long_axis = Nodes::IDX_Z;
72  }
73  sortNodes(long_axis);
74 
75  totalMagVol = 0;
76  // Compute the per-region volumes and the total volume.
77  std::for_each(tet.begin(), tet.end(),
78  [this](Tetra::Tet const &te)
79  {
80  double vol_tet = te.calc_vol();
81  paramTetra[te.idxPrm].volume += vol_tet;
82  if(isMagnetic(te))
83  totalMagVol += vol_tet;
84  });
85  vol = std::transform_reduce(paramTetra.begin(), paramTetra.end(), 0.0,
86  std::plus<>(), [](const Tetra::prm &region){ return region.volume; });
87 
88  // Build the list of tetrahedrons for each region.
89  std::for_each(tet.begin(), tet.end(), [this](Tetra::Tet const &te)
90  {
91  volumeRegions[te.idxPrm].push_back(te.idx);
92  });
93 
94  // Build the list of all the mesh edges.
95  edges.reserve(tet.size() * 6); // 6 (non unique) edges per tetrahedron
96  std::for_each(tet.begin(), tet.end(),
97  [this](Tetra::Tet const &te)
98  {
99  for (int i = 0; i < 3; ++i)
100  {
101  for (int j = i + 1; j < 4; ++j)
102  { edges.push_back(std::minmax(te.ind[i], te.ind[j])); }
103  }
104  });
105  std::sort(EXEC_POL, edges.begin(), edges.end());
106  auto last = std::unique(EXEC_POL, edges.begin(), edges.end());
107  edges.erase(last, edges.end());
108  edges.shrink_to_fit(); // save memory, as this could be quite big
109  magNode.resize(node.size());
110  std::fill(magNode.begin(),magNode.end(),false);
111  std::for_each(tet.begin(),tet.end(),[this](Tetra::Tet &te)
112  {
113  if(isMagnetic(te))
114  {
115  magTet.push_back(te.idx);
116  for (int i=0;i<4;i++)
117  { magNode[te.ind[i]] = true; }
118  }
119  });
120 
121  for(unsigned int i=0;i<fac.size();i++)
122  {
123  if (isMagnetic(fac[i]) && !mySets.paramFacette[fac[i].idxPrm].suppress_charges
124  && !isInMagList(magFac,fac[i]) )
125  { magFac.push_back(i); }
126  }
127 
128  if(mySets.getFieldType() == R4toR3)
129  { setExtSpaceField(mySets); }
130  }
131 
133  mesh(const mesh &) = delete;
134 
136  mesh &operator=(const mesh &) = delete;
137 
139  inline int getNbNodes(void) const { return node.size(); }
140 
142  inline int getNbFacs(void) const { return fac.size(); }
143 
145  inline int getNbTets(void) const { return tet.size(); }
146 
148  inline const Eigen::Vector3d getNode_p(const int i) const { return node[i].p; }
149 
151  inline const Eigen::Vector3d getNode_u(const int i) const { return node[i].get_u(Nodes::NEXT); }
152 
154  inline const Eigen::Vector3d getNode_v(const int i) const { return node[i].get_v(Nodes::NEXT); }
155 
157  inline double getProj_ep(const int i) const {return node[i].proj_ep();}
158 
160  inline double getProj_eq(const int i) const {return node[i].proj_eq();}
161 
163  inline void set_node_u0(const int i, Eigen::Vector3d const &val)
164  { node[i].d[Nodes::CURRENT].u = val; }
165 
167  inline void set_node_zero_v(const int i) { node[i].d[Nodes::NEXT].v.setZero(); }
168 
170  void infos(void) const;
171 
173  inline void setBasis(const double r)
174  {
175  std::for_each(EXEC_POL, node.begin(), node.end(),
176  [&r](Nodes::Node &nod) { nod.setBasis(r); });
177  }
178 
180  inline void updateNode(int i, double vp, double vq, const double dt)
181  { node[i].make_evol(vp*gamma0, vq*gamma0, dt); }
182 
184  inline void evolution(void)
185  {
186  std::for_each(EXEC_POL, node.begin(), node.end(),
187  [](Nodes::Node &nod) { nod.evolution(); });
188  }
189 
191  Eigen::Vector3d c;
192 
194  Eigen::Vector3d l;
195 
197  double vol;
198 
200  double totalMagVol;
201 
203  std::vector<Facette::Fac> fac;
204 
206  std::vector<Tetra::Tet> tet;
207 
209  std::vector<Tetra::prm> &paramTetra;
210 
214  double readSol(bool VERBOSE ,
215  const std::string fileName );
216 
219  inline void init_distrib(Settings const &mySets )
220  {
221  for (int nodeIdx = 0; nodeIdx < int(node.size()); ++nodeIdx)
222  {
223  Nodes::Node &n = node[nodeIdx];
224  n.d[Nodes::NEXT].phi = 0.;
225  n.d[Nodes::NEXT].phiv = 0.;
226 
227  // A non-magnetic node's magnetization is a vector of NAN.
228  if (!magNode[nodeIdx])
229  {
230  n.d[Nodes::CURRENT].u = Eigen::Vector3d(NAN, NAN, NAN);
231  n.d[Nodes::NEXT].u = n.d[Nodes::CURRENT].u;
232  continue;
233  }
234 
235  // If the initial magnetization depends only on the node position, we do not need to
236  // build the list of region names.
237  if (mySets.getMagType() == POSITION_ONLY)
238  {
239  n.d[Nodes::CURRENT].u = mySets.getMagnetization(n.p);
240  n.d[Nodes::NEXT].u = n.d[Nodes::CURRENT].u;
241  continue;
242  }
243 
244  // Get the list of region indices this node belongs to.
245  std::set<int> nodeRegions;
246  // skip region 0 (__default__) which should be empty
247  for (size_t regIdx = 1; regIdx < volumeRegions.size(); ++regIdx)
248  {
249  const std::vector<int> &regionTetras = volumeRegions[regIdx];
250  bool node_in_region = std::any_of(EXEC_POL,
251  regionTetras.begin(), regionTetras.end(),
252  [this, nodeIdx](int tetIdx)
253  {
254  const Tetra::Tet &tetrahedron = tet[tetIdx];
255  for (int i = 0; i < Tetra::N; ++i) // node of tetrahedron tetIdx
256  {
257  if (tetrahedron.ind[i] == nodeIdx)
258  { return true; }
259  }
260  return false;
261  });
262  if (node_in_region)
263  { nodeRegions.insert(regIdx); }
264  }
265 
266  // Get the list of region names this node belongs to.
267  std::vector<std::string> region_names;
268  region_names.resize(nodeRegions.size());
269  std::transform(nodeRegions.begin(), nodeRegions.end(), region_names.begin(),
270  [this](int regIdx){ return paramTetra[regIdx].regName; });
271 
272  n.d[Nodes::CURRENT].u = mySets.getMagnetization(n.p, region_names);
273  n.d[Nodes::NEXT].u = n.d[Nodes::CURRENT].u;
274  }
275  }
276 
280  double avg(std::function<double(Nodes::Node, Nodes::index)> getter ,
281  Nodes::index d ,
282  int region = -1 ) const;
283 
285  double max_angle() const
286  {
287  double min_dot_product = std::transform_reduce(EXEC_POL, edges.begin(), edges.end(), 1.0,
288  [](double a, double b){ return std::min(a, b); },
289  [this](const Edge edge)
290  {
291  Eigen::Vector3d m1 = getNode_u(edge.first);
292  Eigen::Vector3d m2 = getNode_u(edge.second);
293  return m1.dot(m2);
294  });
295  return std::acos(min_dot_product);
296  }
297 
304  void savesol(const int precision ,
305  const std::string fileName ,
306  std::string const &metadata ,
307  bool withSpinAcc ,
308  std::vector<Eigen::Vector3d> &s ) const;
309 
312  inline void set(const int i ,
313  std::function<void(Nodes::Node &, const double)> what_to_set ,
314  const double val )
315  { what_to_set(node[i], val); }
316 
318  inline int getNodeIndex(const int i) const { return node_index[i]; }
319 
321  inline bool isMagnetic(const Tetra::Tet &t) { return (paramTetra[t.idxPrm].Ms > 0); }
322 
324  inline bool isMagnetic(const Facette::Fac &f)
325  { return (magNode[f.ind[0]] && magNode[f.ind[1]] && magNode[f.ind[2]]); }
326 
329  std::vector<Edge> edges;
330 
334  std::vector<bool> magNode;
335 
337  std::vector<int> magTet;
338 
343  std::vector<int> magFac;
344 
346  std::vector< Eigen::Matrix<double,Nodes::DIM,Tetra::NPI> > extSpaceField;
347 
348 private:
351  std::vector<Nodes::Node> node;
352 
358  std::vector<int> node_index;
359 
361  std::vector<std::vector<int>> volumeRegions;
362 
365  void checkMeshFile(Settings const &mySets );
366 
368  void readNodes(Settings const &mySets );
369 
371  void readTetraedrons(Settings const &mySets );
372 
374  void readTriangles(Settings const &mySets );
375 
377  void readMesh(Settings const &mySets );
378 
380  double doOnNodes(const double init_val ,
381  const Nodes::index coord ,
382  std::function<bool(double, double)> whatToDo ) const;
383 
385  inline double minNodes(const Nodes::index coord ) const
386  {
387  return doOnNodes(__DBL_MAX__, coord, [](double a, double b) { return a < b; });
388  }
389 
391  inline double maxNodes(const Nodes::index coord ) const
392  {
393  return doOnNodes(__DBL_MIN__, coord, [](double a, double b) { return a > b; });
394  }
395 
419  void indexReorder();
420 
423  void sortNodes(Nodes::index long_axis );
424 
428  double surface(std::vector<int> &facIndices);
429 
432  bool isInMagList(std::vector<int> &idxMagList, Facette::Fac &f)
433  {
434  auto it = std::find_if(idxMagList.begin(),idxMagList.end(),
435  [this,&f](int idx) { return (fac[idx] == f); });
436  return(it != idxMagList.end());
437  }
438 
441  void setExtSpaceField(Settings &s );
442  }; // end class mesh
443  } // end namespace Mesh
444 #endif
Definition: facette.h:109
Definition: mesh.h:32
const Eigen::Vector3d getNode_p(const int i) const
Definition: mesh.h:148
void indexReorder()
Definition: mesh.cpp:48
Eigen::Vector3d l
Definition: mesh.h:194
bool isInMagList(std::vector< int > &idxMagList, Facette::Fac &f)
Definition: mesh.h:432
std::vector< int > magTet
Definition: mesh.h:337
std::vector< Eigen::Matrix< double, Nodes::DIM, Tetra::NPI > > extSpaceField
Definition: mesh.h:346
const Eigen::Vector3d getNode_u(const int i) const
Definition: mesh.h:151
void readMesh(Settings const &mySets)
Definition: read.cpp:12
int getNbFacs(void) const
Definition: mesh.h:142
Eigen::Vector3d c
Definition: mesh.h:191
mesh(Settings &mySets)
Definition: mesh.h:36
void set_node_zero_v(const int i)
Definition: mesh.h:167
void init_distrib(Settings const &mySets)
Definition: mesh.h:219
double max_angle() const
Definition: mesh.h:285
std::vector< Edge > edges
Definition: mesh.h:329
int getNbNodes(void) const
Definition: mesh.h:139
std::vector< Nodes::Node > node
Definition: mesh.h:351
bool isMagnetic(const Tetra::Tet &t)
Definition: mesh.h:321
double minNodes(const Nodes::index coord) const
Definition: mesh.h:385
std::vector< bool > magNode
Definition: mesh.h:334
std::vector< std::vector< int > > volumeRegions
Definition: mesh.h:361
bool isMagnetic(const Facette::Fac &f)
Definition: mesh.h:324
int getNodeIndex(const int i) const
Definition: mesh.h:318
double getProj_ep(const int i) const
Definition: mesh.h:157
std::vector< Tetra::Tet > tet
Definition: mesh.h:206
double maxNodes(const Nodes::index coord) const
Definition: mesh.h:391
int getNbTets(void) const
Definition: mesh.h:145
void set_node_u0(const int i, Eigen::Vector3d const &val)
Definition: mesh.h:163
void sortNodes(Nodes::index long_axis)
Definition: mesh.cpp:100
std::vector< Facette::Fac > fac
Definition: mesh.h:203
mesh(const mesh &)=delete
void setBasis(const double r)
Definition: mesh.h:173
void evolution(void)
Definition: mesh.h:184
std::vector< int > magFac
Definition: mesh.h:343
double totalMagVol
Definition: mesh.h:200
const Eigen::Vector3d getNode_v(const int i) const
Definition: mesh.h:154
std::vector< int > node_index
Definition: mesh.h:358
std::vector< Tetra::prm > & paramTetra
Definition: mesh.h:209
void updateNode(int i, double vp, double vq, const double dt)
Definition: mesh.h:180
double getProj_eq(const int i) const
Definition: mesh.h:160
double vol
Definition: mesh.h:197
mesh & operator=(const mesh &)=delete
void set(const int i, std::function< void(Nodes::Node &, const double)> what_to_set, const double val)
Definition: mesh.h:312
Container for all the settings provided by the user, with conversions to/from YAML.
Definition: settings.h:73
int verbose
Definition: settings.h:139
mag_exprType getMagType() const
Definition: settings.h:272
Eigen::Vector3d getMagnetization(const Eigen::Ref< Eigen::Vector3d > p) const
Definition: settings.h:282
Definition: tetra.h:141
int idxPrm
Definition: element.h:53
std::vector< int > ind
Definition: element.h:50
contains namespace Facette header containing Fac class, and some constants and a less_than operator t...
std::pair< int, int > Edge
Definition: mesh.h:25
constexpr double a[N][NPI]
Definition: facette.h:55
index
Definition: node.h:34
header to define struct Node
many settings to give some parameters to the solver, boundary conditions for the problem,...
@ R4toR3
Definition: settings.h:46
@ POSITION_ONLY
M(x, y, z)
Definition: settings.h:29
Definition: node.h:61
Eigen::Vector3d p
Definition: node.h:62
dataNode d[NB_DATANODE]
Definition: node.h:71
double phi
Definition: node.h:52
double phiv
Definition: node.h:53
Eigen::Vector3d u
Definition: node.h:50
Definition: tetra.h:87
namespace Tetra header containing Tet class, some constants, and integrales