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  {
23  using Edge = std::pair<int, int>;
24 
29 class mesh
30  {
31 public:
34  mesh(Settings &mySets )
35  : paramTetra(mySets.paramTetra), volumeRegions(mySets.paramTetra.size())
36  {
37  readMesh(mySets);
38  indexReorder();
39 
40  if (mySets.verbose)
41  { std::cout << " reindexed\n"; }
42 
43  double xmin = minNodes(Nodes::IDX_X);
44  double xmax = maxNodes(Nodes::IDX_X);
45 
46  double ymin = minNodes(Nodes::IDX_Y);
47  double ymax = maxNodes(Nodes::IDX_Y);
48 
49  double zmin = minNodes(Nodes::IDX_Z);
50  double zmax = maxNodes(Nodes::IDX_Z);
51 
52  l = Eigen::Vector3d(xmax - xmin, ymax - ymin, zmax - zmin);
53  c = Eigen::Vector3d(0.5 * (xmax + xmin), 0.5 * (ymax + ymin), 0.5 * (zmax + zmin));
54 
55  // Find the longest axis of the sample.
56  Nodes::index long_axis;
57  if (l.x() > l.y())
58  {
59  if (l.x() > l.z())
60  long_axis = Nodes::IDX_X;
61  else
62  long_axis = Nodes::IDX_Z;
63  }
64  else
65  {
66  if (l.y() > l.z())
67  long_axis = Nodes::IDX_Y;
68  else
69  long_axis = Nodes::IDX_Z;
70  }
71  sortNodes(long_axis);
72 
73  totalMagVol = 0;
74  // Compute the per-region volumes and the total volume.
75  std::for_each(tet.begin(), tet.end(),
76  [this](Tetra::Tet const &te)
77  {
78  double vol_tet = te.calc_vol();
79  paramTetra[te.idxPrm].volume += vol_tet;
80  if(isMagnetic(te))
81  totalMagVol += vol_tet;
82  });
83  vol = std::transform_reduce(paramTetra.begin(), paramTetra.end(), 0.0,
84  std::plus<>(), [](const Tetra::prm &region){ return region.volume; });
85 
86  // Build the list of tetrahedrons for each region.
87  std::for_each(tet.begin(), tet.end(), [this](Tetra::Tet const &te)
88  {
89  volumeRegions[te.idxPrm].push_back(te.idx);
90  });
91 
92  // Build the list of all the mesh edges.
93  edges.reserve(tet.size() * 6); // 6 (non unique) edges per tetrahedron
94  std::for_each(tet.begin(), tet.end(),
95  [this](Tetra::Tet const &te)
96  {
97  for (int i = 0; i < 3; ++i)
98  {
99  for (int j = i + 1; j < 4; ++j)
100  { edges.push_back(std::minmax(te.ind[i], te.ind[j])); }
101  }
102  });
103  std::sort(EXEC_POL, edges.begin(), edges.end());
104  auto last = std::unique(EXEC_POL, edges.begin(), edges.end());
105  edges.erase(last, edges.end());
106  edges.shrink_to_fit(); // save memory, as this could be quite big
107  magNode.resize(node.size());
108  std::fill(magNode.begin(),magNode.end(),false);
109  std::for_each(tet.begin(),tet.end(),[this](Tetra::Tet &te)
110  {
111  if(isMagnetic(te))
112  {
113  magTet.push_back(te.idx);
114  for (int i=0;i<4;i++)
115  { magNode[te.ind[i]] = true; }
116  }
117  });
118 
119  for(unsigned int i=0;i<fac.size();i++)
120  {
121  if (isMagnetic(fac[i]) && !mySets.paramFacette[fac[i].idxPrm].suppress_charges
122  && !isInMagList(magFac,fac[i]) )
123  { magFac.push_back(i); }
124  }
125 
126  if(mySets.getFieldType() == R4toR3)
127  { setExtSpaceField(mySets); }
128  }
129 
131  mesh(const mesh &) = delete;
132 
134  mesh &operator=(const mesh &) = delete;
135 
137  inline int getNbNodes(void) const { return node.size(); }
138 
140  inline int getNbFacs(void) const { return fac.size(); }
141 
143  inline int getNbTets(void) const { return tet.size(); }
144 
146  inline const Eigen::Vector3d getNode_p(const int i) const { return node[i].p; }
147 
149  inline const Eigen::Vector3d getNode_u(const int i) const { return node[i].get_u(Nodes::NEXT); }
150 
152  inline const Eigen::Vector3d getNode_v(const int i) const { return node[i].get_v(Nodes::NEXT); }
153 
155  inline double getProj_ep(const int i) const {return node[i].proj_ep();}
156 
158  inline double getProj_eq(const int i) const {return node[i].proj_eq();}
159 
161  inline void set_node_u0(const int i, Eigen::Vector3d const &val)
162  { node[i].d[Nodes::CURRENT].u = val; }
163 
165  inline void set_node_zero_v(const int i) { node[i].d[Nodes::NEXT].v.setZero(); }
166 
168  void infos(void) const;
169 
171  inline void setBasis(const double r)
172  {
173  std::for_each(EXEC_POL, node.begin(), node.end(),
174  [&r](Nodes::Node &nod) { nod.setBasis(r); });
175  }
176 
178  inline void updateNode(int i, double vp, double vq, const double dt)
179  { node[i].make_evol(vp*gamma0, vq*gamma0, dt); }
180 
182  inline void evolution(void)
183  {
184  std::for_each(EXEC_POL, node.begin(), node.end(),
185  [](Nodes::Node &nod) { nod.evolution(); });
186  }
187 
189  Eigen::Vector3d c;
190 
192  Eigen::Vector3d l;
193 
195  double vol;
196 
198  double totalMagVol;
199 
201  std::vector<Facette::Fac> fac;
202 
204  std::vector<Tetra::Tet> tet;
205 
207  std::vector<Tetra::prm> &paramTetra;
208 
212  double readSol(bool VERBOSE ,
213  const std::string fileName );
214 
217  inline void init_distrib(Settings const &mySets )
218  {
219  for (int nodeIdx = 0; nodeIdx < int(node.size()); ++nodeIdx)
220  {
221  Nodes::Node &n = node[nodeIdx];
222  n.d[Nodes::NEXT].phi = 0.;
223  n.d[Nodes::NEXT].phiv = 0.;
224 
225  // A non-magnetic node's magnetization is a vector of NAN.
226  if (!magNode[nodeIdx])
227  {
228  n.d[Nodes::CURRENT].u = Eigen::Vector3d(NAN, NAN, NAN);
229  n.d[Nodes::NEXT].u = n.d[Nodes::CURRENT].u;
230  continue;
231  }
232 
233  // If the initial magnetization depends only on the node position, we do not need to
234  // build the list of region names.
235  if (mySets.getMagType() == POSITION_ONLY)
236  {
237  n.d[Nodes::CURRENT].u = mySets.getMagnetization(n.p);
238  n.d[Nodes::NEXT].u = n.d[Nodes::CURRENT].u;
239  continue;
240  }
241 
242  // Get the list of region indices this node belongs to.
243  std::set<int> nodeRegions;
244  // skip region 0 (__default__) which should be empty
245  for (size_t regIdx = 1; regIdx < volumeRegions.size(); ++regIdx)
246  {
247  const std::vector<int> &regionTetras = volumeRegions[regIdx];
248  bool node_in_region = std::any_of(EXEC_POL,
249  regionTetras.begin(), regionTetras.end(),
250  [this, nodeIdx](int tetIdx)
251  {
252  const Tetra::Tet &tetrahedron = tet[tetIdx];
253  for (int i = 0; i < Tetra::N; ++i) // node of tetrahedron tetIdx
254  {
255  if (tetrahedron.ind[i] == nodeIdx)
256  { return true; }
257  }
258  return false;
259  });
260  if (node_in_region)
261  { nodeRegions.insert(regIdx); }
262  }
263 
264  // Get the list of region names this node belongs to.
265  std::vector<std::string> region_names;
266  region_names.resize(nodeRegions.size());
267  std::transform(nodeRegions.begin(), nodeRegions.end(), region_names.begin(),
268  [this](int regIdx){ return paramTetra[regIdx].regName; });
269 
270  n.d[Nodes::CURRENT].u = mySets.getMagnetization(n.p, region_names);
271  n.d[Nodes::NEXT].u = n.d[Nodes::CURRENT].u;
272  }
273  }
274 
278  double avg(std::function<double(Nodes::Node, Nodes::index)> getter ,
279  Nodes::index d ,
280  int region = -1 ) const;
281 
283  double max_angle() const
284  {
285  double min_dot_product = std::transform_reduce(EXEC_POL, edges.begin(), edges.end(), 1.0,
286  [](double a, double b){ return std::min(a, b); },
287  [this](const Edge edge)
288  {
289  Eigen::Vector3d m1 = getNode_u(edge.first);
290  Eigen::Vector3d m2 = getNode_u(edge.second);
291  return m1.dot(m2);
292  });
293  return std::acos(min_dot_product);
294  }
295 
302  void savesol(const int precision ,
303  const std::string fileName ,
304  std::string const &metadata ,
305  bool withSpinAcc ,
306  std::vector<Eigen::Vector3d> &s ) const;
307 
310  inline void set(const int i ,
311  std::function<void(Nodes::Node &, const double)> what_to_set ,
312  const double val )
313  { what_to_set(node[i], val); }
314 
316  inline int getNodeIndex(const int i) const { return node_index[i]; }
317 
319  inline bool isMagnetic(const Tetra::Tet &t) { return (paramTetra[t.idxPrm].Ms > 0); }
320 
322  inline bool isMagnetic(const Facette::Fac &f)
323  { return (magNode[f.ind[0]] && magNode[f.ind[1]] && magNode[f.ind[2]]); }
324 
327  std::vector<Edge> edges;
328 
332  std::vector<bool> magNode;
333 
335  std::vector<int> magTet;
336 
341  std::vector<int> magFac;
342 
344  std::vector< Eigen::Matrix<double,Nodes::DIM,Tetra::NPI> > extSpaceField;
345 
346 private:
349  std::vector<Nodes::Node> node;
350 
356  std::vector<int> node_index;
357 
359  std::vector<std::vector<int>> volumeRegions;
360 
362  void checkMeshFile(Settings const &mySets );
363 
365  void readNodes(Settings const &mySets );
366 
368  void readTetraedrons(Settings const &mySets );
369 
371  void readTriangles(Settings const &mySets );
372 
374  void readMesh(Settings const &mySets );
375 
377  double doOnNodes(const double init_val ,
378  const Nodes::index coord ,
379  std::function<bool(double, double)> whatToDo ) const;
380 
382  inline double minNodes(const Nodes::index coord ) const
383  {
384  return doOnNodes(__DBL_MAX__, coord, [](double a, double b) { return a < b; });
385  }
386 
388  inline double maxNodes(const Nodes::index coord ) const
389  {
390  return doOnNodes(__DBL_MIN__, coord, [](double a, double b) { return a > b; });
391  }
392 
416  void indexReorder();
417 
420  void sortNodes(Nodes::index long_axis );
421 
425  double surface(std::vector<int> &facIndices);
426 
428  bool isInMagList(std::vector<int> &idxMagList, Facette::Fac &f)
429  {
430  auto it = std::find_if(idxMagList.begin(),idxMagList.end(),
431  [this,&f](int idx) { return (fac[idx] == f); });
432  return(it != idxMagList.end());
433  }
434 
437  void setExtSpaceField(Settings &s );
438  }; // end class mesh
439  } // end namespace Mesh
440 #endif
Definition: facette.h:105
Definition: mesh.h:30
const Eigen::Vector3d getNode_p(const int i) const
Definition: mesh.h:146
void indexReorder()
Definition: mesh.cpp:48
Eigen::Vector3d l
Definition: mesh.h:192
bool isInMagList(std::vector< int > &idxMagList, Facette::Fac &f)
Definition: mesh.h:428
std::vector< int > magTet
Definition: mesh.h:335
std::vector< Eigen::Matrix< double, Nodes::DIM, Tetra::NPI > > extSpaceField
Definition: mesh.h:344
const Eigen::Vector3d getNode_u(const int i) const
Definition: mesh.h:149
void readMesh(Settings const &mySets)
Definition: read.cpp:12
int getNbFacs(void) const
Definition: mesh.h:140
Eigen::Vector3d c
Definition: mesh.h:189
mesh(Settings &mySets)
Definition: mesh.h:34
void set_node_zero_v(const int i)
Definition: mesh.h:165
void init_distrib(Settings const &mySets)
Definition: mesh.h:217
double max_angle() const
Definition: mesh.h:283
std::vector< Edge > edges
Definition: mesh.h:327
int getNbNodes(void) const
Definition: mesh.h:137
std::vector< Nodes::Node > node
Definition: mesh.h:349
bool isMagnetic(const Tetra::Tet &t)
Definition: mesh.h:319
double minNodes(const Nodes::index coord) const
Definition: mesh.h:382
std::vector< bool > magNode
Definition: mesh.h:332
std::vector< std::vector< int > > volumeRegions
Definition: mesh.h:359
bool isMagnetic(const Facette::Fac &f)
Definition: mesh.h:322
int getNodeIndex(const int i) const
Definition: mesh.h:316
double getProj_ep(const int i) const
Definition: mesh.h:155
std::vector< Tetra::Tet > tet
Definition: mesh.h:204
double maxNodes(const Nodes::index coord) const
Definition: mesh.h:388
int getNbTets(void) const
Definition: mesh.h:143
void set_node_u0(const int i, Eigen::Vector3d const &val)
Definition: mesh.h:161
void sortNodes(Nodes::index long_axis)
Definition: mesh.cpp:97
std::vector< Facette::Fac > fac
Definition: mesh.h:201
mesh(const mesh &)=delete
void setBasis(const double r)
Definition: mesh.h:171
void evolution(void)
Definition: mesh.h:182
std::vector< int > magFac
Definition: mesh.h:341
double totalMagVol
Definition: mesh.h:198
const Eigen::Vector3d getNode_v(const int i) const
Definition: mesh.h:152
std::vector< int > node_index
Definition: mesh.h:356
std::vector< Tetra::prm > & paramTetra
Definition: mesh.h:207
void updateNode(int i, double vp, double vq, const double dt)
Definition: mesh.h:178
double getProj_eq(const int i) const
Definition: mesh.h:158
double vol
Definition: mesh.h:195
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:310
Container for all the settings provided by the user, with conversions to/from YAML.
Definition: feellgoodSettings.h:73
int verbose
Definition: feellgoodSettings.h:139
mag_exprType getMagType() const
Definition: feellgoodSettings.h:272
Eigen::Vector3d getMagnetization(const Eigen::Ref< Eigen::Vector3d > p) const
Definition: feellgoodSettings.h:282
Definition: tetra.h:135
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,...
@ R4toR3
Definition: feellgoodSettings.h:46
@ POSITION_ONLY
M(x, y, z)
Definition: feellgoodSettings.h:29
std::pair< int, int > Edge
Definition: mesh.h:23
constexpr double a[N][NPI]
Definition: facette.h:55
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:85
namespace Tetra header containing Tet class, some constants, and integrales