62 bool* isThisCellOnAFace,
65 const bool excludeSlicesAndPeriodicDimensions
67 for(uint
i=0;
i<6;
i++) {
68 isThisCellOnAFace[
i] =
false;
71 isThisCellOnAFace[0] =
true;
74 isThisCellOnAFace[1] =
true;
77 isThisCellOnAFace[2] =
true;
80 isThisCellOnAFace[3] =
true;
83 isThisCellOnAFace[4] =
true;
86 isThisCellOnAFace[5] =
true;
88 if(excludeSlicesAndPeriodicDimensions ==
true) {
90 isThisCellOnAFace[0] =
false;
91 isThisCellOnAFace[1] =
false;
94 isThisCellOnAFace[2] =
false;
95 isThisCellOnAFace[3] =
false;
98 isThisCellOnAFace[4] =
false;
99 isThisCellOnAFace[5] =
false;
117 std::array<bool, 6> &isThisCellOnAFace,
118 const dccrg::Dccrg<SpatialCell,dccrg::Cartesian_Geometry>& mpiGrid,
120 const bool excludeSlicesAndPeriodicDimensions
122 isThisCellOnAFace.fill(
false);
124 std::array<std::set<CellID>, 6> dirNeighbors;
127 std::cerr <<
"No neighbors found for " <<
id << std::endl;
131 for (
auto pair : *p) {
134 }
else if (pair.second[0] > 0) {
135 dirNeighbors[0].insert(pair.first);
136 }
else if (pair.second[0] < 0) {
137 dirNeighbors[1].insert(pair.first);
138 }
else if (pair.second[1] > 0) {
139 dirNeighbors[2].insert(pair.first);
140 }
else if (pair.second[1] < 0) {
141 dirNeighbors[3].insert(pair.first);
142 }
else if (pair.second[2] > 0) {
143 dirNeighbors[4].insert(pair.first);
144 }
else if (pair.second[2] < 0) {
145 dirNeighbors[5].insert(pair.first);
151 for (
int i = 0;
i < 6; ++
i) {
152 if(dirNeighbors[
i].size() < 2) {
153 isThisCellOnAFace[
i] =
true;
157 if(excludeSlicesAndPeriodicDimensions ==
true) {
159 isThisCellOnAFace[0] =
false;
160 isThisCellOnAFace[1] =
false;
163 isThisCellOnAFace[2] =
false;
164 isThisCellOnAFace[3] =
false;
167 isThisCellOnAFace[4] =
false;
168 isThisCellOnAFace[5] =
false;
182 cerr <<
"ERROR: SysBoundaryCondition::addParameters called instead of derived class function!" << endl;
193 const fsgrid::FsStencil& stencil,
cuint component) {
194 auto& dPerBGrid0 = dperb[stencil.ooo()];
195 auto& dMomentsGrid0 = dmoments[stencil.ooo()];
252 cerr << __FILE__ <<
":" << __LINE__ <<
":" <<
" Invalid component" << endl;
263 const fsgrid::FsStencil& stencil,
cuint component) {
264 auto& vol = vols[stencil.ooo()];
294 dccrg::Dccrg<SpatialCell,dccrg::Cartesian_Geometry>& mpiGrid,
296 const bool& copyMomentsOnly,
298 const bool copy_V_moments
305 copyCellData(mpiGrid[closestCell],mpiGrid[cellID], copyMomentsOnly, popID, copy_V_moments);
316 dccrg::Dccrg<SpatialCell,dccrg::Cartesian_Geometry>& mpiGrid,
318 const bool& copyMomentsOnly,
320 const bool copy_V_moments
325 abort_mpi(
"No closest L1 Outflow cell found!", 1);
327 phiprof::Timer boundaryTimer {
"vlasovBoundaryCopyFromTheClosestL1OutflowNbr"};
328 copyCellData(mpiGrid[closestCell],mpiGrid[cellID], copyMomentsOnly, popID, copy_V_moments);
329 boundaryTimer.stop();
339 dccrg::Dccrg<SpatialCell,dccrg::Cartesian_Geometry>& mpiGrid,
340 const CellID& cellID,
const uint popID,
const bool copy_V_moments
358 dccrg::Dccrg<SpatialCell,dccrg::Cartesian_Geometry>& mpiGrid,
359 const CellID& cellID,
const uint popID,
const bool copy_V_moments,
const creal fluffiness
366 averageCellData(mpiGrid, closeCells, mpiGrid[cellID], popID, fluffiness);
379 const bool copyMomentsOnly,
381 const bool copy_V_moments
384 if (copy_V_moments) {
405 if(copyMomentsOnly) {
407 if (copy_V_moments) {
412 for (uint
i=0;
i<3;
i++) {
414 if (copy_V_moments) {
420 for (uint
i=0;
i<6;
i++) {
422 if (copy_V_moments) {
441 const dccrg::Dccrg<SpatialCell,dccrg::Cartesian_Geometry>& mpiGrid,
442 const vector<CellID> cellList,
445 const creal fluffiness
447 const size_t numberOfCells = cellList.size();
451 if (fluffiness != 0.0) {
455 for (
size_t i=0;
i<numberOfCells;
i++) {
467 const dccrg::Dccrg<SpatialCell,dccrg::Cartesian_Geometry>& mpiGrid,
468 const vector<CellID> & local_cells_on_boundary
471 for(vector<CellID>::const_iterator it = local_cells_on_boundary.begin(); it != local_cells_on_boundary.end(); ++it) {
472 const CellID cellId = *it;
474 closestCells.clear();
478 closestL1OutflowCells.clear();
480 closeL1OutflowCells.clear();
481 uint dist = numeric_limits<uint>::max();
482 uint d2 = numeric_limits<uint>::max();
483 uint distL1 = numeric_limits<uint>::max();
484 uint d2L1 = numeric_limits<uint>::max();
487 if(mpiGrid[cellId]->sysBoundaryLayer == 1) {
490 CellID neighbor = nbrPair.first;
493 d2 = nbrPair.second[0]*nbrPair.second[0] + nbrPair.second[1]*nbrPair.second[1] + nbrPair.second[2]*nbrPair.second[2];
495 if (
i.first == neighbor) {
496 closeCells.push_back(neighbor);
498 closestCells.push_back(neighbor);
499 }
else if (d2 < dist) {
500 closestCells.clear();
501 closestCells.push_back(neighbor);
511 if (mpiGrid[cellId]->sysBoundaryLayer == 2) {
514 CellID neighbor = nbrPair.first;
517 d2 = nbrPair.second[0]*nbrPair.second[0] + nbrPair.second[1]*nbrPair.second[1] + nbrPair.second[2]*nbrPair.second[2];
518 closeCells.push_back(neighbor);
520 closestCells.push_back(neighbor);
521 }
else if (d2 < dist) {
522 closestCells.clear();
523 closestCells.push_back(neighbor);
529 d2L1 = nbrPair.second[0]*nbrPair.second[0] + nbrPair.second[1]*nbrPair.second[1] + nbrPair.second[2]*nbrPair.second[2];
530 closeL1OutflowCells.push_back(neighbor);
532 closestL1OutflowCells.push_back(neighbor);
533 }
else if (d2L1 < distL1) {
534 closestL1OutflowCells.clear();
535 closestL1OutflowCells.push_back(neighbor);
543 if(closestCells.size() == 0) {
546 if(closeCells.size() == 0) {
549 if(closestL1OutflowCells.size() == 0) {
552 if(closeL1OutflowCells.size() == 0) {
571 return closestCells.at(0);
585 const auto stencil =
fsgrid.makeStencil(
i,
j,
k);
586 int distance = numeric_limits<int>::max();
587 vector<array<int, 3>> closestCells;
589 for (
int kk=-2; kk<3; kk++) {
590 for (
int jj=-2; jj<3; jj++) {
591 for (
int ii=-2; ii<3 ; ii++) {
592 if (stencil.cellExists(ii, jj, kk)) {
593 if (technical[stencil.indexFromOffset(ii, jj, kk)].sysBoundaryFlag ==
595 distance =
min(distance, ii * ii + jj * jj + kk * kk);
602 for (
int kk=-2; kk<3; kk++) {
603 for (
int jj=-2; jj<3; jj++) {
604 for (
int ii=-2; ii<3 ; ii++) {
605 if (stencil.cellExists(ii, jj, kk)) {
606 if (technical[stencil.indexFromOffset(ii, jj, kk)].sysBoundaryFlag ==
608 const int d = ii * ii + jj * jj + kk * kk;
610 closestCells.push_back({
i + ii,
j + jj,
k + kk});
618 if (closestCells.empty()) {
619 closestCells.push_back({numeric_limits<int>::min()});
634 return closestCells.at(0);
646 return closestCells.at(0);
674 const fsgrid::FsStencil& stencil,
cuint component,
cuint mask) {
675 int distance = numeric_limits<int>::max();
676 auto closestCellIndex = 0;
678 for (
auto kk = -2; kk < 3; kk++) {
679 for (
auto jj = -2; jj < 3; jj++) {
680 for (
auto ii = -2; ii < 3; ii++) {
681 if (stencil.cellExists(ii, jj, kk)) {
682 const auto index = stencil.indexFromOffset(ii, jj, kk);
683 const auto& tech = technical[
index];
684 const bool copyable = (tech.SOLVE & mask) == mask &&
687 const int d = ii * ii + jj * jj + kk * kk;
688 if (copyable && d < distance) {
690 closestCellIndex =
index;
697 if (distance == numeric_limits<int>::max()) {
708 cerr <<
"ERROR: SysBoundaryCondition::getFaces called instead of derived class function!" << endl;
709 for(
int i=0;
i<6;
i++) {
725 std::array<bool, 3> isFacePeriodic
734 std::array<Real, CellParams::N_SPATIAL_CELL_PARAMS>& cellParams
736 std::cerr <<
"Error: SysBoundaryCondition::mapCellPotentialAndGetEXBDrift called!\n";
757 const uint blocksCount = vblocks_ini[0]*vblocks_ini[1]*vblocks_ini[2];
781 Real vRadiusSquared = (
Real)counter * (
Real)counter * dV[0] * dV[0];
786 vmesh->setNewSize(currentMaxSize);
787 GIDbuffer =
vmesh->getGrid()->data();
791 for (uint kv=0; kv<vblocks_ini[2]; ++kv) {
792 for (uint jv=0; jv<vblocks_ini[1]; ++jv) {
793 for (uint iv=0; iv<vblocks_ini[0]; ++iv) {
797 V_crds[0] += 0.5*dV[0] - VX0;
798 V_crds[1] += 0.5*dV[1] - VY0;
799 V_crds[2] += 0.5*dV[2] - VZ0;
800 Real R2 = ((V_crds[0])*(V_crds[0])
801 + (V_crds[1])*(V_crds[1])
802 + (V_crds[2])*(V_crds[2]));
805 if (LID >= currentMaxSize) {
806 currentMaxSize = LID + counter*counter*counter;
807 vmesh->setNewSize(currentMaxSize);
808 GIDbuffer =
vmesh->getGrid()->data();
811 if (R2 < vRadiusSquared) {
812 GIDbuffer[LID] = GID;
831 vmesh->setNewSize(LID);
838 bool* isThisCellOnAFace,
841 const std::array<bool, 3> periodicity,
842 const bool excludeSlicesAndPeriodicDimensions
844 for(uint
i=0;
i<6;
i++) {
845 isThisCellOnAFace[
i] =
false;
848 isThisCellOnAFace[0] =
true;
851 isThisCellOnAFace[1] =
true;
854 isThisCellOnAFace[2] =
true;
857 isThisCellOnAFace[3] =
true;
860 isThisCellOnAFace[4] =
true;
863 isThisCellOnAFace[5] =
true;
865 if(excludeSlicesAndPeriodicDimensions ==
true) {
867 isThisCellOnAFace[0] =
false;
868 isThisCellOnAFace[1] =
false;
871 isThisCellOnAFace[2] =
false;
872 isThisCellOnAFace[3] =
false;
875 isThisCellOnAFace[4] =
false;
876 isThisCellOnAFace[5] =
false;
888 std::array<bool, 6> isThisCellOnAFace;
892 for (
auto&
id : cells) {
896 creal*
const cellParams = &(mpiGrid[id]->parameters[0]);
904 for(uint
i=0;
i<6;
i++) {
905 isThisCellOnAFace[
i] =
false;
910 for (
int j = 0;
j < 6;
j++) {
914 mpiGrid[id]->sysBoundaryFlag = this->
getIndex();
917 const auto index_local = this->
getIndex();
919 const std::array<bool, 3> periodic_local = this->
periodic;
921 fsgrid.serial_for([](
int timerId) -> phiprof::Timer {
return phiprof::Timer{timerId}; },
922 phiprof::initializeTimer(
"Assign sysboundary flags to fsgrid cells"), technical,
923 [=](
const fsgrid::Coordinates &coordinates,
const fsgrid::FsStencil& stencil,
cuint sysBoundaryFlag,
cuint sysBoundaryLayer) {
925 creal dy =
P::dy_ini * pow(2, -technical[stencil.ooo()].refLevel);
926 creal dz =
P::dz_ini * pow(2, -technical[stencil.ooo()].refLevel);
928 std::array<bool, 6> isThisCellOnAFace = {{
false}};
929 bool doAssign =
false;
930 const std::array<Real, 3> coords = coordinates.getPhysicalCoords(stencil.i, stencil.j, stencil.k);
931 const std::array<Real, 3> gridSpacing = coordinates.physicalGridSpacing;
933 determineFaceNoClassMembers(isThisCellOnAFace.data(), coords[0] + 0.5 * gridSpacing[0], coords[1] + 0.5 * gridSpacing[1], coords[2] + 0.5 * gridSpacing[2],
dx, dy, dz, periodic_local);
934 for (
int iface = 0; iface < 6; iface++) {
935 doAssign = doAssign || (facesToProcess_local[iface] && isThisCellOnAFace[iface]);
938 technical[stencil.ooo()].sysBoundaryFlag = index_local;
#define gpuStreamSynchronize
#define gpuMemcpyHostToDevice
virtual void assignSysBoundary(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid)
std::array< bool, 6 > facesToProcess
std::array< int, 3 > getTheClosestNonsysboundaryCell(fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, cint i, cint j, cint k)
void vlasovBoundaryCopyFromAllClosestNbrs(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const CellID &cellID, const uint popID, const bool calculate_V_moments)
bool doApplyUponRestart() const
static void setCellBVOLDerivativesToZero(fsgrids::volspan vols, const fsgrid::FsStencil &stencil, cuint component)
void determineFace(bool *isThisCellOnAFace, const creal x, const creal y, const creal z, const creal dx, const creal dy, const creal dz, const bool excludeSlicesAndPeriodicDimensions=false) const
Function used to determine on which face(s) if any the cell at given coordinates is.
void vlasovBoundaryCopyFromTheClosestNbr(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const CellID &cellID, const bool ©MomentsOnly, const uint popID, const bool calculate_V_moments)
std::vector< std::array< int, 3 > > getAllClosestNonsysboundaryCells(fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, cint i, cint j, cint k)
std::unordered_map< CellID, std::vector< CellID > > allCloseL1OutflowCells
void vlasovBoundaryCopyFromTheClosestL1OutflowNbr(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const CellID &cellID, const bool ©MomentsOnly, const uint popID, const bool calculate_V_moments)
void setPeriodicity(std::array< bool, 3 > isFacePeriodic)
virtual uint getIndex() const =0
virtual ~SysBoundaryCondition()
std::unordered_map< CellID, std::vector< CellID > > allClosestNonsysboundaryCells
std::unordered_map< CellID, std::vector< CellID > > allCloseNonsysboundaryCells
void vlasovBoundaryFluffyCopyFromAllCloseNbrs(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const CellID &cellID, const uint popID, const bool calculate_V_moments, creal fluffiness)
std::vector< CellID > & getAllCloseNonsysboundaryCells(const CellID &cellID)
static void addParameters()
void copyCellData(const SpatialCell *from, SpatialCell *to, const bool copyMomentsOnly, const uint popID, const bool copy_V_moments)
CellID & getTheClosestL1OutflowCell(const CellID &cellID)
uint getPrecedence() const
Real fieldBoundaryCopyFromSolvingNbrMagneticField(fsgrids::perbspan b, fsgrids::consttechnicalspan technical, const fsgrid::FsStencil &stencil, cuint component, cuint mask)
static void setCellDerivativesToZero(fsgrids::dperbspan dperb, fsgrids::dmomentsspan dmoments, const fsgrid::FsStencil &stencil, cuint component)
virtual void getFaces(bool *faces)=0
virtual void mapCellPotentialAndGetEXBDrift(std::array< Real, CellParams::N_SPATIAL_CELL_PARAMS > &cellParams)
std::array< bool, 3 > periodic
std::unordered_map< CellID, std::vector< CellID > > allClosestL1OutflowCells
bool updateSysBoundaryConditionsAfterLoadBalance(const dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const std::vector< CellID > &local_cells_on_boundary)
void set_population(const Population &pop, cuint popID)
const Real * get_velocity_grid_cell_size(const uint popID)
vmesh::VelocityMesh * get_velocity_mesh(const size_t &popID)
void scale_population(creal factor, cuint popID)
void increment_population(const Population &pop, creal factor, cuint popID)
Real getVelocityBlockMinValue(const uint popID) const
void dev_resize_vmesh(const uint popID, const uint nBlocks)
const vmesh::LocalID * get_velocity_grid_length(const uint popID)
Population & get_population(const uint popID)
void get_velocity_block_coordinates(const uint popID, const vmesh::GlobalID &globalID, Real *coords)
std::array< Real, CellParams::N_SPATIAL_CELL_PARAMS > parameters
const Real * get_velocity_grid_block_size(const uint popID)
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
__host__ gpuStream_t gpu_getStream()
ObjectWrapper & getObjectWrapper()
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.
void determineFaceNoClassMembers(bool *isThisCellOnAFace, creal x, creal y, creal z, creal dx, creal dy, creal dz, const std::array< bool, 3 > periodicity, const bool excludeSlicesAndPeriodicDimensions)
void averageCellData(const dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const vector< CellID > cellList, SpatialCell *to, const uint popID, const creal fluffiness)
std::span< std::array< Real, fsgrids::bfield::N_BFIELD > > perbspan
std::span< std::array< Real, fsgrids::dmoments::N_DMOMENTS > > dmomentsspan
std::span< technical > technicalspan
std::span< std::array< Real, fsgrids::dperb::N_DPERB > > dperbspan
std::span< const technical > consttechnicalspan
std::span< std::array< Real, fsgrids::volfields::N_VOL > > volspan
ARCH_HOSTDEV Realf MaxwellianPhaseSpaceDensity(creal &vx, creal &vy, creal &vz, creal &T, creal &rho, creal &mass)
const uint64_t INVALID_CELLID
std::vector< species::Species > particleSpecies
static ARCH_HOSTDEV VecSimple< T > min(VecSimple< T > const &l, VecSimple< T > const &r)