51 RP::add(
"Magnetosphere.constBgBX",
"Constant flat Bx component in the whole simulation box. Default is none.", 0.0);
52 RP::add(
"Magnetosphere.constBgBY",
"Constant flat By component in the whole simulation box. Default is none.", 0.0);
53 RP::add(
"Magnetosphere.constBgBZ",
"Constant flat Bz component in the whole simulation box. Default is none.", 0.0);
54 RP::add(
"Magnetosphere.noDipoleInSW",
"If set to 1, the dipole magnetic field is not set in the solar wind inflow cells. Default 0.", 0.0);
55 RP::add(
"Magnetosphere.dipoleScalingFactor",
"Scales the field strength of the magnetic dipole compared to Earths.", 1.0);
56 RP::add(
"Magnetosphere.dipoleType",
"0: Normal 3D dipole, 1: line-dipole for 2D polar simulations, 2: line-dipole with mirror, 3: 3D dipole with mirror", 0);
57 RP::add(
"Magnetosphere.dipoleMirrorLocationX",
"x-coordinate of dipole Mirror", -1.0);
59 RP::add(
"Magnetosphere.refine_L4radius",
"Radius of L4-refined sphere or cap", 6.0e7);
60 RP::add(
"Magnetosphere.refine_L4nosexmin",
"Low x-value of nose L4-refined box", 5.5e7);
62 RP::add(
"Magnetosphere.refine_L3radius",
"Radius of L3-refined sphere or cap", 6.371e7);
63 RP::add(
"Magnetosphere.refine_L3nosexmin",
"Low x-value of nose L3-refined box", 5.0e7);
64 RP::add(
"Magnetosphere.refine_L3tailheight",
"Height in +-z of tail L3-refined box", 1.0e7);
65 RP::add(
"Magnetosphere.refine_L3tailwidth",
"Width in +-y of tail L3-refined box", 5.0e7);
66 RP::add(
"Magnetosphere.refine_L3tailxmin",
"Low x-value of tail L3-refined box", -20.0e7);
67 RP::add(
"Magnetosphere.refine_L3tailxmax",
"High x-value of tail L3-refined box", -5.0e7);
69 RP::add(
"Magnetosphere.refine_L2radius",
"Radius of L2-refined sphere", 9.5565e7);
70 RP::add(
"Magnetosphere.refine_L2tailthick",
"Thickness of L2-refined tail region", 3.1855e7);
71 RP::add(
"Magnetosphere.refine_L1radius",
"Radius of L1-refined sphere", 1.59275e8);
72 RP::add(
"Magnetosphere.refine_L1tailthick",
"Thickness of L1-refined tail region", 6.371e7);
74 RP::add(
"Magnetosphere.dipoleTiltPhi",
"Magnitude of dipole tilt, in degrees", 0.0);
75 RP::add(
"Magnetosphere.dipoleTiltTheta",
"Direction of dipole tilt from Sun-Earth-line, in degrees", 0.0);
76 RP::add(
"Magnetosphere.dipoleXFull",
"X-coordinate up to which dipole is at full strength, in metres", 9.5565e7);
77 RP::add(
"Magnetosphere.dipoleXZero",
"X-coordinate after which dipole is at zero strength, in metres", 1.9113e8);
78 RP::add(
"Magnetosphere.dipoleInflowBX",
"Inflow magnetic field Bx component to which the vector potential dipole converges. Default is none.", 0.0);
79 RP::add(
"Magnetosphere.dipoleInflowBY",
"Inflow magnetic field By component to which the vector potential dipole converges. Default is none.", 0.0);
80 RP::add(
"Magnetosphere.dipoleInflowBZ",
"Inflow magnetic field Bz component to which the vector potential dipole converges. Default is none.", 0.0);
82 RP::add(
"Magnetosphere.dipoleXOffset",
"Distance of dipole from centre position in x. Default is none.", 0.0);
83 RP::add(
"Magnetosphere.dipoleYOffset",
"Distance of dipole from centre position in y. Default is none.", 0.0);
84 RP::add(
"Magnetosphere.dipoleZOffset",
"Distance of dipole from centre position in z. Default is none.", 0.0);
88 RP::add(
"Magnetosphere.zeroOutDerivativesX",
"Zero Out Perpendicular components", 1.0);
89 RP::add(
"Magnetosphere.zeroOutDerivativesY",
"Zero Out Perpendicular components", 1.0);
90 RP::add(
"Magnetosphere.zeroOutDerivativesZ",
"Zero Out Perpendicular components", 1.0);
96 RP::add(pop +
"_Magnetosphere.rho",
"Tail region number density (m^-3)", 0.0);
97 RP::add(pop +
"_Magnetosphere.T",
"Temperature (K)", 0.0);
98 RP::add(pop +
"_Magnetosphere.VX0",
"Initial bulk velocity in x-direction", 0.0);
99 RP::add(pop +
"_Magnetosphere.VY0",
"Initial bulk velocity in y-direction", 0.0);
100 RP::add(pop +
"_Magnetosphere.VZ0",
"Initial bulk velocity in z-direction", 0.0);
101 RP::add(pop +
"_Magnetosphere.taperInnerRadius",
"Inner radius of the zone with a density tapering from the ionospheric value to the background (m)", 0.0);
102 RP::add(pop +
"_Magnetosphere.taperOuterRadius",
"Outer radius of the zone with a density tapering from the ionospheric value to the background (m)", 0.0);
108 MPI_Comm_rank(MPI_COMM_WORLD,&
myRank);
115 RP::get(
"Magnetosphere.constBgBX", this->
constBgB[0]);
116 RP::get(
"Magnetosphere.constBgBY", this->
constBgB[1]);
117 RP::get(
"Magnetosphere.constBgBZ", this->
constBgB[2]);
118 RP::get(
"Magnetosphere.noDipoleInSW", dummy);
124 RP::get(
"Magnetosphere.dipoleType", this->
dipoleType);
129 std::cerr<<
"Note: Initializing Magnetosphere with dipole type 4, which requires the dipole + vector potential "
130 <<
"correction terms in the solar wind. Thus overriding the config and setting Magnetosphere.noDipoleInSW=0."<<std::endl;
138 RP::get(
"copysphere.centerX", this->
center[0]);
139 RP::get(
"copysphere.centerY", this->
center[1]);
140 RP::get(
"copysphere.centerZ", this->
center[2]);
144 RP::get(
"ionosphere.centerX", this->
center[0]);
145 RP::get(
"ionosphere.centerY", this->
center[1]);
146 RP::get(
"ionosphere.centerZ", this->
center[2]);
150 std::cerr<<
"Warning in initializing Magnetosphere: Could not find inner boundary (ionosphere or copysphere)!"<<std::endl;
157 std::cerr<<
"[Magnetosphere] Note: ionosphereRadius given was < 1000, assuming units of R_E and scaling for you."<<std::endl;
178 RP::get(
"Magnetosphere.dipoleXFull", this->
dipoleXFull);
179 RP::get(
"Magnetosphere.dipoleXZero", this->
dipoleXZero);
180 RP::get(
"Magnetosphere.dipoleInflowBX", this->
dipoleInflowB[0]);
181 RP::get(
"Magnetosphere.dipoleInflowBY", this->
dipoleInflowB[1]);
182 RP::get(
"Magnetosphere.dipoleInflowBZ", this->
dipoleInflowB[2]);
191 std::cerr<<
"[Magnetosphere] WARNING: dipole offset position vector exceeds the ionosphere radius. "
192 <<
"This is very likely to cause problems."<<std::endl;
206 RP::get(pop +
"_Magnetosphere.rho", sP.
rho);
207 RP::get(pop +
"_Magnetosphere.T", sP.
T);
208 RP::get(pop +
"_Magnetosphere.VX0", sP.
V0[0]);
209 RP::get(pop +
"_Magnetosphere.VY0", sP.
V0[1]);
210 RP::get(pop +
"_Magnetosphere.VZ0", sP.
V0[2]);
232 cerr <<
"Error: " << pop <<
"_Magnetosphere.taperInnerRadius and tapeOuterRadius should be >= 0! Aborting." << endl;
238 cerr <<
"Error: " << pop <<
"_Magnetosphere.taperInnerRadius should be <= taperOuterRadius! Aborting." << endl;
244 cerr <<
"Error: " << pop <<
"_Magnetosphere.taperOuterRadius is non-zero yet smaller than ionosphere.radius / copysphere.radius! Aborting." << endl;
250 cerr <<
"Warning: " << pop <<
"_Magnetosphere.taperInnerRadius is zero (default), now setting this to the same value as ionosphere.radius / copysphere.radius, that is " << this->ionosphereRadius <<
". Set/change " << pop <<
"_Magnetosphere.taperInnerRadius if this is not the expected behavior." << endl;
257 cerr <<
"Warning: " << pop <<
"_copysphere.T is zero (default), now setting to the same value as " << pop <<
"_Magnetosphere.T, that is " << sP.
T <<
". Set/change " << pop <<
"_copysphere.T if this is not the expected behavior." << endl;
259 cerr <<
"Warning: " << pop <<
"_ionosphere.T is zero (default), now setting to the same value as " << pop <<
"_Magnetosphere.T, that is " << sP.
T <<
". Set/change " << pop <<
"_ionosphere.T if this is not the expected behavior." << endl;
267 cerr <<
"Warning: " << pop <<
"_copysphere.rho is zero (default), now setting to the same value as " << pop <<
"_Magnetosphere.rho, that is " << sP.
rho <<
". Set/change " << pop <<
"_copysphere.rho if this is not the expected behavior." << endl;
269 cerr <<
"Warning: " << pop <<
"_ionosphere.rho is zero (default), now setting to the same value as " << pop <<
"_Magnetosphere.rho, that is " << sP.
rho <<
". Set/change " << pop <<
"_ionosphere.rho if this is not the expected behavior." << endl;
306 std::cerr << __FILE__ <<
":" << __LINE__ <<
":" <<
"ionosphere.geometry has to be 0, 1, 2 or 3." << std::endl;
320 phiprof::Timer switchDipoleTypeTimer {
"switch-dipoleType"};
334 bgFieldLineDipole.
initialize(126.2e6 *this->dipoleScalingFactor, 0.0, 0.0, 0.0 );
339 bgFieldLineDipole.
initialize(126.2e6 *this->dipoleScalingFactor, 0.0, 0.0, 0.0 );
347 bgFieldDipole.
initialize(8e15 *this->dipoleScalingFactor, 0.0, 0.0, 0.0, 0.0 );
368 bgVectorDipole.
initialize(8e15 *this->dipoleScalingFactor, this->
dipoleXOffset, this->
dipoleYOffset, this->
dipoleZOffset, this->
dipoleTiltPhi*M_PI/180., this->
dipoleTiltTheta*M_PI/180., this->
dipoleXFull, this->
dipoleXZero, this->
dipoleInflowB[0], this->
dipoleInflowB[1], this->
dipoleInflowB[2]);
372 fsgrid.parallel_for([](
int timerId) -> phiprof::Timer {
return phiprof::Timer{timerId}; },
373 phiprof::initializeTimer(
"setProjectBField-loop"), technical,
374 [=](
const fsgrid::Coordinates &coordinates,
const fsgrid::FsStencil& stencil,
cuint sysBoundaryFlag,
cuint sysBoundaryLayer) {
375 const auto& BGBcell = bgb[stencil.ooo()];
376 auto& PERBcell = perb[stencil.ooo()];
386 switchDipoleTypeTimer.stop();
391 const auto constBgB_l = this->
constBgB;
392 fsgrid.parallel_for([](
int timerId) -> phiprof::Timer {
return phiprof::Timer{timerId}; },
393 phiprof::initializeTimer(
"zeroing-out"), technical,
394 [=](
const fsgrid::Coordinates &coordinates,
const fsgrid::FsStencil& stencil,
cuint sysBoundaryFlag,
cuint sysBoundaryLayer) {
400 auto& cell = bgb[stencil.ooo()];
416 auto& cell = bgb[stencil.ooo()];
431 auto& cell = bgb[stencil.ooo()];
448 auto& cell = bgb[stencil.ooo()];
453 auto& pb = perb[stencil.ooo()];
460 phiprof::Timer addConstantTimer {
"add-constant-field"};
462 if(constBgB_l[0] != 0.0 || constBgB_l[1] != 0.0 || constBgB_l[2] != 0.0) {
464 bgConstantField.
initialize(constBgB_l[0], constBgB_l[1], constBgB_l[2]);
468 addConstantTimer.stop();
469 phiprof::Timer storeNodeTimer {
"ionosphereGrid.storeNodeB"};
471 storeNodeTimer.stop();
480 const uint nRequested
493 std::array<Real, 3> initV0 = this->
getV0(x, y, z, popID)[0];
494 const Real initV0X = initV0[0];
495 const Real initV0Y = initV0[1];
496 const Real initV0Z = initV0[2];
526 vmesh->getBlockInfo(blockGID,&blockCoords[0]);
527 creal vxBlock = blockCoords[0];
528 creal vyBlock = blockCoords[1];
529 creal vzBlock = blockCoords[2];
530 creal dvxCell = blockCoords[3];
531 creal dvyCell = blockCoords[4];
532 creal dvzCell = blockCoords[5];
534 creal vx = vxBlock + (
i+0.5)*dvxCell - initV0X;
535 creal vy = vyBlock + (
j+0.5)*dvyCell - initV0Y;
536 creal vz = vzBlock + (
k+0.5)*dvzCell - initV0Z;
564 std::array<Real, 3> initV0 = this->
getV0(x, y, z, popID)[0];
565 const Real initV0X = initV0[0];
566 const Real initV0Y = initV0[1];
567 const Real initV0Z = initV0[2];
580 creal vx = vx_in - initV0X;
581 creal vy = vy_in - initV0Y;
582 creal vz = vz_in - initV0Z;
595 vector<std::array<Real, 3> > centerPoints;
596 std::array<Real, 3> V0 {{sP.
V0[0], sP.
V0[1], sP.
V0[2]}};
604 for(uint
i=0;
i<3;
i++) {
605 V0[
i]=
q*(V0[
i]-ionosphereV0[
i])+ionosphereV0[
i];
607 V0[
i] = ionosphereV0[
i];
612 centerPoints.push_back(V0);
617 phiprof::Timer refineSCTimer {
"Magnetosphere: refine spatial cells"};
620 MPI_Comm_rank(MPI_COMM_WORLD,&
myRank);
623 std::cout <<
"Maximum refinement level is " << mpiGrid.mapping.get_maximum_refinement_level() << std::endl;
631 for (uint
i = 0;
i < cells.size(); ++
i) {
633 std::array<double,3> xyz = mpiGrid.get_center(
id);
635 Real radius2 = pow(xyz[0], 2) + pow(xyz[1], 2) + pow(xyz[2], 2);
640 mpiGrid.refine_completely(
id);
644 cells = mpiGrid.stop_refining();
646 std::cout <<
"Finished first level of refinement" << endl;
648 #ifdef DEBUG_VLASIATOR
649 if (cells.size() > 0) {
650 std::cout <<
"Rank " <<
myRank <<
" refined " << cells.size() <<
" cells to level 1" << std::endl;
658 for (uint
i = 0;
i < cells.size(); ++
i) {
660 std::array<double,3> xyz = mpiGrid.get_center(
id);
662 Real radius2 = pow(xyz[0], 2) + pow(xyz[1], 2) + pow(xyz[2], 2);
665 if ((inSphere || inTail) && radius2 <
P::refineRadius * P ::refineRadius) {
667 mpiGrid.refine_completely(
id);
670 cells = mpiGrid.stop_refining();
672 std::cout <<
"Finished second level of refinement" << endl;
674 #ifdef DEBUG_VLASIATOR
675 if (cells.size() > 0) {
676 std::cout <<
"Rank " <<
myRank <<
" refined " << cells.size() <<
" cells to level 2" << std::endl;
685 for (uint
i = 0;
i < cells.size(); ++
i) {
687 std::array<double,3> xyz = mpiGrid.get_center(
id);
689 Real radius2 = pow(xyz[0], 2) + pow(xyz[1], 2) + pow(xyz[2], 2);
694 mpiGrid.refine_completely(
id);
697 cells = mpiGrid.stop_refining();
699 std::cout <<
"Finished third level of refinement" << endl;
701 #ifdef DEBUG_VLASIATOR
702 if (cells.size() > 0) {
703 std::cout <<
"Rank " <<
myRank <<
" refined " << cells.size() <<
" cells to level 3" << std::endl;
711 for (uint
i = 0;
i < cells.size(); ++
i) {
713 std::array<double,3> xyz = mpiGrid.get_center(
id);
715 Real radius2 = (xyz[0]*xyz[0]+xyz[1]*xyz[1]+xyz[2]*xyz[2]);
721 mpiGrid.refine_completely(
id);
725 cells = mpiGrid.stop_refining();
727 std::cout <<
"Finished fourth level of refinement" << endl;
729 #ifdef DEBUG_VLASIATOR
730 if (cells.size() > 0) {
731 std::cout <<
"Rank " <<
myRank <<
" refined " << cells.size() <<
" cells to level 4" << std::endl;
742 MPI_Comm_rank(MPI_COMM_WORLD,&
myRank);
745 std::cout <<
"Maximum refinement level is " << mpiGrid.mapping.get_maximum_refinement_level() << std::endl;
749 std::array<double,3> xyz {mpiGrid.get_center(
id)};
750 Real radius2 {pow(xyz[0], 2) + pow(xyz[1], 2) + pow(xyz[2], 2)};
751 int refLevel {mpiGrid.get_refinement_level(
id)};
752 int refineTarget {0};
757 if ((inSphere || inTail) && radius2 <
P::refineRadius * P ::refineRadius)
763 if ((inSphere || inTail) && radius2 <
P::refineRadius * P ::refineRadius)
769 if ((inNoseCap || inTail) && radius2 <
P::refineRadius * P ::refineRadius)
779 mpiGrid.dont_refine(
id);
780 mpiGrid.dont_unrefine(
id);
781 }
else if (refLevel <= n && refLevel < refineTarget) {
782 mpiGrid.refine_completely(
id);
783 }
else if (refLevel >= mpiGrid.mapping.get_maximum_refinement_level() - n && refLevel > refineTarget) {
784 mpiGrid.unrefine_completely(
id);
786 mpiGrid.dont_unrefine(
id);
sqrt(1.0+vA *vA/(c *c))) % Ion-acoustic wave cS
#define ARCH_INNER_BODY(...)
void setBackgroundFieldToZero(FieldSolverGrid &fsgrid, fsgrids::technicalspan technical, fsgrids::bgbspan bgb)
void setBackgroundField(const FieldFunction &bgFunction, fsgrids::bgbspan bgb, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, bool append)
void setPerturbedField(const FieldFunction &bfFunction, std::span< std::array< Real, numFields > > b, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, int offset=fsgrids::bfield::PERBX, bool append=false)
void initialize(const double Bx, const double By, const double Bz)
void initialize(const double moment, const double center_x, const double center_y, const double center_z, const double tilt_angle)
void initialize(const double moment, const double center_x, const double center_y, const double center_z)
SysBoundary contains the SysBoundaryConditions used in the simulation.
bool existSysBoundary(std::string name)
Boolean check if queried sysboundarycondition exists Note: this queries against the parsed list of na...
void initialize(const double moment, const double center_x, const double center_y, const double center_z, const double tilt_angle_phi, const double tilt_angle_theta, const double xlimit_f, const double xlimit_z, const double IMF_Bx, const double IMF_By, const double IMF_Bz)
virtual void getParameters(void) override
std::vector< MagnetosphereSpeciesParameters > speciesParams
Real dipoleMirrorLocationX
virtual Realf probePhaseSpace(spatial_cell::SpatialCell *cell, const uint popID, Real vx_in, Real vy_in, Real vz_in) const override
Real zeroOutComponents[3]
bool forceRefinement(dccrg::Dccrg< spatial_cell::SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, int n) const override
std::array< Real, 3 > constBgB
static void addParameters(void)
virtual void setProjectBField(fsgrids::perbspan perb, fsgrids::bgbspan bgb, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid) override
Real geometryRadius(Real x, Real y, Real z) const
virtual std::vector< std::array< Real, 3 > > getV0(creal x, creal y, creal z, const uint popID) const override
Return a vector containing the velocity coordinate of the centre of each ion population in the distri...
virtual void calcCellParameters(spatial_cell::SpatialCell *cell, creal &t) override
virtual bool initialize(void) override
bool refineSpatialCells(dccrg::Dccrg< spatial_cell::SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid) const override
virtual Realf fillPhaseSpace(spatial_cell::SpatialCell *cell, const uint popID, const uint nRequested) const override
virtual bool canRefine(spatial_cell::SpatialCell *cell) const
virtual bool initialize()
virtual void getParameters()
vmesh::VelocityMesh * get_velocity_mesh(const size_t &popID)
vmesh::VelocityBlockContainer * get_velocity_blocks(const size_t &popID)
std::array< Real, CellParams::N_SPATIAL_CELL_PARAMS > parameters
vmesh::VelocityBlockContainer * dev_get_velocity_blocks(const size_t &popID)
vmesh::VelocityMesh * dev_get_velocity_mesh(const size_t &popID)
ARCH_HOSTDEV Realf * getData()
const std::vector< CellID > & getLocalCells()
fsgrid::FsGrid< FS_STENCIL_WIDTH > FieldSolverGrid
ObjectWrapper & getObjectWrapper()
SphericalTriGrid ionosphereGrid
static void parallel_reduce(const uint(&limits)[NDim], Lambda loop_body, T &sum)
std::span< std::array< Real, fsgrids::bfield::N_BFIELD > > perbspan
std::span< technical > technicalspan
std::span< std::array< Real, bgbfield::N_BGB > > bgbspan
ARCH_HOSTDEV Realf MaxwellianPhaseSpaceDensity(creal &vx, creal &vy, creal &vz, creal &T, creal &rho, creal &mass)
SysBoundary sysBoundaryContainer
std::vector< species::Species > particleSpecies
static int amrMaxSpatialRefLevel
static int amrMaxAllowedSpatialRefLevel
static ARCH_HOSTDEV VecSimple< T > max(VecSimple< T > const &l, VecSimple< T > const &r)