42#define DEBUG_COPYSPHERE
44#ifdef DEBUG_SYSBOUNDARY
45#define DEBUG_COPYSPHERE
58 Readparameters::add(
"copysphere.geometry",
"Select the geometry of the copysphere, 0: inf-norm (diamond), 1: 1-norm (square), 2: 2-norm (circle, DEFAULT), 3: 2-norm cylinder aligned with y-axis, use with polar plane/line dipole.", 2);
59 Readparameters::add(
"copysphere.precedence",
"Precedence value of the copysphere system boundary condition (integer), the higher the stronger.", 2);
60 Readparameters::add(
"copysphere.reapplyUponRestart",
"If 0 (default), keep going with the state existing in the restart file. If 1, calls again applyInitialState. Can be used to change boundary condition behaviour during a run.", 0);
61 Readparameters::add(
"copysphere.zeroPerB",
"If 0 (default), normal copysphere behaviour of magnetic field at inner boundary. If 1, keep magnetic field static at the inner boundary", 0);
67 Readparameters::add(pop +
"_copysphere.rho",
"Number density of the copysphere (m^-3)", 0.0);
69 Readparameters::add(pop +
"_copysphere.VX0",
"Bulk velocity of copyspheric distribution function in X direction (m/s)", 0.0);
70 Readparameters::add(pop +
"_copysphere.VY0",
"Bulk velocity of copyspheric distribution function in X direction (m/s)", 0.0);
71 Readparameters::add(pop +
"_copysphere.VZ0",
"Bulk velocity of copyspheric distribution function in X direction (m/s)", 0.0);
72 Readparameters::add(pop +
"_copysphere.fluffiness",
"Inertia of boundary smoothing when copying neighbour's moments and velocity distributions (0=completely constant boundaries, 1=neighbours are interpolated immediately).", 0);
138 r = fabs(x - center[0]) + fabs(y - center[1]) + fabs(z - center[2]);
142 r =
max(
max(fabs(x - center[0]), fabs(y - center[1])), fabs(z - center[2]));
146 r =
sqrt((x - center[0]) * (x - center[0]) + (y - center[1]) * (y - center[1]) +
147 (z - center[2]) * (z - center[2]));
151 r =
sqrt((x - center[0]) * (x - center[0]) + (z - center[2]) * (z - center[2]));
154 abort_mpi(
"copysphere.geometry has to be 0, 1 or 2.", 1);
163 for (uint
i = 0;
i < cells.size();
i++) {
168 const creal*
const cellParams = &(mpiGrid[cells[
i]]->parameters[0]);
177 mpiGrid[cells[
i]]->sysBoundaryFlag = this->
getIndex();
187 #pragma omp parallel for
188 for (uint
i = 0;
i < cells.size(); ++
i) {
193 #ifdef DEBUG_VLASIATOR
196 printf(
"ERROR in vmesh check: %s at %d\n",__FILE__,__LINE__);
210 std::array<Real, 3> normalDirection{{ 0.0, 0.0, 0.0 }};
215 const auto& gridSpacing =
fsgrid.getGridSpacing();
218 creal dy = gridSpacing[1];
219 creal dz = gridSpacing[2];
220 const std::array<fsgrid::FsSize_t, 3> globalIndices =
fsgrid.localToGlobal(
i,
j,
k);
235 "What do you expect to do with a single-cell simulation of copysphere boundary type? Stop kidding.", 1);
239 normalDirection[2] = zsign;
244 normalDirection[1] = ysign;
250 normalDirection[1] = DIAG2 * ysign;
251 normalDirection[2] = DIAG2 * zsign;
254 if (fabs(y) == fabs(z)) {
255 normalDirection[1] = ysign * DIAG2;
256 normalDirection[2] = zsign * DIAG2;
259 if (fabs(y) > (this->
radius - dy)) {
260 normalDirection[1] = ysign;
263 if (fabs(z) > (this->
radius - dz)) {
264 normalDirection[2] = zsign;
267 if (fabs(y) > (this->
radius - 2.0 * dy)) {
268 normalDirection[1] = ysign;
271 if (fabs(z) > (this->
radius - 2.0 * dz)) {
272 normalDirection[2] = zsign;
278 normalDirection[1] = y /
length;
279 normalDirection[2] = z /
length;
282 std::cerr << __FILE__ <<
":" << __LINE__ <<
":" <<
"copysphere.geometry has to be 0, 1 or 2 with this grid shape." << std::endl;
290 normalDirection[0] = xsign;
296 normalDirection[0] = DIAG2 * xsign;
297 normalDirection[2] = DIAG2 * zsign;
300 if (fabs(x) == fabs(z)) {
301 normalDirection[0] = xsign * DIAG2;
302 normalDirection[2] = zsign * DIAG2;
305 if (fabs(x) > (this->
radius -
dx)) {
306 normalDirection[0] = xsign;
309 if (fabs(z) > (this->
radius - dz)) {
310 normalDirection[2] = zsign;
313 if (fabs(x) > (this->
radius - 2.0 *
dx)) {
314 normalDirection[0] = xsign;
317 if (fabs(z) > (this->
radius - 2.0 * dz)) {
318 normalDirection[2] = zsign;
325 normalDirection[0] = x /
length;
326 normalDirection[2] = z /
length;
329 std::cerr << __FILE__ <<
":" << __LINE__ <<
":" <<
"copysphere.geometry has to be 0, 1, 2 or 3 with this grid shape." << std::endl;
338 normalDirection[0] = DIAG2 * xsign;
339 normalDirection[1] = DIAG2 * ysign;
342 if (fabs(x) == fabs(y)) {
343 normalDirection[0] = xsign * DIAG2;
344 normalDirection[1] = ysign * DIAG2;
347 if (fabs(x) > (this->
radius -
dx)) {
348 normalDirection[0] = xsign;
351 if (fabs(y) > (this->
radius - dy)) {
352 normalDirection[1] = ysign;
355 if (fabs(x) > (this->
radius - 2.0 *
dx)) {
356 normalDirection[0] = xsign;
359 if (fabs(y) > (this->
radius - 2.0 * dy)) {
360 normalDirection[1] = ysign;
366 normalDirection[0] = x /
length;
367 normalDirection[1] = y /
length;
370 abort_mpi(
"copysphere.geometry has to be 0, 1 or 2 with this grid shape.", 1);
377 normalDirection[0] = DIAG3 * xsign;
378 normalDirection[1] = DIAG3 * ysign;
379 normalDirection[2] = DIAG3 * zsign;
382 if (fabs(x) == fabs(y) && fabs(x) == fabs(z) && fabs(x) > this->
radius -
dx) {
383 normalDirection[0] = xsign * DIAG3;
384 normalDirection[1] = ysign * DIAG3;
385 normalDirection[2] = zsign * DIAG3;
388 if (fabs(x) == fabs(y) && fabs(x) == fabs(z) && fabs(x) > this->
radius - 2.0 *
dx) {
389 normalDirection[0] = xsign * DIAG3;
390 normalDirection[1] = ysign * DIAG3;
391 normalDirection[2] = zsign * DIAG3;
394 if (fabs(x) == fabs(y) && fabs(x) > this->
radius -
dx && fabs(z) < this->
radius - dz) {
395 normalDirection[0] = xsign * DIAG2;
396 normalDirection[1] = ysign * DIAG2;
397 normalDirection[2] = 0.0;
400 if (fabs(y) == fabs(z) && fabs(y) > this->
radius - dy && fabs(x) < this->
radius -
dx) {
401 normalDirection[0] = 0.0;
402 normalDirection[1] = ysign * DIAG2;
403 normalDirection[2] = zsign * DIAG2;
406 if (fabs(x) == fabs(z) && fabs(x) > this->
radius -
dx && fabs(y) < this->
radius - dy) {
407 normalDirection[0] = xsign * DIAG2;
408 normalDirection[1] = 0.0;
409 normalDirection[2] = zsign * DIAG2;
412 if (fabs(x) == fabs(y) && fabs(x) > this->
radius - 2.0 *
dx && fabs(z) < this->
radius - 2.0 * dz) {
413 normalDirection[0] = xsign * DIAG2;
414 normalDirection[1] = ysign * DIAG2;
415 normalDirection[2] = 0.0;
418 if (fabs(y) == fabs(z) && fabs(y) > this->
radius - 2.0 * dy && fabs(x) < this->
radius - 2.0 *
dx) {
419 normalDirection[0] = 0.0;
420 normalDirection[1] = ysign * DIAG2;
421 normalDirection[2] = zsign * DIAG2;
424 if (fabs(x) == fabs(z) && fabs(x) > this->
radius - 2.0 *
dx && fabs(y) < this->
radius - 2.0 * dy) {
425 normalDirection[0] = xsign * DIAG2;
426 normalDirection[1] = 0.0;
427 normalDirection[2] = zsign * DIAG2;
430 if (fabs(x) > (this->
radius -
dx)) {
431 normalDirection[0] = xsign;
434 if (fabs(y) > (this->
radius - dy)) {
435 normalDirection[1] = ysign;
438 if (fabs(z) > (this->
radius - dz)) {
439 normalDirection[2] = zsign;
442 if (fabs(x) > (this->
radius - 2.0 *
dx)) {
443 normalDirection[0] = xsign;
446 if (fabs(y) > (this->
radius - 2.0 * dy)) {
447 normalDirection[1] = ysign;
450 if (fabs(z) > (this->
radius - 2.0 * dz)) {
451 normalDirection[2] = zsign;
457 normalDirection[0] = x /
length;
458 normalDirection[1] = y /
length;
459 normalDirection[2] = z /
length;
463 normalDirection[0] = x /
length;
464 normalDirection[2] = z /
length;
467 abort_mpi(
"copysphere.geometry has to be 0, 1, 2 or 3 with this grid shape.", 1);
471 return normalDirection;
483 const std::array<Real, 3>& gridSpacing,
484 const std::array<fsgrid::FsSize_t, 3>& globalCoordinates,
485 const fsgrid::FsStencil& stencil,
cuint component) {
487 const uint32_t bitfield = 1 << component;
490 static constexpr std::array permutations = {
502 const std::array permutation = permutations[component];
504 const std::array<size_t, 6> inds = {
514 auto bitFieldSet = [&bitfield](
auto& tech) {
return (tech.SOLVE & bitfield) == bitfield; };
515 auto sbLayerIsOne = [](
auto& tech) {
return tech.sysBoundaryLayer == 1; };
516 auto averageNeigbours = [&technical, &b, &inds, &permutation, &perbComponent,
517 &bitFieldSet](
auto begin,
auto end,
auto& sum,
auto& nCells) {
518 for (
size_t i = begin;
i < end;
i++) {
519 const auto j = inds[permutation[
i]];
520 if (bitFieldSet(technical[
j])) {
521 sum += b[
j][perbComponent];
527 auto averageAllNeighbours = [&stencil, &technical, &b, &perbComponent](
auto predicateLambda,
auto& sum,
529 for (
const auto&
i : stencil.indices()) {
530 if (predicateLambda(technical[
i])) {
531 sum += b[
i][perbComponent];
540 sum = b[stencil.ooo()][perbComponent];
543 if (sbLayerIsOne(technical[stencil.ooo()])) {
544 averageNeigbours(0ul, 2ul, sum, nCells);
547 averageNeigbours(2ul, 6ul, sum, nCells);
551 averageAllNeighbours(bitFieldSet, sum, nCells);
555 averageAllNeighbours(sbLayerIsOne, sum, nCells);
560 cerr << __FILE__ <<
":" << __LINE__ <<
": ERROR: this should not have fallen through." << endl;
569 const fsgrid::FsStencil& stencil,
cuint component) {
574 const fsgrid::FsStencil& stencil,
cuint component) {
575 std::array<Real, fsgrids::ehall::N_EHALL>& cp = ehall[stencil.ooo()];
596 cerr << __FILE__ <<
":" << __LINE__ <<
":" <<
" Invalid component" << endl;
608 const fsgrid::FsStencil& stencil,
cuint RKCase,
cuint component) {
613 const fsgrid::FsStencil& stencil,
cuint component) {
620 const CellID& cellID,
const uint popID,
const bool calculate_V_moments) {
640 Real initRho, initT, initV0X, initV0Y, initV0Z;
682 vmesh->getBlockInfo(blockGID,&blockCoords[0]);
683 creal vxBlock = blockCoords[0];
684 creal vyBlock = blockCoords[1];
685 creal vzBlock = blockCoords[2];
686 creal dvxCell = blockCoords[3];
687 creal dvyCell = blockCoords[4];
688 creal dvzCell = blockCoords[5];
690 creal vx = vxBlock + (
i+0.5)*dvxCell - initV0X;
691 creal vy = vyBlock + (
j+0.5)*dvyCell - initV0Y;
692 creal vz = vzBlock + (
k+0.5)*dvzCell - initV0Z;
706 templateCell.adjustSingleCellVelocityBlocks(popID,
true);
sqrt(1.0+vA *vA/(c *c))) % Ion-acoustic wave cS
#define ARCH_INNER_BODY(...)
void calculateCellMoments(spatial_cell::SpatialCell *cell, const bool &computeSecond, const bool &computePopulationMomentsOnly, const bool &doNotSkip)
static void get(const std::string &name, std::string &value)
static void add(const std::string &name, const std::string &desc, const std::string &defValue)
virtual void updateState(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, fsgrids::perbspan perb, fsgrids::bgbspan bgb, creal t) override
spatial_cell::SpatialCell templateCell
void setCellFromTemplate(SpatialCell *cell, const uint popID)
virtual std::string getName() const override
void getFaces(bool *faces) override
virtual void fieldSolverBoundaryCondGradPeElectricField(fsgrids::egradpespan EGradPe, const fsgrid::FsStencil &stencil, cuint component) override
virtual Real fieldSolverBoundaryCondMagneticField(fsgrids::perbspan b, fsgrids::constbgbspan bgb, fsgrids::consttechnicalspan technical, const std::array< Real, 3 > &gridSpacing, const std::array< fsgrid::FsSize_t, 3 > &globalCoordinates, const fsgrid::FsStencil &stencil, cuint component) override
virtual void fieldSolverBoundaryCondHallElectricField(fsgrids::ehallspan ehall, const fsgrid::FsStencil &stencil, cuint component) override
static void addParameters()
virtual void assignSysBoundary(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid) override
virtual void getParameters() override
virtual void vlasovBoundaryCondition(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const CellID &cellID, const uint popID, const bool calculate_V_moments) override
virtual void fieldSolverBoundaryCondDerivatives(fsgrids::dperbspan dperb, fsgrids::dmomentsspan dmoments, const fsgrid::FsStencil &stencil, cuint RKCase, cuint component) override
std::vector< CopysphereSpeciesParameters > speciesParams
virtual void applyInitialState(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, fsgrids::perbspan perb, fsgrids::bgbspan bgb, Project &project) override
std::array< Real, 3 > fieldSolverGetNormalDirection(fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, cint i, cint j, cint k)
virtual void initSysBoundary(creal &t, Project &project) override
virtual void fieldSolverBoundaryCondBVOLDerivatives(fsgrids::volspan vols, const fsgrid::FsStencil &stencil, cuint component) override
virtual uint getIndex() const override
virtual void fieldSolverBoundaryCondElectricField(fsgrids::efieldspan e, const fsgrid::FsStencil &stencil, cuint component) override
static void setCellBVOLDerivativesToZero(fsgrids::volspan vols, const fsgrid::FsStencil &stencil, cuint component)
virtual void generateTemplateCell()
void vlasovBoundaryFluffyCopyFromAllCloseNbrs(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const CellID &cellID, const uint popID, const bool calculate_V_moments, creal fluffiness)
void copyCellData(const SpatialCell *from, SpatialCell *to, const bool copyMomentsOnly, const uint popID, const bool copy_V_moments)
static void setCellDerivativesToZero(fsgrids::dperbspan dperb, fsgrids::dmomentsspan dmoments, const fsgrid::FsStencil &stencil, cuint component)
bool checkMesh(const uint popID)
void setReservation(const uint popID, const vmesh::LocalID reservationsize, bool force=false)
ARCH_HOSTDEV Realf * getData()
void abort_mpi(const std::string str, const int err_type)
const std::vector< CellID > & getLocalCells()
T convert(const T &number)
fsgrid::FsGrid< FS_STENCIL_WIDTH > FieldSolverGrid
Real divideIfNonZero(creal numerator, creal denominator)
Helper function.
Definitions of the limiter functions used in the field solver.
ObjectWrapper & getObjectWrapper()
FieldTracingParameters fieldTracingParameters
vmesh::LocalID findMaxwellianBlocksToInitialize(const uint popID, spatial_cell::SpatialCell &cell, creal &rho, creal &T, creal &VX0, creal &VY0, creal &VZ0)
SBC::findMaxwellianBlocksToInitialize returns a list of blocks to construct the VDF with.
Real getR(creal x, creal y, creal z, uint geometry, Real center[3])
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< const std::array< Real, bgbfield::N_BGB > > constbgbspan
std::span< std::array< Real, fsgrids::egradpe::N_EGRADPE > > egradpespan
std::span< std::array< Real, fsgrids::dmoments::N_DMOMENTS > > dmomentsspan
std::span< technical > technicalspan
std::span< std::array< Real, bgbfield::N_BGB > > bgbspan
std::span< std::array< Real, fsgrids::dperb::N_DPERB > > dperbspan
std::span< const technical > consttechnicalspan
std::span< std::array< Real, fsgrids::efield::N_EFIELD > > efieldspan
std::span< std::array< Real, fsgrids::volfields::N_VOL > > volspan
std::span< std::array< Real, fsgrids::ehall::N_EHALL > > ehallspan
ARCH_HOSTDEV Realf MaxwellianPhaseSpaceDensity(creal &vx, creal &vy, creal &vz, creal &T, creal &rho, creal &mass)
std::vector< species::Species > particleSpecies
static ARCH_HOSTDEV VecSimple< T > max(VecSimple< T > const &l, VecSimple< T > const &r)