Extension: Geometries
#include "dg/geometries/geometries.h"
Loading...
Searching...
No Matches
solovev.h
Go to the documentation of this file.
1#pragma once
2
3#include <iostream>
4#include <cmath>
5#include <vector>
6
7#include "dg/blas.h"
8
9#include "dg/algorithm.h"
10#include "solovev_parameters.h"
11#include "magnetic_field.h"
12#include "modified.h"
13
14
19namespace dg
20{
21namespace geo
22{
28namespace solovev
29{
32
60struct Psip: public aCylindricalFunctor<Psip>
61{
67 Psip( const Parameters& gp ): m_R0(gp.R_0), mA(gp.A), m_pp(gp.pp), mc(gp.c) {
68 m_prev = std::make_shared< std::array<double,3>>(std::array<double,3>{ 0,0,0});
69 }
70 double do_compute(double R, double Z) const
71 {
72 // Optimization rationale: The way we compute magnetic field terms
73 // through the TokamakMagneticField class and e.g. the BHatR class
74 // leads to repeated evaluations of Psip, PsipR, etc. at the same
75 // point. We thus let the Psip classes remember the result of the
76 // previous call to avoid recomputing the same point. Since the
77 // different calls are made through different copies of Psip we need to
78 // store the previous results in a shared_ptr such that all copies of
79 // Psip have access to it
80 if( R == (*m_prev)[0] && Z == (*m_prev)[1])
81 return (*m_prev)[2];
82
83 double Rn = R / m_R0, Rn2 = Rn * Rn, lgRn = log(Rn);
84 double Zn = Z/m_R0;
85 // Copied from Mathematica ...
86 (*m_prev)[2] = m_R0*m_pp*(mc[0] + Rn2 * ((lgRn * mA) / 2. + mc[1] +
87 Zn * (mc[8] + Zn *
88 (-4 * mc[3] - 9 * mc[4] +
89 Zn * (Zn * (8 * mc[5] - 140 * mc[6]) -
90 4 * mc[10]))) +
91 lgRn * (-mc[2] +
92 Zn * (-3 * mc[9] +
93 Zn * (-12 * mc[4] +
94 Zn * (-120 * Zn * mc[6] - 80 * mc[11]))
95 )) + Rn2 *
96 (0.125 - mA / 8. + mc[3] +
97 Rn2 * (mc[5] - 15 * lgRn * mc[6]) +
98 Zn * (Zn * (-12 * mc[5] + 75 * mc[6]) +
99 3 * mc[10] - 45 * mc[11]) +
100 lgRn * (3 * mc[4] +
101 Zn * (180 * Zn * mc[6] + 60 * mc[11]))))\
102 + Zn * (mc[7] + Zn *
103 (mc[2] + Zn *
104 (mc[9] +
105 Zn * (2 * mc[4] +
106 Zn * (8 * Zn * mc[6] + 8 * mc[11])))))
107 );
108 (*m_prev)[0] = R, (*m_prev)[1] = Z;
109 return (*m_prev)[2];
110 }
111 private:
112 double m_R0, mA, m_pp;
113 std::vector<double> mc;
114 std::shared_ptr<std::array<double,3>> m_prev;
115};
116
135struct PsipR: public aCylindricalFunctor<PsipR>
136{
138 PsipR( const Parameters& gp ): m_R0(gp.R_0), mA(gp.A), m_pp(gp.pp), mc(gp.c) {
139 m_prev = std::make_shared< std::array<double,3>>(std::array<double,3>{ 0,0,0});
140 }
141 double do_compute(double R, double Z) const
142 {
143 if( R == (*m_prev)[0] && Z == (*m_prev)[1])
144 return (*m_prev)[2];
145 double Rn = R / m_R0, Rn2 = Rn * Rn, lgRn = log(Rn);
146 double Zn = Z / m_R0;
147 // Copied from Mathematica ...
148 (*m_prev)[2] = m_pp * (mA * Rn * (0.5 + lgRn - Rn2 / 2.) +
149 Rn * (2 * mc[1] - mc[2] -
150 8 * Zn * Zn * mc[3] +
151 lgRn * (-2 * mc[2] +
152 Zn * (-6 * mc[9] +
153 Zn * (-24 * mc[4] +
154 Zn * (-240 * Zn * mc[6] - 160 * mc[11])
155 ))) +
156 Zn * (2 * mc[8] - 3 * mc[9] +
157 Zn * (-30 * mc[4] +
158 Zn * (Zn * (16 * mc[5] - 400 * mc[6]) -
159 8 * mc[10] - 80 * mc[11]))) +
160 Rn2 * (0.5 + 4 * mc[3] + 3 * mc[4] +
161 Rn2 * (6 * mc[5] - 15 * mc[6] -
162 90 * lgRn * mc[6]) +
163 Zn * (Zn * (-48 * mc[5] + 480 * mc[6]) +
164 12 * mc[10] - 120 * mc[11]) +
165 lgRn * (12 * mc[4] +
166 Zn * (720 * Zn * mc[6] + 240 * mc[11]))))
167 );
168 (*m_prev)[0] = R, (*m_prev)[1] = Z;
169 return (*m_prev)[2];
170 }
171 private:
172 double m_R0, mA, m_pp;
173 std::vector<double> mc;
174 std::shared_ptr<std::array<double,3>> m_prev;
175};
193struct PsipRR: public aCylindricalFunctor<PsipRR>
194{
196 PsipRR( const Parameters& gp ): m_R0(gp.R_0), mA(gp.A), m_pp(gp.pp), mc(gp.c) {
197 m_prev = std::make_shared< std::array<double,3>>(std::array<double,3>{ 0,0,0});
198 }
199 double do_compute(double R, double Z) const
200 {
201 if( R == (*m_prev)[0] && Z == (*m_prev)[1])
202 return (*m_prev)[2];
203 double Rn = R / m_R0, Rn2 = Rn * Rn, lgRn = log(Rn);
204 double Zn = Z / m_R0;
205 // Copied from Mathematica ...
206 (*m_prev)[2] = m_pp/m_R0 * (mA * (1.5 + lgRn - (3 * Rn2) / 2.) + 2 * mc[1] -
207 3 * mc[2] - 8 * Zn * Zn * mc[3] +
208 lgRn * (-2 * mc[2] +
209 Zn * (-6 * mc[9] +
210 Zn * (-24 * mc[4] +
211 Zn * (-240 * Zn * mc[6] - 160 * mc[11]))))
212 + Zn * (2 * mc[8] - 9 * mc[9] +
213 Zn * (-54 * mc[4] +
214 Zn * (Zn * (16 * mc[5] - 640 * mc[6]) -
215 8 * mc[10] - 240 * mc[11]))) +
216 Rn2 * (1.5 + 12 * mc[3] + 21 * mc[4] +
217 Rn2 * (30 * mc[5] - 165 * mc[6] -
218 450 * lgRn * mc[6]) +
219 Zn * (Zn * (-144 * mc[5] + 2160 * mc[6]) +
220 36 * mc[10] - 120 * mc[11]) +
221 lgRn * (36 * mc[4] +
222 Zn * (2160 * Zn * mc[6] + 720 * mc[11])))
223 );
224 (*m_prev)[0] = R, (*m_prev)[1] = Z;
225 return (*m_prev)[2];
226 }
227 private:
228 double m_R0, mA, m_pp;
229 std::vector<double> mc;
230 std::shared_ptr<std::array<double,3>> m_prev;
231};
246struct PsipZ: public aCylindricalFunctor<PsipZ>
247{
249 PsipZ( const Parameters& gp ): m_R0(gp.R_0), m_pp(gp.pp), mc(gp.c) {
250 m_prev = std::make_shared< std::array<double,3>>(std::array<double,3>{ 0,0,0});
251 }
252 double do_compute(double R, double Z) const
253 {
254 if( R == (*m_prev)[0] && Z == (*m_prev)[1])
255 return (*m_prev)[2];
256 double Rn = R / m_R0, Rn2 = Rn * Rn, lgRn = log(Rn);
257 double Zn = Z / m_R0;
258 // Copied from Mathematica ...
259 (*m_prev)[2] = m_pp * (mc[7] + Rn2 * (mc[8] - 3 * lgRn * mc[9] +
260 Rn2 * (3 * mc[10] - 45 * mc[11] +
261 60 * lgRn * mc[11])) +
262 Zn * (2 * mc[2] + Rn2 *
263 (-8 * mc[3] + (-18 - 24 * lgRn) * mc[4] +
264 Rn2 * (-24 * mc[5] + 150 * mc[6] +
265 360 * lgRn * mc[6])) +
266 Zn * (3 * mc[9] +
267 Rn2 * (-12 * mc[10] - 240 * lgRn * mc[11]) +
268 Zn * (8 * mc[4] +
269 Rn2 * (32 * mc[5] - 560 * mc[6] -
270 480 * lgRn * mc[6]) +
271 Zn * (48 * Zn * mc[6] + 40 * mc[11]))))
272 );
273 (*m_prev)[0] = R, (*m_prev)[1] = Z;
274 return (*m_prev)[2];
275
276 }
277 private:
278 double m_R0, m_pp;
279 std::vector<double> mc;
280 std::shared_ptr<std::array<double,3>> m_prev;
281};
293struct PsipZZ: public aCylindricalFunctor<PsipZZ>
294{
296 PsipZZ( const Parameters& gp): m_R0(gp.R_0), m_pp(gp.pp), mc(gp.c) {
297 m_prev = std::make_shared< std::array<double,3>>(std::array<double,3>{ 0,0,0});
298 }
299 double do_compute(double R, double Z) const
300 {
301 if( R == (*m_prev)[0] && Z == (*m_prev)[1])
302 return (*m_prev)[2];
303 double Rn = R / m_R0, Rn2 = Rn * Rn, lgRn = log(Rn);
304 double Zn = Z / m_R0;
305 // Copied from Mathematica ...
306 (*m_prev)[2] = m_pp/m_R0 * (2 * mc[2] + 24 * Zn * Zn * mc[4] +
307 Zn * (6 * mc[9] + Zn * Zn *
308 (240 * Zn * mc[6] + 160 * mc[11])) +
309 Rn2 * (-8 * mc[3] + (-18 - 24 * lgRn) * mc[4] +
310 Rn2 * (-24 * mc[5] + 150 * mc[6] +
311 360 * lgRn * mc[6]) +
312 Zn * (Zn * (96 * mc[5] - 1680 * mc[6] -
313 1440 * lgRn * mc[6]) - 24 * mc[10] -
314 480 * lgRn * mc[11]))
315 );
316 (*m_prev)[0] = R, (*m_prev)[1] = Z;
317 return (*m_prev)[2];
318 }
319 private:
320 double m_R0, m_pp;
321 std::vector<double> mc;
322 std::shared_ptr<std::array<double,3>> m_prev;
323};
337struct PsipRZ: public aCylindricalFunctor<PsipRZ>
338{
340 PsipRZ( const Parameters& gp ): m_R0(gp.R_0), m_pp(gp.pp), mc(gp.c) {
341 m_prev = std::make_shared< std::array<double,3>>(std::array<double,3>{ 0,0,0});
342 }
343 double do_compute(double R, double Z) const
344 {
345 if( R == (*m_prev)[0] && Z == (*m_prev)[1])
346 return (*m_prev)[2];
347 double Rn = R / m_R0, Rn2 = Rn * Rn, lgRn = log(Rn);
348 double Zn = Z / m_R0;
349 // Copied from Mathematica ...
350 (*m_prev)[2] = m_pp/m_R0 * (Rn * (2 * mc[8] - 3 * mc[9] - 6 * lgRn * mc[9] +
351 Rn2 * (Zn * (-96 * mc[5] + 960 * mc[6] +
352 1440 * lgRn * mc[6]) + 12 * mc[10] -
353 120 * mc[11] + 240 * lgRn * mc[11]) +
354 Zn * (-16 * mc[3] + (-60 - 48 * lgRn) * mc[4] +
355 Zn * (Zn * (64 * mc[5] - 1600 * mc[6] -
356 960 * lgRn * mc[6]) - 24 * mc[10] -
357 240 * mc[11] - 480 * lgRn * mc[11])))
358 );
359 (*m_prev)[0] = R, (*m_prev)[1] = Z;
360 return (*m_prev)[2];
361 }
362 private:
363 double m_R0, m_pp;
364 std::vector<double> mc;
365 std::shared_ptr<std::array<double,3>> m_prev;
366};
367
373struct Ipol: public aCylindricalFunctor<Ipol>
374{
381 Ipol( const Parameters &gp, const std::function<double(double,double)>& psip ): m_R0(gp.R_0), m_A(gp.A), m_pp(gp.pp), m_pi(gp.pi), m_psip(psip) {
382 if( gp.pp == 0.)
383 m_pp = 1.; //safety measure to avoid divide by zero errors
384 }
385 double do_compute(double R, double Z) const
386 {
387 return m_pi*sqrt(-2.*m_A* m_psip(R,Z) /m_R0/m_pp + 1.);
388 }
389 private:
390 double m_R0, m_A, m_pp, m_pi;
391 std::function<double(double,double)> m_psip;
392};
396struct IpolR: public aCylindricalFunctor<IpolR>
397{
402 IpolR( const Parameters& gp, const std::function<double(double,double)>& psip, std::function<double(double,double)> psipR ):
403 m_R0(gp.R_0), m_A(gp.A), m_pp(gp.pp), m_pi(gp.pi), m_psip(psip), m_psipR(psipR) {
404 if( gp.pp == 0.)
405 m_pp = 1.; //safety measure to avoid divide by zero errors
406 }
407 double do_compute(double R, double Z) const
408 {
409 return -m_pi/sqrt(-2.*m_A* m_psip(R,Z) /m_R0/m_pp + 1.)*(m_A*m_psipR(R,Z)/m_R0/m_pp);
410 }
411 private:
412 double m_R0, m_A, m_pp, m_pi;
413 std::function<double(double,double)> m_psip, m_psipR;
414};
418struct IpolZ: public aCylindricalFunctor<IpolZ>
419{
424 IpolZ( const Parameters& gp, const std::function<double(double,double)>& psip, std::function<double(double,double)> psipZ ):
425 m_R0(gp.R_0), m_A(gp.A), m_pp(gp.pp), m_pi(gp.pi), m_psip(psip), m_psipZ(psipZ) {
426 if( gp.pp == 0.)
427 m_pp = 1.; //safety measure to avoid divide by zero errors
428 }
429 double do_compute(double R, double Z) const
430 {
431 return -m_pi/sqrt(-2.*m_A* m_psip(R,Z) /m_R0/m_pp + 1.)*(m_A*m_psipZ(R,Z)/m_R0/m_pp);
432 }
433 private:
434 double m_R0, m_A, m_pp, m_pi;
435 std::function<double(double,double)> m_psip, m_psipZ;
436};
437
439{
440 return CylindricalFunctorsLvl2( Psip(gp), PsipR(gp), PsipZ(gp),
441 PsipRR(gp), PsipRZ(gp), PsipZZ(gp));
442}
444{
446 solovev::Ipol(gp, psip.f()),
447 solovev::IpolR(gp,psip.f(), psip.dfx()),
448 solovev::IpolZ(gp,psip.f(), psip.dfy()));
449}
450
453
454} //namespace solovev
455
466{
468 equilibrium::solovev, modifier::none, str2description.at( gp.description)};
469 auto psip = solovev::createPsip(gp); // make sure prev is shared
470 return TokamakMagneticField( gp.R_0, psip,
471 solovev::createIpol(gp, psip), params);
472}
491 const dg::geo::solovev::Parameters& gp, double psi0, double alpha, double sign = -1)
492{
494 equilibrium::solovev, modifier::heaviside, str2description.at( gp.description)};
495 auto psip = solovev::createPsip(gp); // make sure prev is shared
496 return TokamakMagneticField( gp.R_0,
497 mod::createPsip( mod::everywhere, psip, psi0, alpha, sign),
498 solovev::createIpol( gp, mod::createPsip( mod::everywhere, psip, psi0, alpha, sign)),
499 params);
500}
501
502} //namespace geo
503} //namespace dg
504
@ none
no modification
@ heaviside
Psip is dampened to a constant outside a critical value.
@ solovev
dg::geo::solovev::Psip
dg::geo::CylindricalFunctorsLvl2 createPsip(const std::function< bool(double, double)> predicate, const CylindricalFunctorsLvl2 &psip, double psi0, double alpha, double sign=-1)
Definition modified.h:175
dg::geo::CylindricalFunctorsLvl1 createIpol(const Parameters &gp, const CylindricalFunctorsLvl1 &psip)
Definition solovev.h:443
dg::geo::TokamakMagneticField createSolovevField(const dg::geo::solovev::Parameters &gp)
Create a Solovev Magnetic field.
Definition solovev.h:464
dg::geo::CylindricalFunctorsLvl2 createPsip(const Parameters &gp)
Definition solovev.h:438
dg::geo::TokamakMagneticField createModifiedSolovevField(const dg::geo::solovev::Parameters &gp, double psi0, double alpha, double sign=-1)
DEPRECATED Create a modified Solovev Magnetic field.
Definition solovev.h:490
This struct bundles a function and its first derivatives.
Definition fluxfunctions.h:185
const CylindricalFunctor & dfx() const
Definition fluxfunctions.h:208
const CylindricalFunctor & f() const
Definition fluxfunctions.h:206
const CylindricalFunctor & dfy() const
Definition fluxfunctions.h:210
This struct bundles a function and its first and second derivatives.
Definition fluxfunctions.h:222
Meta-data about the magnetic field in particular the flux function.
Definition magnetic_field.h:101
A tokamak field as given by R0, Psi and Ipol plus Meta-data like shape and equilibrium.
Definition magnetic_field.h:172
Represent functions written in cylindrical coordinates that are independent of the angle phi serving ...
Definition fluxfunctions.h:66
Definition solovev.h:374
double do_compute(double R, double Z) const
Definition solovev.h:385
Ipol(const Parameters &gp, const std::function< double(double, double)> &psip)
Construct from given geometric parameters.
Definition solovev.h:381
Definition solovev.h:397
IpolR(const Parameters &gp, const std::function< double(double, double)> &psip, std::function< double(double, double)> psipR)
Construct from given geometric parameters.
Definition solovev.h:402
double do_compute(double R, double Z) const
Definition solovev.h:407
Definition solovev.h:419
IpolZ(const Parameters &gp, const std::function< double(double, double)> &psip, std::function< double(double, double)> psipZ)
Construct from given geometric parameters.
Definition solovev.h:424
double do_compute(double R, double Z) const
Definition solovev.h:429
Constructs and display geometric parameters for the solovev and taylor fields.
Definition solovev_parameters.h:43
double pp
prefactor for Psi_p
Definition solovev_parameters.h:46
double R_0
major tokamak radius
Definition solovev_parameters.h:45
double a
little tokamak radius
Definition solovev_parameters.h:48
std::string description
Definition solovev_parameters.h:52
double elongation
elongation of the magnetic surfaces
Definition solovev_parameters.h:49
double triangularity
triangularity of the magnetic surfaces
Definition solovev_parameters.h:50
Definition solovev.h:61
double do_compute(double R, double Z) const
Definition solovev.h:70
Psip(const Parameters &gp)
Construct from given geometric parameters.
Definition solovev.h:67
Definition solovev.h:136
double do_compute(double R, double Z) const
Definition solovev.h:141
PsipR(const Parameters &gp)
Construct from given geometric parameters.
Definition solovev.h:138
Definition solovev.h:194
double do_compute(double R, double Z) const
Definition solovev.h:199
PsipRR(const Parameters &gp)
Construct from given geometric parameters.
Definition solovev.h:196
Definition solovev.h:338
double do_compute(double R, double Z) const
Definition solovev.h:343
PsipRZ(const Parameters &gp)
Construct from given geometric parameters.
Definition solovev.h:340
Definition solovev.h:247
double do_compute(double R, double Z) const
Definition solovev.h:252
PsipZ(const Parameters &gp)
Construct from given geometric parameters.
Definition solovev.h:249
Definition solovev.h:294
PsipZZ(const Parameters &gp)
Construct from given geometric parameters.
Definition solovev.h:296
double do_compute(double R, double Z) const
Definition solovev.h:299