Feellgood
mesh.h
Go to the documentation of this file.
1 #ifndef mesh_h
2 #define mesh_h
3 
8 #include <cmath>
9 #include <algorithm>
10 #pragma GCC diagnostic push
11 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
12 #include <execution>
13 #pragma GCC diagnostic pop
14 
15 #include "facette.h"
16 #include "node.h"
17 #include "tetra.h"
18 #include "feellgoodSettings.h"
19 
20 namespace Mesh
21  {
26 class mesh
27  {
28 public:
31  mesh(Settings &mySets )
32  : paramTetra(mySets.paramTetra), volumeRegions(mySets.paramTetra.size())
33  {
34  readMesh(mySets);
35  indexReorder();
36 
37  if (mySets.verbose)
38  { std::cout << " reindexed\n"; }
39 
40  double xmin = minNodes(Nodes::IDX_X);
41  double xmax = maxNodes(Nodes::IDX_X);
42 
43  double ymin = minNodes(Nodes::IDX_Y);
44  double ymax = maxNodes(Nodes::IDX_Y);
45 
46  double zmin = minNodes(Nodes::IDX_Z);
47  double zmax = maxNodes(Nodes::IDX_Z);
48 
49  l = Eigen::Vector3d(xmax - xmin, ymax - ymin, zmax - zmin);
50  c = Eigen::Vector3d(0.5 * (xmax + xmin), 0.5 * (ymax + ymin), 0.5 * (zmax + zmin));
51 
52  // Find the longest axis of the sample.
53  Nodes::index long_axis;
54  if (l.x() > l.y())
55  {
56  if (l.x() > l.z())
57  long_axis = Nodes::IDX_X;
58  else
59  long_axis = Nodes::IDX_Z;
60  }
61  else
62  {
63  if (l.y() > l.z())
64  long_axis = Nodes::IDX_Y;
65  else
66  long_axis = Nodes::IDX_Z;
67  }
68  sortNodes(long_axis);
69 
70  totalMagVol = 0;
71  // Compute the per-region volumes and the total volume.
72  std::for_each(tet.begin(), tet.end(),
73  [this](Tetra::Tet const &te)
74  {
75  double vol_tet = te.calc_vol();
76  paramTetra[te.idxPrm].volume += vol_tet;
77  if(isMagnetic(te))
78  totalMagVol += vol_tet;
79  });
80  vol = std::transform_reduce(paramTetra.begin(), paramTetra.end(), 0.0,
81  std::plus<>(), [](const Tetra::prm &region){ return region.volume; });
82 
83  // Build the list of tetrahedrons for each region.
84  std::for_each(tet.begin(), tet.end(), [this](Tetra::Tet const &te)
85  {
86  volumeRegions[te.idxPrm].push_back(te.idx);
87  });
88 
89  // Build the list of all the mesh edges.
90  edges.reserve(tet.size() * 6); // 6 (non unique) edges per tetrahedron
91  std::for_each(tet.begin(), tet.end(),
92  [this](Tetra::Tet const &te)
93  {
94  for (int i = 0; i < 3; ++i)
95  {
96  for (int j = i + 1; j < 4; ++j)
97  { edges.push_back(std::minmax(te.ind[i], te.ind[j])); }
98  }
99  });
100  std::sort(EXEC_POL, edges.begin(), edges.end());
101  auto last = std::unique(EXEC_POL, edges.begin(), edges.end());
102  edges.erase(last, edges.end());
103  edges.shrink_to_fit(); // save memory, as this could be quite big
104  magNode.resize(node.size());
105  std::fill(magNode.begin(),magNode.end(),false);
106  std::for_each(tet.begin(),tet.end(),[this](Tetra::Tet &te)
107  {
108  if(isMagnetic(te))
109  {
110  for (int i=0;i<4;i++)
111  { magNode[te.ind[i]] = true; }
112  }
113  });
114 
115  for(unsigned int i=0;i<tet.size();i++)
116  {
117  if (isMagnetic(tet[i]))
118  { magTet.push_back(i); }
119  }
120 
121  for(unsigned int i=0;i<fac.size();i++)
122  {
123  if (isMagnetic(fac[i]) && !isInMagList(magFac,fac[i]) )
124  { magFac.push_back(i); }
125  }
126  }
127 
129  mesh(const mesh &) = delete;
130 
132  mesh &operator=(const mesh &) = delete;
133 
135  inline int getNbNodes(void) const { return node.size(); }
136 
138  inline int getNbFacs(void) const { return fac.size(); }
139 
141  inline int getNbTets(void) const { return tet.size(); }
142 
144  inline const Eigen::Vector3d getNode_p(const int i) const { return node[i].p; }
145 
147  inline const Eigen::Vector3d getNode_u(const int i) const { return node[i].get_u(Nodes::NEXT); }
148 
150  inline const Eigen::Vector3d getNode_v(const int i) const { return node[i].get_v(Nodes::NEXT); }
151 
153  inline double getProj_ep(const int i) const {return node[i].proj_ep();}
154 
156  inline double getProj_eq(const int i) const {return node[i].proj_eq();}
157 
159  inline void set_node_u0(const int i, Eigen::Vector3d const &val)
160  { node[i].d[Nodes::CURRENT].u = val; }
161 
163  inline void set_node_zero_v(const int i) { node[i].d[Nodes::NEXT].v.setZero(); }
164 
166  void infos(void) const;
167 
169  inline void setBasis(const double r)
170  {
171  std::for_each(EXEC_POL, node.begin(), node.end(),
172  [&r](Nodes::Node &nod) { nod.setBasis(r); });
173  }
174 
176  inline void updateNode(int i, double vp, double vq, const double dt)
177  { node[i].make_evol(vp*gamma0, vq*gamma0, dt); }
178 
180  inline void evolution(void)
181  {
182  std::for_each(EXEC_POL, node.begin(), node.end(),
183  [](Nodes::Node &nod) { nod.evolution(); });
184  }
185 
187  Eigen::Vector3d c;
188 
190  Eigen::Vector3d l;
191 
193  double vol;
194 
196  double totalMagVol;
197 
199  std::vector<Facette::Fac> fac;
200 
202  std::vector<Tetra::Tet> tet;
203 
205  std::vector<Tetra::prm> &paramTetra;
206 
210  double readSol(bool VERBOSE ,
211  const std::string fileName );
212 
215  inline void init_distrib(Settings const &mySets )
216  {
217  for (int nodeIdx = 0; nodeIdx < int(node.size()); ++nodeIdx)
218  {
219  Nodes::Node &n = node[nodeIdx];
220  n.d[Nodes::NEXT].phi = 0.;
221  n.d[Nodes::NEXT].phiv = 0.;
222 
223  // A non-magnetic node's magnetization is a vector of NAN.
224  if (!magNode[nodeIdx])
225  {
226  n.d[Nodes::CURRENT].u = Eigen::Vector3d(NAN, NAN, NAN);
227  n.d[Nodes::NEXT].u = n.d[Nodes::CURRENT].u;
228  continue;
229  }
230 
231  // If the initial magnetization depends only on the node position, we do not need to
232  // build the list of region names.
233  if (mySets.getMagType() == POSITION_ONLY)
234  {
235  n.d[Nodes::CURRENT].u = mySets.getMagnetization(n.p);
236  n.d[Nodes::NEXT].u = n.d[Nodes::CURRENT].u;
237  continue;
238  }
239 
240  // Get the list of region indices this node belongs to.
241  std::set<int> nodeRegions;
242  // skip region 0 (__default__) which should be empty
243  for (size_t regIdx = 1; regIdx < volumeRegions.size(); ++regIdx)
244  {
245  const std::vector<int> &regionTetras = volumeRegions[regIdx];
246  bool node_in_region = std::any_of(EXEC_POL,
247  regionTetras.begin(), regionTetras.end(),
248  [this, nodeIdx](int tetIdx)
249  {
250  const Tetra::Tet &tetrahedron = tet[tetIdx];
251  for (int i = 0; i < Tetra::N; ++i) // node of tetrahedron tetIdx
252  {
253  if (tetrahedron.ind[i] == nodeIdx)
254  { return true; }
255  }
256  return false;
257  });
258  if (node_in_region)
259  { nodeRegions.insert(regIdx); }
260  }
261 
262  // Get the list of region names this node belongs to.
263  std::vector<std::string> region_names;
264  region_names.resize(nodeRegions.size());
265  std::transform(nodeRegions.begin(), nodeRegions.end(), region_names.begin(),
266  [this](int regIdx){ return paramTetra[regIdx].regName; });
267 
268  n.d[Nodes::CURRENT].u = mySets.getMagnetization(n.p, region_names);
269  n.d[Nodes::NEXT].u = n.d[Nodes::CURRENT].u;
270  }
271  }
272 
276  double avg(std::function<double(Nodes::Node, Nodes::index)> getter ,
277  Nodes::index d ,
278  int region = -1 ) const;
279 
281  double max_angle() const
282  {
283  double min_dot_product = std::transform_reduce(EXEC_POL, edges.begin(), edges.end(), 1.0,
284  [](double a, double b){ return std::min(a, b); },
285  [this](const std::pair<int, int> edge)
286  {
287  Eigen::Vector3d m1 = getNode_u(edge.first);
288  Eigen::Vector3d m2 = getNode_u(edge.second);
289  return m1.dot(m2);
290  });
291  return std::acos(min_dot_product);
292  }
293 
300  void savesol(const int precision ,
301  const std::string fileName ,
302  std::string const &metadata ,
303  bool withSpinAcc ,
304  std::vector<Eigen::Vector3d> &s ) const;
305 
308  inline void set(const int i ,
309  std::function<void(Nodes::Node &, const double)> what_to_set ,
310  const double val )
311  { what_to_set(node[i], val); }
312 
314  inline int getNodeIndex(const int i) const { return node_index[i]; }
315 
317  inline bool isMagnetic(const Tetra::Tet &t) { return (paramTetra[t.idxPrm].J > 0); }
318 
320  inline bool isMagnetic(const Facette::Fac &f)
321  { return (magNode[f.ind[0]] && magNode[f.ind[1]] && magNode[f.ind[2]]); }
322 
326  std::vector<std::pair<int, int>> edges;
327 
331  std::vector<bool> magNode;
332 
334  std::vector<int> magTet;
335 
337  std::vector<int> magFac;
338 private:
341  std::vector<Nodes::Node> node;
342 
348  std::vector<int> node_index;
349 
351  std::vector<std::vector<int>> volumeRegions;
352 
354  void checkMeshFile(Settings const &mySets );
355 
357  void readNodes(Settings const &mySets );
358 
360  void readTetraedrons(Settings const &mySets );
361 
363  void readTriangles(Settings const &mySets );
364 
366  void readMesh(Settings const &mySets );
367 
369  double doOnNodes(const double init_val ,
370  const Nodes::index coord ,
371  std::function<bool(double, double)> whatToDo ) const;
372 
374  inline double minNodes(const Nodes::index coord ) const
375  {
376  return doOnNodes(__DBL_MAX__, coord, [](double a, double b) { return a < b; });
377  }
378 
380  inline double maxNodes(const Nodes::index coord ) const
381  {
382  return doOnNodes(__DBL_MIN__, coord, [](double a, double b) { return a > b; });
383  }
384 
408  void indexReorder();
409 
412  void sortNodes(Nodes::index long_axis );
413 
417  double surface(std::vector<int> &facIndices);
418 
420  bool isInMagList(std::vector<int> &idxMagList, Facette::Fac &f)
421  {
422  auto it = std::find_if(idxMagList.begin(),idxMagList.end(),
423  [this,&f](int idx) { return (fac[idx] == f); });
424  return(it != idxMagList.end());
425  }
426  }; // end class mesh
427  } // end namespace Mesh
428 #endif
Definition: facette.h:72
Definition: mesh.h:27
const Eigen::Vector3d getNode_p(const int i) const
Definition: mesh.h:144
void indexReorder()
Definition: mesh.cpp:48
Eigen::Vector3d l
Definition: mesh.h:190
bool isInMagList(std::vector< int > &idxMagList, Facette::Fac &f)
Definition: mesh.h:420
std::vector< int > magTet
Definition: mesh.h:334
const Eigen::Vector3d getNode_u(const int i) const
Definition: mesh.h:147
void readMesh(Settings const &mySets)
Definition: read.cpp:12
int getNbFacs(void) const
Definition: mesh.h:138
Eigen::Vector3d c
Definition: mesh.h:187
mesh(Settings &mySets)
Definition: mesh.h:31
void set_node_zero_v(const int i)
Definition: mesh.h:163
void init_distrib(Settings const &mySets)
Definition: mesh.h:215
double max_angle() const
Definition: mesh.h:281
int getNbNodes(void) const
Definition: mesh.h:135
std::vector< Nodes::Node > node
Definition: mesh.h:341
bool isMagnetic(const Tetra::Tet &t)
Definition: mesh.h:317
double minNodes(const Nodes::index coord) const
Definition: mesh.h:374
std::vector< bool > magNode
Definition: mesh.h:331
std::vector< std::vector< int > > volumeRegions
Definition: mesh.h:351
bool isMagnetic(const Facette::Fac &f)
Definition: mesh.h:320
int getNodeIndex(const int i) const
Definition: mesh.h:314
double getProj_ep(const int i) const
Definition: mesh.h:153
std::vector< Tetra::Tet > tet
Definition: mesh.h:202
double maxNodes(const Nodes::index coord) const
Definition: mesh.h:380
int getNbTets(void) const
Definition: mesh.h:141
void set_node_u0(const int i, Eigen::Vector3d const &val)
Definition: mesh.h:159
void sortNodes(Nodes::index long_axis)
Definition: mesh.cpp:97
std::vector< Facette::Fac > fac
Definition: mesh.h:199
mesh(const mesh &)=delete
void setBasis(const double r)
Definition: mesh.h:169
void evolution(void)
Definition: mesh.h:180
std::vector< int > magFac
Definition: mesh.h:337
double totalMagVol
Definition: mesh.h:196
const Eigen::Vector3d getNode_v(const int i) const
Definition: mesh.h:150
std::vector< std::pair< int, int > > edges
Definition: mesh.h:326
std::vector< int > node_index
Definition: mesh.h:348
std::vector< Tetra::prm > & paramTetra
Definition: mesh.h:205
void updateNode(int i, double vp, double vq, const double dt)
Definition: mesh.h:176
double getProj_eq(const int i) const
Definition: mesh.h:156
double vol
Definition: mesh.h:193
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:308
Container for all the settings provided by the user, with conversions to/from YAML.
Definition: feellgoodSettings.h:73
int verbose
Definition: feellgoodSettings.h:135
mag_exprType getMagType() const
Definition: feellgoodSettings.h:268
Eigen::Vector3d getMagnetization(const Eigen::Ref< Eigen::Vector3d > p) const
Definition: feellgoodSettings.h:278
Definition: tetra.h:111
int idxPrm
Definition: element.h:47
std::vector< int > ind
Definition: element.h:44
contains namespace Facette header containing Fac class, and some constants and a less_than operator t...
many settings to give some parameters to the solver, boundary conditions for the problem,...
@ POSITION_ONLY
M(x, y, z)
Definition: feellgoodSettings.h:29
constexpr double a[N][NPI]
Definition: facette.h:28
index
Definition: node.h:34
header to define struct Node
Definition: node.h:61
Eigen::Vector3d p
Definition: node.h:62
dataNode d[NB_DATANODE]
Definition: node.h:70
double phi
Definition: node.h:52
double phiv
Definition: node.h:53
Eigen::Vector3d u
Definition: node.h:50
Definition: tetra.h:61
namespace Tetra header containing Tet class, some constants, and integrales