Extension: Geometries
#include "dg/geometries/geometries.h"
make_field.h
Go to the documentation of this file.
1#ifdef JSONCPP_VERSION_STRING
2#include "magnetic_field.h"
3#include "solovev.h"
4#include "guenter.h"
5#include "polynomial.h"
6#include "toroidal.h"
7#include "fieldaligned.h"
8#include <dg/file/json_utilities.h>
9
14namespace dg{
15namespace geo{
16
75static inline TokamakMagneticField createMagneticField( dg::file::WrappedJsonValue gs)
76{
77 std::string e = gs.get( "equilibrium", "solovev" ).asString();
79 try{
80 equi = str2equilibrium.at( e);
81 }catch ( std::out_of_range& err)
82 {
83 std::string message = "ERROR: Key \"" + e
84 + "\" not valid in field:\n\t"
85 + gs.access_string() + "\"equilibrium\" \n";
86 throw std::out_of_range(message);
87 }
88 switch( equi){
90 {
92 return createPolynomialField( gp);
93 }
95 {
96 double R0 = gs.get( "R_0", 10.0).asDouble();
97 return createToroidalField( R0);
98 }
100 {
101 double I0 = gs.get( "I_0", 20.0).asDouble();
102 double R0 = gs.get( "R_0", 10.0).asDouble();
103 return createGuenterField( R0, I0);
104 }
106 {
107 double I0 = gs.get( "I_0", 20.0).asDouble();
108 double R0 = gs.get( "R_0", 10.0).asDouble();
109 double a = gs.get( "a", 1.0).asDouble();
110 double b = gs.get( "b", 1.0).asDouble();
111 return createCircularField( R0, I0, a, b);
112 }
113#ifdef BOOST_VERSION
115 {
116 solovev::Parameters gp( gs);
117 return createTaylorField( gp);
118 }
119#endif
120 default:
121 {
122 solovev::Parameters gp( gs);
123 return createSolovevField( gp);
124 }
125 }
126}
127
128
130namespace detail{
131void transform_psi( TokamakMagneticField mag, double& psi0, double& alpha0, double& sign0)
132{
133 double RO=mag.R0(), ZO=0.;
134 dg::geo::findOpoint( mag.get_psip(), RO, ZO);
135 double psipO = mag.psip()( RO, ZO);
136 double wall_psi0p = (1.-psi0*psi0)*psipO;
137 double wall_alpha0p = -(2.*psi0+alpha0)*alpha0*psipO;
138 psi0 = wall_psi0p + sign0*wall_alpha0p/2.;
139 alpha0 = fabs( wall_alpha0p/2.);
140 sign0 = sign0*((psipO>0)-(psipO<0));
141}
142}//namespace detail
144
147
183 dg::file::WrappedJsonValue gs, dg::file::WrappedJsonValue jsmod,
184 CylindricalFunctor& wall, CylindricalFunctor& transition)
185{
187 const MagneticFieldParameters& inp = mag.params();
188 description desc = inp.getDescription();
189 equilibrium equi = inp.getEquilibrium();
190 std::string m = jsmod.get( "type", "heaviside" ).asString();
191 modifier mod = str2modifier.at( m);
192 MagneticFieldParameters mod_params{ inp.a(), inp.elongation(),
193 inp.triangularity(), equi, mod, desc};
195 switch (mod) {
196 default: //none
197 {
198 wall = mod::DampingRegion( mod::nowhere, mag.psip(), 0, 1, -1);
199 transition = mod::MagneticTransition( mod::nowhere, mag.psip(),
200 0, 1, -1);
201 return mag;
202 }
204 {
205 double psi0 = jsmod.get( "boundary", 1.1 ).asDouble();
206 double alpha = jsmod.get( "alpha", 0.2 ).asDouble();
207 double sign = +1;
208 if( desc == description::standardX || desc == description::standardO ||
209 desc == description::doubleX)
210 detail::transform_psi( mag, psi0, alpha, sign);
211 else
212 sign = jsmod.get( "sign", -1. ).asDouble();
213
214 mod_psip = mod::createPsip( mod::everywhere, mag.get_psip(), psi0, alpha, sign);
215 wall = mod::DampingRegion( mod::everywhere, mag.psip(), psi0, alpha, -sign);
216 transition = mod::MagneticTransition( mod::everywhere, mag.psip(), psi0, alpha, sign);
217 break;
218 }
220 {
221 double psi0 = jsmod["boundary"].get( 0, 1.1 ).asDouble();
222 double alpha0 = jsmod["alpha"].get(0, 0.2 ).asDouble();
223 double psi1 = jsmod["boundary"].get(1, 0.97 ).asDouble();
224 double alpha1 = jsmod[ "alpha"].get(1, 0.2 ).asDouble();
225 switch( desc){
227 {
228 double sign0 = +1., sign1 = -1.;
229 detail::transform_psi( mag, psi0, alpha0, sign0);
230 detail::transform_psi( mag, psi1, alpha1, sign1);
231 //we can find the X-point
232 double RX = mag.R0()-1.1*mag.params().triangularity()*mag.params().a();
233 double ZX = -1.1*mag.params().elongation()*mag.params().a();
234 dg::geo::findXpoint( mag.get_psip(), RX, ZX);
235 CylindricalFunctorsLvl2 mod0_psip;
236 mod0_psip = mod::createPsip(
237 mod::everywhere, mag.get_psip(), psi0, alpha0, sign0);
238 mod_psip = mod::createPsip(
239 mod::HeavisideZ( ZX, -1), mod0_psip, psi1, alpha1, sign1);
240 CylindricalFunctor wall0 = mod::DampingRegion( mod::everywhere, mag.psip(), psi0, alpha0, -sign0);
241 CylindricalFunctor transition0 = mod::MagneticTransition( mod::everywhere, mag.psip(), psi0, alpha0, sign0);
242 CylindricalFunctor wall1 = mod::DampingRegion( mod::HeavisideZ(ZX, -1), mag.psip(), psi1, alpha1, -sign1);
243 CylindricalFunctor transition1 = mod::MagneticTransition( mod::HeavisideZ(ZX, -1), mag.psip(), psi1, alpha1, sign1);
244 wall = mod::SetUnion( wall0, wall1);
245 transition = mod::SetUnion( transition0, transition1);
246 break;
247 }
249 {
250 double sign0 = +1., sign1 = -1.;
251 detail::transform_psi( mag, psi0, alpha0, sign0);
252 detail::transform_psi( mag, psi1, alpha1, sign1);
253 //we can find the X-point
254 double RX1 = mag.R0()-1.1*mag.params().triangularity()*mag.params().a();
255 double ZX1 = -1.1*mag.params().elongation()*mag.params().a();
256 dg::geo::findXpoint( mag.get_psip(), RX1, ZX1);
257 double RX2 = mag.R0()-1.1*mag.params().triangularity()*mag.params().a();
258 double ZX2 = +1.1*mag.params().elongation()*mag.params().a();
259 dg::geo::findXpoint( mag.get_psip(), RX2, ZX2);
260 CylindricalFunctorsLvl2 mod0_psip, mod1_psip;
261 mod0_psip = mod::createPsip(
262 mod::everywhere, mag.get_psip(), psi0, alpha0, sign0);
263 mod1_psip = mod::createPsip(
264 mod::HeavisideZ( ZX1, -1), mod0_psip, psi1, alpha1, sign1);
265 mod_psip = mod::createPsip(
266 mod::HeavisideZ( ZX2, +1), mod1_psip, psi1, alpha1, sign1);
267 CylindricalFunctor wall0 = mod::DampingRegion( mod::everywhere, mag.psip(), psi0, alpha0, -sign0);
268 CylindricalFunctor wall1 = mod::DampingRegion( mod::HeavisideZ(ZX1, -1), mag.psip(), psi1, alpha1, -sign1);
269 CylindricalFunctor wall2 = mod::DampingRegion( mod::HeavisideZ(ZX2, +1), mag.psip(), psi1, alpha1, -sign1);
270 CylindricalFunctor transition0 = mod::MagneticTransition( mod::everywhere, mag.psip(), psi0, alpha0, sign0);
271 CylindricalFunctor transition1 = mod::MagneticTransition( mod::HeavisideZ(ZX1, -1), mag.psip(), psi1, alpha1, sign1);
272 CylindricalFunctor transition2 = mod::MagneticTransition( mod::HeavisideZ(ZX2, +1), mag.psip(), psi1, alpha1, sign1);
273 transition = mod::SetUnion( mod::SetUnion( transition0, transition1), transition2);
274 wall = mod::SetUnion( mod::SetUnion( wall0, wall1), wall2);
275 break;
276 }
277 default:
278 {
279 double sign0 = jsmod[ "sign"].get( 0, -1. ).asDouble();
280 double sign1 = jsmod[ "sign"].get( 1, +1. ).asDouble();
281 CylindricalFunctorsLvl2 mod0_psip;
282 mod0_psip = mod::createPsip(
283 mod::everywhere, mag.get_psip(), psi0, alpha0, sign0);
284 mod_psip = mod::createPsip(
285 mod::everywhere, mod0_psip, psi1, alpha1, sign1);
286 CylindricalFunctor wall0 = mod::DampingRegion( mod::everywhere, mag.psip(), psi0, alpha0, sign0);
287 CylindricalFunctor transition0 = mod::MagneticTransition( mod::everywhere, mag.psip(), psi0, alpha0, sign0);
288 CylindricalFunctor wall1 = mod::DampingRegion( mod::everywhere, mag.psip(), psi1, alpha1, sign1);
289 CylindricalFunctor transition1 = mod::MagneticTransition( mod::everywhere, mag.psip(), psi1, alpha1, sign1);
290 wall = mod::SetUnion( wall0, wall1);
291 transition = mod::SetUnion( transition0, transition1);
292 break;
293 }
294 }
295 }
296 }
297 switch( equi){
299 {
300 solovev::Parameters gp( gs);
301 return TokamakMagneticField( gp.R_0,mod_psip,
302 solovev::createIpol( gp, mod_psip), mod_params);
303 }
304 default:
305 {
306 return TokamakMagneticField( mag.R0(), mod_psip,
307 mag.get_ipol(), mod_params);
308 }
309 }
310}
311
312
314static inline CylindricalFunctor createWallRegion( dg::file::WrappedJsonValue gs, dg::file::WrappedJsonValue jsmod)
315{
316 CylindricalFunctor wall, transition;
317 TokamakMagneticField mag = createModifiedField( gs, jsmod, wall, transition);
318 return wall;
319}
320
350static inline void createSheathRegion(
351 dg::file::WrappedJsonValue jsmod, TokamakMagneticField mag,
352 CylindricalFunctor wall, dg::Grid2d& sheath_walls,
353 CylindricalFunctor& sheath)
354{
355 double R0 = sheath_walls.x0(), R1 = sheath_walls.x1();
356 double Z0 = sheath_walls.y0(), Z1 = sheath_walls.y1();
357 Grid1d gR1d ( R0, R1, 1, 100);
358 Grid1d gZ1d ( Z0, Z1, 1, 100);
359 std::array<bool,2> sheathR = {false,false}, sheathZ = {false,false};
360 for ( unsigned i=0; i<100; i++)
361 {
362 if( wall( R0+i*gR1d.h(), Z0) == 0)
363 sheathR[0] = true;
364 if( wall( R0+i*gR1d.h(), Z1) == 0)
365 sheathR[1] = true;
366 if( wall( R0, Z0 + i*gZ1d.h()) == 0)
367 sheathZ[0] = true;
368 if( wall( R1, Z0 + i*gZ1d.h()) == 0)
369 sheathZ[1] = true;
370 }
371 if( false == sheathR[0]) Z0 = -1e10;
372 if( false == sheathR[1]) Z1 = 1e10;
373 if( false == sheathZ[0]) R0 = -1e10;
374 if( false == sheathZ[1]) R1 = 1e10;
375 sheath_walls = dg::Grid2d( R0, R1, Z0, Z1, 1,1,1);
376 double boundary = jsmod.get( "boundary", 0.0625 ).asDouble(); // 1/16
377 double alpha = jsmod.get( "alpha", 0.015625 ).asDouble(); // 1/64
379 mag), sheath_walls, (-boundary-1e-3)*2.0*M_PI,
380 1e-6, "phi");
382 mag), sheath_walls, (+boundary+1e-3)*2.0*M_PI,
383 1e-6, "phi");
384 dg::PolynomialHeaviside polyM( -boundary*2.*M_PI + alpha*M_PI, alpha*M_PI, +1);
385 dg::PolynomialHeaviside polyP( boundary*2.*M_PI - alpha*M_PI, alpha*M_PI, -1);
386 auto sheathM = dg::compose( polyM, distM); //positive (because distance)
387 auto sheathP = dg::compose( polyP, distP);
388 sheath = mod::SetUnion( sheathM, sheathP);
389 sheath = mod::SetIntersection( mod::SetNot( wall), sheath);
390}
392
393} //namespace geo
394}//namespace dg
395#endif //JSONCPP_VERSION_STRING
#define M_PI
static dg::geo::TokamakMagneticField createCircularField(double R0, double I0, double a=1, double b=1)
Definition: toroidal.h:136
auto compose(UnaryOp f, Functor g)
static TokamakMagneticField createMagneticField(dg::file::WrappedJsonValue gs)
Create a Magnetic field based on the given parameters.
Definition: make_field.h:75
dg::RealGrid2d< double > Grid2d
static dg::geo::TokamakMagneticField createGuenterField(double R_0, double I_0)
Create a Guenter Magnetic field.
Definition: guenter.h:158
modifier
How flux-function is modified.
Definition: magnetic_field.h:36
equilibrium
How flux-function is computed. Decides how to construct magnetic field.
Definition: magnetic_field.h:26
description
How flux function looks like. Decider on whether and what flux aligned grid to construct.
Definition: magnetic_field.h:48
CylindricalVectorLvl1 createBHat(const TokamakMagneticField &mag)
Contravariant components of the magnetic unit vector field and its Divergence and derivative in cylin...
Definition: magnetic_field.h:931
@ sol_pfr
Psip is dampened in the SOL and PFR regions but not in the closed field line region.
@ heaviside
Psip is dampened to a constant outside a critical value.
@ solovev
dg::geo::solovev::Psip
@ taylor
dg::geo::taylor::Psip
@ polynomial
dg::geo::polynomial::Psip
@ guenter
dg::geo::guenter::Psip
@ toroidal
dg::geo::createToroidalField
@ circular
dg::geo::circular::Psip
@ standardO
closed flux surfaces centered around an O-point located near (R_0, 0); flux-aligned grids can be cons...
@ doubleX
closed flux surfaces centered around an O-point located near (R_0, 0) and bordered by a separatrix wi...
@ standardX
closed flux surfaces centered around an O-point located near (R_0, 0) and bordered by a separatrix wi...
static void findXpoint(const CylindricalFunctorsLvl2 &psi, double &RC, double &ZC)
This function finds X-points of psi.
Definition: fluxfunctions.h:350
static int findOpoint(const CylindricalFunctorsLvl2 &psi, double &RC, double &ZC)
This function finds O-points of psi.
Definition: fluxfunctions.h:332
static 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
static dg::geo::TokamakMagneticField createPolynomialField(dg::geo::polynomial::Parameters gp)
Create a Polynomial Magnetic field.
Definition: polynomial.h:167
static dg::geo::CylindricalFunctorsLvl1 createIpol(const Parameters &gp, const CylindricalFunctorsLvl1 &psip)
Definition: solovev.h:354
static dg::geo::TokamakMagneticField createSolovevField(dg::geo::solovev::Parameters gp)
Create a Solovev Magnetic field.
Definition: solovev.h:375
static dg::geo::TokamakMagneticField createTaylorField(dg::geo::solovev::Parameters gp)
Create a Taylor Magnetic field.
Definition: taylor.h:314
static dg::geo::TokamakMagneticField createToroidalField(double R0)
Create a Toroidal Magnetic field.
Definition: toroidal.h:118
static TokamakMagneticField createModifiedField(dg::file::WrappedJsonValue gs, dg::file::WrappedJsonValue jsmod, CylindricalFunctor &wall, CylindricalFunctor &transition)
Modify Magnetic Field and create wall above or below certain Psi values according to given parameters...
Definition: make_field.h:182
static void createSheathRegion(dg::file::WrappedJsonValue jsmod, TokamakMagneticField mag, CylindricalFunctor wall, dg::Grid2d &sheath_walls, CylindricalFunctor &sheath)
Create the sheath region where fieldlines intersect the boundary.
Definition: make_field.h:350
static CylindricalFunctor createWallRegion(dg::file::WrappedJsonValue gs, dg::file::WrappedJsonValue jsmod)
A convenience function call for dg::geo::createModifiedField that ignores the transition parameter an...
Definition: make_field.h:314
real_type h() const
real_type x0() const
real_type y1() const
real_type y0() const
real_type x1() const
This struct bundles a function and its first and second derivatives.
Definition: fluxfunctions.h:219
Meta-data about the magnetic field in particular the flux function.
Definition: magnetic_field.h:91
double a() const
The minor radius.
Definition: magnetic_field.h:122
description getDescription() const
how the flux function looks
Definition: magnetic_field.h:140
double elongation() const
Definition: magnetic_field.h:128
double triangularity() const
Definition: magnetic_field.h:134
equilibrium getEquilibrium() const
the way the flux function is computed
Definition: magnetic_field.h:136
A tokamak field as given by R0, Psi and Ipol plus Meta-data like shape and equilibrium.
Definition: magnetic_field.h:162
const CylindricalFunctorsLvl2 & get_psip() const
Definition: magnetic_field.h:197
const CylindricalFunctorsLvl1 & get_ipol() const
Definition: magnetic_field.h:198
const MagneticFieldParameters & params() const
Access Meta-data of the field.
Definition: magnetic_field.h:204
double R0() const
Definition: magnetic_field.h:177
const CylindricalFunctor & psip() const
, where R, Z are cylindrical coordinates
Definition: magnetic_field.h:179
Distance to wall along fieldline in phi or s coordinate
Definition: fieldaligned.h:221
Definition: modified.h:291
Definition: modified.h:311
Definition: modified.h:271
Constructs and display geometric parameters for the polynomial fields.
Definition: polynomial_parameters.h:46
Constructs and display geometric parameters for the solovev and taylor fields.
Definition: solovev_parameters.h:46
double R_0
major tokamak radius
Definition: solovev_parameters.h:48