Feellgood
electrostatSolver.h
Go to the documentation of this file.
1 
8 #include <iostream>
9 #include <map>
10 
11 #include "config.h"
12 #include "fem.h"
13 #include "mesh.h"
14 
15 #include "facette.h"
16 #include "tetra.h"
17 
18 #include "spinTransferTorque.h"
19 
21 inline void assembling_mat(Tetra::Tet const &tet, double Ke[Tetra::N][Tetra::N], std::vector<Eigen::Triplet<double>> &K)
22  {
23  for (int ie = 0; ie < Tetra::N; ie++)
24  {
25  for (int je = 0; je < Tetra::N; je++)
26  {
27  double val = Ke[ie][je];
28  if (val != 0)
29  { K.push_back( Eigen::Triplet(tet.ind[ie], tet.ind[je], val) ); }
30  }
31  }
32  }
33 
35 inline void assembling_vect(Facette::Fac const &fac, std::vector<double> const &Le, Eigen::Ref<Eigen::VectorXd> L)
36  {
37  for (int ie = 0; ie < Facette::N; ie++)
38  { L(fac.ind[ie]) += Le[ie]; }
39  }
40 
43 void integrales(Tetra::Tet const &tet, double sigma, double AE[Tetra::N][Tetra::N])
44  {
45  for (int npi = 0; npi < Tetra::NPI; npi++)
46  {
47  double w = tet.weight[npi];
48 
49  for (int ie = 0; ie < Tetra::N; ie++)
50  {
51  double dai_dx = tet.da(ie,Nodes::IDX_X);
52  double dai_dy = tet.da(ie,Nodes::IDX_Y);
53  double dai_dz = tet.da(ie,Nodes::IDX_Z);
54 
55  for (int je = 0; je < Tetra::N; je++)
56  {
57  double daj_dx = tet.da(je,Nodes::IDX_X);
58  double daj_dy = tet.da(je,Nodes::IDX_Y);
59  double daj_dz = tet.da(je,Nodes::IDX_Z);
60  AE[ie][je] += sigma * (dai_dx * daj_dx + dai_dy * daj_dy + dai_dz * daj_dz) * w;
61  }
62  }
63  }
64  }
65 
67 void integrales(Facette::Fac const &fac, double pot_val, std::vector<double> &BE)
68  {
69  for (int npi = 0; npi < Facette::NPI; npi++)
70  for (int ie = 0; ie < Facette::N; ie++)
71  {
72  BE[ie] -= Facette::a[ie][npi] * pot_val * fac.weight[npi];
73  }
74  }
75 
81  {
82 public:
85  Mesh::mesh const &_msh ,
86  STT const &_p_stt ,
87  const double _tol ,
88  const bool v ,
89  const int max_iter ,
90  const std::string
91  _fileName )
92  : msh(_msh), p_stt(_p_stt), verbose(v), MAXITER(max_iter), precision(PRECISION_STT),
93  fileName(_fileName)
94  {
96  D0 = 2.0 * p_stt.sigma / (Nodes::sq(CHARGE_ELECTRON) * p_stt.N0);
97  pf = Nodes::sq(p_stt.lJ) / (D0 * (1. + ksi * ksi)) * BOHRS_MUB * p_stt.beta / CHARGE_ELECTRON;
98 
99  if (verbose)
100  {
101  std::cout << "Dirichlet boundary conditions..." << std::endl;
102  infos();
103  }
104  V.resize(_msh.getNbNodes());
105  bool has_converged = solve(_tol);
106  if (has_converged)
107  {
108  if (p_stt.V_file)
109  {
110  if (verbose)
111  {
112  std::cout << "writing electrostatic potential solutions to file " << fileName
113  << std::endl;
114  }
115  bool iznogood = msh.savesol(precision, fileName, "## columns: index\tV\n", V);
116  if (verbose && iznogood)
117  {
118  std::cout << "file " << fileName << " status : " << iznogood << std::endl;
119  }
120  }
121  std::for_each(msh.tet.begin(), msh.tet.end(),
122  [this](Tetra::Tet const &tet)
123  {
124  Eigen::Matrix<double,Nodes::DIM,Tetra::NPI> _gradV;
125  calc_gradV(tet, _gradV);
126  gradV.push_back(_gradV);
127 
128  Eigen::Matrix<double,Nodes::DIM,Tetra::NPI> _Hm;
129  calc_Hm(tet, _gradV, _Hm);
130  Hm.push_back(_Hm);
131  });
132  prepareExtras();
133  }
134  else
135  {
136  std::cerr << "Solver (STT) has not converged" << std::endl;
137  exit(1);
138  }
139  }
140 
142  void calc_gradV(Tetra::Tet const &tet, Eigen::Ref<Eigen::Matrix<double,Nodes::DIM,Tetra::NPI>> _gradV) const
143  {
144  for (int npi = 0; npi < Tetra::NPI; npi++)
145  {
146  Eigen::Vector3d v(0,0,0);
147  for (int i = 0; i < Tetra::N; i++)
148  {
149  v += V[tet.ind[i]] * tet.da.row(i);
150  }
151  _gradV.col(npi) = v;
152  }
153  }
154 
156  void calc_Hm(Tetra::Tet const &tet, Eigen::Ref<Eigen::Matrix<double,Nodes::DIM,Tetra::NPI>> _gradV,
157  Eigen::Ref<Eigen::Matrix<double,Nodes::DIM,Tetra::NPI>> _Hm) const
158  {
159  Eigen::Matrix<double,Nodes::DIM,Tetra::NPI> p_g;
160  tet.getPtGauss(p_g);
161 
162  for (int npi = 0; npi < Tetra::NPI; npi++)
163  { _Hm.col(npi) = -p_stt.sigma * _gradV.col(npi).cross(p_g.col(npi)); }
164  }
165 
166 private:
168  void prepareExtras(void)
169  {
170  std::for_each(
171  msh.tet.begin(), msh.tet.end(),
172  [this](Tetra::Tet &tet)
173  {
174  const int _idx = tet.idx;
175  tet.extraField = [this, _idx](Eigen::Ref<Eigen::Matrix<double,Nodes::DIM,Tetra::NPI>> H)
176  {
177  for(int npi = 0; npi<Tetra::NPI; npi++) { H.col(npi) += Hm[_idx].col(npi); }
178  };
179 
180  tet.extraCoeffs_BE = [this, &tet](double Js, Eigen::Ref<Eigen::Matrix<double,Nodes::DIM,Tetra::NPI>> U,
181  Eigen::Ref<Eigen::Matrix<double,Nodes::DIM,Tetra::NPI>> dUdx,
182  Eigen::Ref<Eigen::Matrix<double,Nodes::DIM,Tetra::NPI>> dUdy,
183  Eigen::Ref<Eigen::Matrix<double,Nodes::DIM,Tetra::NPI>> dUdz,
184  Eigen::Ref<Eigen::Matrix<double,Nodes::DIM,Tetra::N>> BE)
185  {
186  const double prefactor = D0 / Nodes::sq(p_stt.lJ) / (gamma0*Js/mu0);
187  for (int npi = 0; npi < Tetra::NPI; npi++)
188  {
189  Eigen::Vector3d const &_gV = gradV[tet.idx].col(npi);
190  Eigen::Vector3d j_grad_u =
191  -p_stt.sigma
192  * Eigen::Vector3d(_gV.dot( Eigen::Vector3d(dUdx(Nodes::IDX_X,npi), dUdy(Nodes::IDX_X,npi), dUdz(Nodes::IDX_X,npi))),
193  _gV.dot( Eigen::Vector3d(dUdx(Nodes::IDX_Y,npi), dUdy(Nodes::IDX_Y,npi), dUdz(Nodes::IDX_Y,npi))),
194  _gV.dot( Eigen::Vector3d(dUdx(Nodes::IDX_Z,npi), dUdy(Nodes::IDX_Z,npi), dUdz(Nodes::IDX_Z,npi))));
195 
196  Eigen::Vector3d m = pf * (ksi * j_grad_u + U.col(npi).cross(j_grad_u));
197  for (int i = 0; i < Tetra::N; i++)
198  {
199  const double ai_w = tet.weight[npi] * Tetra::a[i][npi];
200  BE.col(i) += ai_w*(Hm[tet.idx].col(npi) + prefactor*m);
201  }
202  } // end loop on npi
203  }; //end lambda
204  });//end for_each
205  }
206 
208  double ksi;
209 
211  double D0;
212 
214  double pf;
215 
219 
222 
224  const bool verbose;
225 
227  const unsigned int MAXITER; // fixed to 5000 in ref code
228 
230  const int precision;
231 
233  const std::string fileName;
234 
237  std::vector<double> V;
238 
240  std::vector< Eigen::Matrix<double,Nodes::DIM,Tetra::NPI> > gradV;
241 
244  std::vector< Eigen::Matrix<double,Nodes::DIM,Tetra::NPI> > Hm;
245 
247  inline void infos(void)
248  {
249  std::cout << "sigma: " << p_stt.sigma << std::endl;
250 
251  std::for_each(p_stt.boundaryCond.begin(), p_stt.boundaryCond.end(),
252  [](std::pair<std::string, double> const &p)
253  { std::cout << "regName: " << p.first << "\tV :" << p.second << std::endl; });
254  }
255 
257  void prepareData(std::vector<Eigen::Triplet<double>> &Kw, Eigen::Ref<Eigen::VectorXd> Lw)
258  {
259  const double sigma = p_stt.sigma;
260 
261  std::for_each(msh.tet.begin(), msh.tet.end(),
262  [this, sigma, &Kw](Tetra::Tet const &tet)
263  {
264  double K[Tetra::N][Tetra::N] = {{0}};
265  integrales(tet, sigma, K);
266  assembling_mat(tet, K, Kw);
267  });
268 
269  double pot_val = 0; // we initialize pot_val to the average of the potentials set by the
270  // boundary conditions (does not seem to change convergence speed
271  // whatever value it is ..)
272  std::for_each(p_stt.boundaryCond.begin(), p_stt.boundaryCond.end(),
273  [&pot_val](auto const &it) { pot_val += it.second; });
274  pot_val /= p_stt.boundaryCond.size();
275 
276  std::for_each(msh.fac.begin(), msh.fac.end(),
277  [this, pot_val, &Lw](Facette::Fac const &fac)
278  {
279  std::vector<double> L(Facette::N);
280  integrales(fac, pot_val, L);
281  assembling_vect(fac, L, Lw);
282  });
283  }
284 
287  int solve(const double _tol)
288  {
289  const int NOD = msh.getNbNodes();
290 
291  std::vector<Eigen::Triplet<double>> Kw;
292  Eigen::VectorXd Lw = Eigen::VectorXd::Zero(NOD);
293  prepareData(Kw, Lw);
294 
295  Eigen::VectorXd Xw(NOD);
296  /* do something here with boundary conditions */
297 
298  if (verbose)
299  { std::cout << "line weighting..." << std::endl; }
300 
301  Eigen::SparseMatrix<double> Kr(NOD,NOD);
302  Kr.setFromTriplets(Kw.begin(),Kw.end());
303  std::vector<double> maxRow(NOD,0);
304 
305  //here we fill the vector maxRow with infinity norm : maxRow[i] = max{|Kr.row(i)|}
306  for(int i=0;i<NOD;i++)
307  {
308  for(int k=0;k<Kr.outerSize();++k)
309  for(Eigen::SparseMatrix<double>::InnerIterator it(Kr,k); it; ++it)
310  { if((it.row() == i)&&(fabs(it.value()) > maxRow[i])) { maxRow[i] = fabs(it.value()); } }
311  }
312 
313  for (int i = 0; i < NOD; i++)
314  {
315  double norme = maxRow[i];
316 
317  Lw[i] /= norme;
318  Kr.row(i) /= norme;
319  }
320 
321  if (verbose)
322  { std::cout << "solving ..." << std::endl; }
323 
324  Eigen::BiCGSTAB<Eigen::SparseMatrix<double>> _solver;
325 
326  _solver.setTolerance(_tol);
327  _solver.setMaxIterations(MAXITER);
328  _solver.compute(Kr);
329 
330  Eigen::VectorXd sol = _solver.solve(Lw);
331  for (int i=0;i<NOD;i++)
332  { V[i]= sol(i); }
333  return (_solver.iterations() < MAXITER);
334  }
335 
336  }; // end class electrostatSolver
Definition: facette.h:69
Definition: mesh.h:27
int getNbNodes(void) const
Definition: mesh.h:74
void savesol(const int precision, const std::string fileName, std::string const &metadata) const
Definition: save.cpp:127
std::vector< Tetra::Tet > tet
Definition: mesh.h:137
std::vector< Facette::Fac > fac
Definition: mesh.h:134
Definition: tetra.h:124
void getPtGauss(Eigen::Ref< Eigen::Matrix< double, Nodes::DIM, NPI >> result) const
Definition: tetra.h:320
std::function< void(double Js, Eigen::Ref< Eigen::Matrix< double, Nodes::DIM, NPI >> U, Eigen::Ref< Eigen::Matrix< double, Nodes::DIM, NPI >> dUdx, Eigen::Ref< Eigen::Matrix< double, Nodes::DIM, NPI >> dUdy, Eigen::Ref< Eigen::Matrix< double, Nodes::DIM, NPI >> dUdz, Eigen::Ref< Eigen::Matrix< double, Nodes::DIM, N >> BE)> extraCoeffs_BE
Definition: tetra.h:317
Eigen::Matrix< double, N, Nodes::DIM > da
Definition: tetra.h:169
Definition: electrostatSolver.h:81
int solve(const double _tol)
Definition: electrostatSolver.h:287
std::vector< Eigen::Matrix< double, Nodes::DIM, Tetra::NPI > > Hm
Definition: electrostatSolver.h:244
const std::string fileName
Definition: electrostatSolver.h:233
const bool verbose
Definition: electrostatSolver.h:224
const int precision
Definition: electrostatSolver.h:230
const unsigned int MAXITER
Definition: electrostatSolver.h:227
Mesh::mesh msh
Definition: electrostatSolver.h:218
double D0
Definition: electrostatSolver.h:211
electrostatSolver(Mesh::mesh const &_msh, STT const &_p_stt, const double _tol, const bool v, const int max_iter, const std::string _fileName)
Definition: electrostatSolver.h:84
std::vector< double > V
Definition: electrostatSolver.h:237
void prepareExtras(void)
Definition: electrostatSolver.h:168
std::vector< Eigen::Matrix< double, Nodes::DIM, Tetra::NPI > > gradV
Definition: electrostatSolver.h:240
double ksi
Definition: electrostatSolver.h:208
STT p_stt
Definition: electrostatSolver.h:221
void infos(void)
Definition: electrostatSolver.h:247
double pf
Definition: electrostatSolver.h:214
void calc_gradV(Tetra::Tet const &tet, Eigen::Ref< Eigen::Matrix< double, Nodes::DIM, Tetra::NPI >> _gradV) const
Definition: electrostatSolver.h:142
void prepareData(std::vector< Eigen::Triplet< double >> &Kw, Eigen::Ref< Eigen::VectorXd > Lw)
Definition: electrostatSolver.h:257
void calc_Hm(Tetra::Tet const &tet, Eigen::Ref< Eigen::Matrix< double, Nodes::DIM, Tetra::NPI >> _gradV, Eigen::Ref< Eigen::Matrix< double, Nodes::DIM, Tetra::NPI >> _Hm) const
Definition: electrostatSolver.h:156
Eigen::Matrix< double, NPI, 1 > weight
Definition: element.h:48
std::vector< int > ind
Definition: element.h:42
void integrales(Tetra::Tet const &tet, double sigma, double AE[Tetra::N][Tetra::N])
Definition: electrostatSolver.h:43
void assembling_vect(Facette::Fac const &fac, std::vector< double > const &Le, Eigen::Ref< Eigen::VectorXd > L)
Definition: electrostatSolver.h:35
void assembling_mat(Tetra::Tet const &tet, double Ke[Tetra::N][Tetra::N], std::vector< Eigen::Triplet< double >> &K)
Definition: electrostatSolver.h:21
contains namespace Facette header containing Fac class, and some constants and a less_than operator t...
principal header, contains the struct fem This file is called by many source files in feellgood....
class mesh, readMesh is expecting a mesh file in gmsh format either text or binary,...
const int N
Definition: facette.h:17
constexpr double v[NPI]
Definition: facette.h:22
const int NPI
Definition: facette.h:18
constexpr double a[N][NPI]
Definition: facette.h:28
double sq(const double x)
Definition: node.h:42
const int NPI
Definition: tetra.h:23
const int N
Definition: tetra.h:22
constexpr double w[NPI]
Definition: tetra.h:36
Definition: spinTransferTorque.h:13
double sigma
Definition: spinTransferTorque.h:21
double lsf
Definition: spinTransferTorque.h:27
double beta
Definition: spinTransferTorque.h:15
double lJ
Definition: spinTransferTorque.h:24
double N0
Definition: spinTransferTorque.h:18
std::vector< std::pair< std::string, double > > boundaryCond
Definition: spinTransferTorque.h:36
bool V_file
Definition: spinTransferTorque.h:31
namespace Tetra header containing Tet class, some constants, and integrales