Vlasiator ebf0dd394 on dev (v5.4.0 + 1054 commits)
Loading...
Searching...
No Matches
sysboundarycondition.cpp
Go to the documentation of this file.
1/*
2 * This file is part of Vlasiator.
3 * Copyright 2010-2016 Finnish Meteorological Institute
4 *
5 * For details of usage, see the COPYING file and read the "Rules of the Road"
6 * at http://www.physics.helsinki.fi/vlasiator/
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
29
30#include <cstdlib>
31#include <iostream>
32
33#include "../parameters.h"
37#include "../object_wrapper.h"
38
39using namespace std;
40
41namespace SBC {
42 // ************************************************************
43 // ***** DEFINITIONS FOR BOUNDARYCONDITION BASE CLASS *****
44 // ************************************************************
45
62 bool* isThisCellOnAFace,
63 const creal x,const creal y,const creal z,
64 const creal dx,const creal dy,const creal dz,
65 const bool excludeSlicesAndPeriodicDimensions //=false (default)
66 ) const {
67 for(uint i=0; i<6; i++) {
68 isThisCellOnAFace[i] = false;
69 }
70 if(x > Parameters::xmax - dx * 2) {
71 isThisCellOnAFace[0] = true;
72 }
73 if(x < Parameters::xmin + dx * 2) {
74 isThisCellOnAFace[1] = true;
75 }
76 if(y > Parameters::ymax - dy * 2) {
77 isThisCellOnAFace[2] = true;
78 }
79 if(y < Parameters::ymin + dy * 2) {
80 isThisCellOnAFace[3] = true;
81 }
82 if(z > Parameters::zmax - dz * 2) {
83 isThisCellOnAFace[4] = true;
84 }
85 if(z < Parameters::zmin + dz * 2) {
86 isThisCellOnAFace[5] = true;
87 }
88 if(excludeSlicesAndPeriodicDimensions == true) {
89 if (Parameters::xcells_ini == 1 || this->periodic[0]) {
90 isThisCellOnAFace[0] = false;
91 isThisCellOnAFace[1] = false;
92 }
93 if (Parameters::ycells_ini == 1 || this->periodic[1]) {
94 isThisCellOnAFace[2] = false;
95 isThisCellOnAFace[3] = false;
96 }
97 if (Parameters::zcells_ini == 1 || this->periodic[2]) {
98 isThisCellOnAFace[4] = false;
99 isThisCellOnAFace[5] = false;
100 }
101 }
102 }
103
117 std::array<bool, 6> &isThisCellOnAFace,
118 const dccrg::Dccrg<SpatialCell,dccrg::Cartesian_Geometry>& mpiGrid,
119 const CellID id,
120 const bool excludeSlicesAndPeriodicDimensions //=false (default)
121 ) {
122 isThisCellOnAFace.fill(false);
123
124 std::array<std::set<CellID>, 6> dirNeighbors;
125 auto* p = mpiGrid.get_neighbors_of(id, Neighborhoods::VLASOV_SOLVER);
126 if (!p) {
127 std::cerr << "No neighbors found for " << id << std::endl;
128 return;
129 }
130 int nbrs {0};
131 for (auto pair : *p) {
132 if (!pair.first) {
133 continue; // Error cells should obviously not be counted
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);
146 }
147 ++nbrs;
148 //std::cerr << pair.second[0] << " " << pair.second[1] << " " << pair.second[2] << std::endl;
149 }
150
151 for (int i = 0; i < 6; ++i) {
152 if(dirNeighbors[i].size() < 2) {
153 isThisCellOnAFace[i] = true;
154 }
155 }
156
157 if(excludeSlicesAndPeriodicDimensions == true) {
158 if(Parameters::xcells_ini == 1 || this->periodic[0]) {
159 isThisCellOnAFace[0] = false;
160 isThisCellOnAFace[1] = false;
161 }
162 if(Parameters::ycells_ini == 1 || this->periodic[1]) {
163 isThisCellOnAFace[2] = false;
164 isThisCellOnAFace[3] = false;
165 }
166 if(Parameters::zcells_ini == 1 || this->periodic[2]) {
167 isThisCellOnAFace[4] = false;
168 isThisCellOnAFace[5] = false;
169 }
170 }
171 return;
172 }
173
176
179
182 cerr << "ERROR: SysBoundaryCondition::addParameters called instead of derived class function!" << endl;
183 }
184
190 void
192 fsgrids::dmomentsspan dmoments,
193 const fsgrid::FsStencil& stencil, cuint component) {
194 auto& dPerBGrid0 = dperb[stencil.ooo()];
195 auto& dMomentsGrid0 = dmoments[stencil.ooo()];
196 switch(component) {
197 case 0: // x, xx
198 dMomentsGrid0[fsgrids::dmoments::drhomdx] = 0.0;
199 dMomentsGrid0[fsgrids::dmoments::drhoqdx] = 0.0;
200 dMomentsGrid0[fsgrids::dmoments::dp11dx] = 0.0;
201 dMomentsGrid0[fsgrids::dmoments::dp22dx] = 0.0;
202 dMomentsGrid0[fsgrids::dmoments::dp33dx] = 0.0;
203 dMomentsGrid0[fsgrids::dmoments::dVxdx] = 0.0;
204 dMomentsGrid0[fsgrids::dmoments::dVydx] = 0.0;
205 dMomentsGrid0[fsgrids::dmoments::dVzdx] = 0.0;
206
207 dPerBGrid0[fsgrids::dperb::dPERBydx] = 0.0;
208 dPerBGrid0[fsgrids::dperb::dPERBzdx] = 0.0;
209 dPerBGrid0[fsgrids::dperb::dPERBydxx] = 0.0;
210 dPerBGrid0[fsgrids::dperb::dPERBzdxx] = 0.0;
211 break;
212 case 1: // y, yy
213 dMomentsGrid0[fsgrids::dmoments::drhomdy] = 0.0;
214 dMomentsGrid0[fsgrids::dmoments::drhoqdy] = 0.0;
215 dMomentsGrid0[fsgrids::dmoments::dp11dy] = 0.0;
216 dMomentsGrid0[fsgrids::dmoments::dp22dy] = 0.0;
217 dMomentsGrid0[fsgrids::dmoments::dp33dy] = 0.0;
218 dMomentsGrid0[fsgrids::dmoments::dVxdy] = 0.0;
219 dMomentsGrid0[fsgrids::dmoments::dVydy] = 0.0;
220 dMomentsGrid0[fsgrids::dmoments::dVzdy] = 0.0;
221
222 dPerBGrid0[fsgrids::dperb::dPERBxdy] = 0.0;
223 dPerBGrid0[fsgrids::dperb::dPERBzdy] = 0.0;
224 dPerBGrid0[fsgrids::dperb::dPERBxdyy] = 0.0;
225 dPerBGrid0[fsgrids::dperb::dPERBzdyy] = 0.0;
226 break;
227 case 2: // z, zz
228 dMomentsGrid0[fsgrids::dmoments::drhomdz] = 0.0;
229 dMomentsGrid0[fsgrids::dmoments::drhoqdz] = 0.0;
230 dMomentsGrid0[fsgrids::dmoments::dp11dz] = 0.0;
231 dMomentsGrid0[fsgrids::dmoments::dp22dz] = 0.0;
232 dMomentsGrid0[fsgrids::dmoments::dp33dz] = 0.0;
233 dMomentsGrid0[fsgrids::dmoments::dVxdz] = 0.0;
234 dMomentsGrid0[fsgrids::dmoments::dVydz] = 0.0;
235 dMomentsGrid0[fsgrids::dmoments::dVzdz] = 0.0;
236
237 dPerBGrid0[fsgrids::dperb::dPERBxdz] = 0.0;
238 dPerBGrid0[fsgrids::dperb::dPERBydz] = 0.0;
239 dPerBGrid0[fsgrids::dperb::dPERBxdzz] = 0.0;
240 dPerBGrid0[fsgrids::dperb::dPERBydzz] = 0.0;
241 break;
242 case 3: // xy
243 dPerBGrid0[fsgrids::dperb::dPERBzdxy] = 0.0;
244 break;
245 case 4: // xz
246 dPerBGrid0[fsgrids::dperb::dPERBydxz] = 0.0;
247 break;
248 case 5: // yz
249 dPerBGrid0[fsgrids::dperb::dPERBxdyz] = 0.0;
250 break;
251 default:
252 cerr << __FILE__ << ":" << __LINE__ << ":" << " Invalid component" << endl;
253 abort_mpi("Invalid component", 1);
254 }
255 }
256
263 const fsgrid::FsStencil& stencil, cuint component) {
264 auto& vol = vols[stencil.ooo()];
265 switch(component) {
266 case 0:
270 break;
271 case 1:
275 break;
276 case 2:
280 break;
281 default:
282 abort_mpi("Invalid component", 1);
283 }
284 }
285
294 dccrg::Dccrg<SpatialCell,dccrg::Cartesian_Geometry>& mpiGrid,
295 const CellID& cellID,
296 const bool& copyMomentsOnly,
297 const uint popID,
298 const bool copy_V_moments
299 ) {
300 const CellID closestCell = getTheClosestNonsysboundaryCell(cellID);
301
302 if(closestCell == INVALID_CELLID) {
303 abort_mpi("No closest cell found!", 1);
304 }
305 copyCellData(mpiGrid[closestCell],mpiGrid[cellID], copyMomentsOnly, popID, copy_V_moments);
306 }
307
316 dccrg::Dccrg<SpatialCell,dccrg::Cartesian_Geometry>& mpiGrid,
317 const CellID& cellID,
318 const bool& copyMomentsOnly,
319 const uint popID,
320 const bool copy_V_moments
321 ) {
322 const CellID closestCell = getTheClosestL1OutflowCell(cellID);
323
324 if(closestCell == INVALID_CELLID) {
325 abort_mpi("No closest L1 Outflow cell found!", 1);
326 }
327 phiprof::Timer boundaryTimer {"vlasovBoundaryCopyFromTheClosestL1OutflowNbr"};
328 copyCellData(mpiGrid[closestCell],mpiGrid[cellID], copyMomentsOnly, popID, copy_V_moments);
329 boundaryTimer.stop();
330 }
331
339 dccrg::Dccrg<SpatialCell,dccrg::Cartesian_Geometry>& mpiGrid,
340 const CellID& cellID,const uint popID, const bool copy_V_moments
341 ) {
342 const vector<CellID>& closestCells = getAllClosestNonsysboundaryCells(cellID);
343
344 if(closestCells[0] == INVALID_CELLID) {
345 abort_mpi("No closest cell found!", 1);
346 }
347 averageCellData(mpiGrid, closestCells, mpiGrid[cellID], popID);
348 }
349
358 dccrg::Dccrg<SpatialCell,dccrg::Cartesian_Geometry>& mpiGrid,
359 const CellID& cellID,const uint popID,const bool copy_V_moments,const creal fluffiness
360 ) {
361 const vector<CellID>& closeCells = getAllCloseNonsysboundaryCells(cellID);
362
363 if(closeCells[0] == INVALID_CELLID) {
364 abort_mpi("No close cell found!", 1);
365 }
366 averageCellData(mpiGrid, closeCells, mpiGrid[cellID], popID, fluffiness);
367 }
368
377 const SpatialCell* const from,
378 SpatialCell* to,
379 const bool copyMomentsOnly,
380 const uint popID,
381 const bool copy_V_moments
382 ) {
383 if (popID == 0) {
384 if (copy_V_moments) {
393 } else {
402 }
403 }
404
405 if(copyMomentsOnly) {
406 to->get_population(popID).RHO = from->get_population(popID).RHO;
407 if (copy_V_moments) {
408 to->get_population(popID).RHO_V = from->get_population(popID).RHO_V;
409 } else {
410 to->get_population(popID).RHO_R = from->get_population(popID).RHO_R;
411 }
412 for (uint i=0; i<3; i++) {
413 to->get_population(popID).V[i] = from->get_population(popID).V[i];
414 if (copy_V_moments) {
415 to->get_population(popID).V_V[i] = from->get_population(popID).V_V[i];
416 } else {
417 to->get_population(popID).V_R[i] = from->get_population(popID).V_R[i];
418 }
419 }
420 for (uint i=0; i<6; i++) {
421 to->get_population(popID).P[i] = from->get_population(popID).P[i];
422 if (copy_V_moments) {
423 to->get_population(popID).P_V[i] = from->get_population(popID).P_V[i];
424 } else {
425 to->get_population(popID).P_R[i] = from->get_population(popID).P_R[i];
426 }
427 }
428 } else {
429 to->set_population(from->get_population(popID), popID);
430 }
431 }
432
441 const dccrg::Dccrg<SpatialCell,dccrg::Cartesian_Geometry>& mpiGrid,
442 const vector<CellID> cellList,
443 SpatialCell *to,
444 const uint popID,
445 const creal fluffiness /* default =0.0*/
446 ) {
447 const size_t numberOfCells = cellList.size();
448 creal factor = fluffiness / convert<Real>(numberOfCells);
449
450 // Rescale own vspace
451 if (fluffiness != 0.0) {
452 to->scale_population(1.0 - fluffiness, popID);
453 }
454 // Add other cell vspaces
455 for (size_t i=0; i<numberOfCells; i++) {
456 const SpatialCell* from = mpiGrid[cellList[i]];
457 to->increment_population(from->get_population(popID), factor, popID);
458 }
459 }
460
467 const dccrg::Dccrg<SpatialCell,dccrg::Cartesian_Geometry>& mpiGrid,
468 const vector<CellID> & local_cells_on_boundary
469 ) {
470 // Loop over cellids
471 for(vector<CellID>::const_iterator it = local_cells_on_boundary.begin(); it != local_cells_on_boundary.end(); ++it) {
472 const CellID cellId = *it;
473 vector<CellID> & closestCells = allClosestNonsysboundaryCells[cellId];
474 closestCells.clear();
475 vector<CellID> & closeCells = allCloseNonsysboundaryCells[cellId];
476 closeCells.clear();
477 vector<CellID> & closestL1OutflowCells = allClosestL1OutflowCells[cellId];
478 closestL1OutflowCells.clear();
479 vector<CellID> & closeL1OutflowCells = allCloseL1OutflowCells[cellId];
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();
485
486 // Only closer neighborhood for layer 1
487 if(mpiGrid[cellId]->sysBoundaryLayer == 1) {
488 for (auto nbrPair : *mpiGrid.get_neighbors_of(cellId, Neighborhoods::SYSBOUNDARIES)) {
489 if(nbrPair.first != INVALID_CELLID) {
490 CellID neighbor = nbrPair.first;
491 if(mpiGrid[neighbor]->sysBoundaryFlag == sysboundarytype::NOT_SYSBOUNDARY) {
492 // Find distance and update closestCells
493 d2 = nbrPair.second[0]*nbrPair.second[0] + nbrPair.second[1]*nbrPair.second[1] + nbrPair.second[2]*nbrPair.second[2];
494 for (auto i : *mpiGrid.get_neighbors_to(cellId, Neighborhoods::SYSBOUNDARIES)) {
495 if (i.first == neighbor) {
496 closeCells.push_back(neighbor);
497 if(d2 == dist) {
498 closestCells.push_back(neighbor);
499 } else if (d2 < dist) {
500 closestCells.clear();
501 closestCells.push_back(neighbor);
502 dist = d2;
503 }
504 }
505 }
506 }
507 }
508 }
509 }
510 // search further for L2
511 if (mpiGrid[cellId]->sysBoundaryLayer == 2) {
512 for (auto nbrPair : *mpiGrid.get_neighbors_of(cellId, Neighborhoods::SYSBOUNDARIES_EXTENDED)) {
513 if(nbrPair.first != INVALID_CELLID) {
514 CellID neighbor = nbrPair.first;
515 if(mpiGrid[neighbor]->sysBoundaryFlag == sysboundarytype::NOT_SYSBOUNDARY) {
516 // Find distance and update closestCells
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);
519 if(d2 == dist) {
520 closestCells.push_back(neighbor);
521 } else if (d2 < dist) {
522 closestCells.clear();
523 closestCells.push_back(neighbor);
524 dist = d2;
525 }
526 }
527 if(mpiGrid[cellId]->sysBoundaryFlag == sysboundarytype::OUTFLOW && mpiGrid[neighbor]->sysBoundaryFlag == sysboundarytype::OUTFLOW && mpiGrid[neighbor]->sysBoundaryLayer == 1) {
528 // Find distance and update closestCells
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);
531 if(d2L1 == distL1) {
532 closestL1OutflowCells.push_back(neighbor);
533 } else if (d2L1 < distL1) {
534 closestL1OutflowCells.clear();
535 closestL1OutflowCells.push_back(neighbor);
536 distL1 = d2L1;
537 }
538 }
539 }
540 }
541 }
542
543 if(closestCells.size() == 0) {
544 closestCells.push_back(INVALID_CELLID);
545 }
546 if(closeCells.size() == 0) {
547 closeCells.push_back(INVALID_CELLID);
548 }
549 if(closestL1OutflowCells.size() == 0) {
550 closestL1OutflowCells.push_back(INVALID_CELLID);
551 }
552 if(closeL1OutflowCells.size() == 0) {
553 closeL1OutflowCells.push_back(INVALID_CELLID);
554 }
555 }
556 return true;
557 }
558
566 cint i,
567 cint j,
568 cint k
569 ) {
570 const vector< array<int, 3> > closestCells = getAllClosestNonsysboundaryCells(technical, fsgrid, i, j, k);
571 return closestCells.at(0);
572 }
573
581 cint i,
582 cint j,
583 cint k
584 ) {
585 const auto stencil = fsgrid.makeStencil(i, j, k);
586 int distance = numeric_limits<int>::max();
587 vector<array<int, 3>> closestCells;
588
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);
596 }
597 }
598 }
599 }
600 }
601
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;
609 if (d == distance) {
610 closestCells.push_back({i + ii, j + jj, k + kk});
611 }
612 }
613 }
614 }
615 }
616 }
617
618 if (closestCells.empty()) {
619 closestCells.push_back({numeric_limits<int>::min()});
620 }
621
622 return closestCells;
623 }
624
631 const CellID& cellID
632 ) {
633 vector<CellID> & closestCells = allClosestNonsysboundaryCells.at(cellID);
634 return closestCells.at(0);
635 }
636
643 const CellID& cellID
644 ) {
645 vector<CellID> & closestCells = allClosestL1OutflowCells.at(cellID);
646 return closestCells.at(0);
647 }
648
655 const CellID& cellID
656 ) {
657 vector<CellID> & closestCells = allClosestNonsysboundaryCells.at(cellID);
658 return closestCells;
659 }
660
666 const CellID& cellID
667 ) {
668 vector<CellID> & closeCells = allCloseNonsysboundaryCells.at(cellID);
669 return closeCells;
670 }
671
674 const fsgrid::FsStencil& stencil, cuint component, cuint mask) {
675 int distance = numeric_limits<int>::max();
676 auto closestCellIndex = 0;
677
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 &&
685 tech.sysBoundaryFlag != sysboundarytype::DO_NOT_COMPUTE &&
686 tech.sysBoundaryFlag != sysboundarytype::OUTER_BOUNDARY_PADDING;
687 const int d = ii * ii + jj * jj + kk * kk;
688 if (copyable && d < distance) {
689 distance = d;
690 closestCellIndex = index;
691 }
692 }
693 }
694 }
695 }
696
697 if (distance == numeric_limits<int>::max()) {
698 abort_mpi("No closest cell found!", 1);
699 }
700
701 return b[closestCellIndex][fsgrids::bfield::PERBX + component];
702 }
703
708 cerr << "ERROR: SysBoundaryCondition::getFaces called instead of derived class function!" << endl;
709 for(int i=0; i<6; i++) {
710 faces[i]=false;
711 }
712 }
713
718
723
725 std::array<bool, 3> isFacePeriodic
726 ) {
727 this->periodic = isFacePeriodic;
728 }
729
732
734 std::array<Real, CellParams::N_SPATIAL_CELL_PARAMS>& cellParams
735 ) {
736 std::cerr << "Error: SysBoundaryCondition::mapCellPotentialAndGetEXBDrift called!\n";
737 }
738
740 const uint popID,
742 creal& rho,
743 creal& T,
744 creal& VX0,
745 creal& VY0,
746 creal& VZ0) {
747
748 bool search = true;
749 uint counter = 0;
750 const vmesh::LocalID* vblocks_ini = cell.get_velocity_grid_length(popID);
752 const Real mass = getObjectWrapper().particleSpecies[popID].mass;
753
754 vmesh::GlobalID *GIDbuffer;
755 #ifdef USE_GPU
756 // Host-pinned memory buffer, max possible size
757 const uint blocksCount = vblocks_ini[0]*vblocks_ini[1]*vblocks_ini[2];
758 CHK_ERR( gpuMallocHost((void**)&GIDbuffer,blocksCount*sizeof(vmesh::GlobalID)) );
759 #endif
760 // Non-GPU: insert directly into vmesh
761
762 Real V_crds[3];
763 Real dV[3];
764 dV[0] = cell.get_velocity_grid_block_size(popID)[0];
765 dV[1] = cell.get_velocity_grid_block_size(popID)[1];
766 dV[2] = cell.get_velocity_grid_block_size(popID)[2];
767 creal minValue = cell.getVelocityBlockMinValue(popID);
768 // Single cell, not block
769 const Real dvx=cell.get_velocity_grid_cell_size(popID)[0];
770 const Real dvy=cell.get_velocity_grid_cell_size(popID)[1];
771 const Real dvz=cell.get_velocity_grid_cell_size(popID)[2];
772
773 while (search) {
774 if (0.1 * minValue > projects::MaxwellianPhaseSpaceDensity(counter*dV[0]+0.5*dvx, 0.5*dvy, 0.5*dvz, T, rho, mass) || counter > vblocks_ini[0]) {
775 search = false;
776 }
777 counter++;
778 }
779 counter+=2;
780
781 Real vRadiusSquared = (Real)counter * (Real)counter * dV[0] * dV[0];
782
783 #ifndef USE_GPU
784 // sphere volume is 4/3 pi r^3, approximate that 5*counterX*counterY*counterZ is enough.
785 vmesh::LocalID currentMaxSize = 5*counter*counter*counter;
786 vmesh->setNewSize(currentMaxSize);
787 GIDbuffer = vmesh->getGrid()->data();
788 #endif
789
790 vmesh::LocalID LID = 0;
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) {
794 const vmesh::GlobalID GID = vmesh->getGlobalID(iv,jv,kv);
795
796 cell.get_velocity_block_coordinates(popID,GID,V_crds);
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]));
803
804 #ifndef USE_GPU
805 if (LID >= currentMaxSize) {
806 currentMaxSize = LID + counter*counter*counter;
807 vmesh->setNewSize(currentMaxSize);
808 GIDbuffer = vmesh->getGrid()->data();
809 }
810 #endif
811 if (R2 < vRadiusSquared) {
812 GIDbuffer[LID] = GID;
813 LID++;
814 }
815 }
816 }
817 }
818
819 // Set final size of vmesh
820 cell.get_population(popID).N_blocks = LID;
821
822 #ifdef USE_GPU
823 // Copy data into place
824 cell.dev_resize_vmesh(popID,LID);
825 vmesh::GlobalID *GIDtarget = vmesh->getGrid()->data();
826 gpuStream_t stream = gpu_getStream();
827 CHK_ERR( gpuMemcpyAsync(GIDtarget, GIDbuffer, LID*sizeof(vmesh::GlobalID), gpuMemcpyHostToDevice, stream));
828 CHK_ERR( gpuStreamSynchronize(stream) );
829 CHK_ERR( gpuFreeHost(GIDbuffer));
830 #else
831 vmesh->setNewSize(LID);
832 #endif
833
834 return LID;
835 }
836
838 bool* isThisCellOnAFace,
839 creal x, creal y, creal z,
840 creal dx, creal dy, creal dz,
841 const std::array<bool, 3> periodicity,
842 const bool excludeSlicesAndPeriodicDimensions//=false // (default)
843 ) {
844 for(uint i=0; i<6; i++) {
845 isThisCellOnAFace[i] = false;
846 }
847 if(x > Parameters::xmax - dx * 2) {
848 isThisCellOnAFace[0] = true;
849 }
850 if(x < Parameters::xmin + dx * 2) {
851 isThisCellOnAFace[1] = true;
852 }
853 if(y > Parameters::ymax - dy * 2) {
854 isThisCellOnAFace[2] = true;
855 }
856 if(y < Parameters::ymin + dy * 2) {
857 isThisCellOnAFace[3] = true;
858 }
859 if(z > Parameters::zmax - dz * 2) {
860 isThisCellOnAFace[4] = true;
861 }
862 if(z < Parameters::zmin + dz * 2) {
863 isThisCellOnAFace[5] = true;
864 }
865 if(excludeSlicesAndPeriodicDimensions == true) {
866 if (Parameters::xcells_ini == 1 || periodicity[0]) {
867 isThisCellOnAFace[0] = false;
868 isThisCellOnAFace[1] = false;
869 }
870 if (Parameters::ycells_ini == 1 || periodicity[1]) {
871 isThisCellOnAFace[2] = false;
872 isThisCellOnAFace[3] = false;
873 }
874 if (Parameters::zcells_ini == 1 || periodicity[2]) {
875 isThisCellOnAFace[4] = false;
876 isThisCellOnAFace[5] = false;
877 }
878 }
879 }
880
881 // The function above and the commented parts below make an implementation with lambda
882 // but it breaks some communicator and YPK did not manage to get a working version out of this.
883 // Left in the copies of variable so the [=] compiles without complaining.
884
885 void OuterBoundaryCondition::assignSysBoundary(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
887 bool doAssign;
888 std::array<bool, 6> isThisCellOnAFace;
889
890 // Assign boundary flags to local DCCRG cells
891 const vector<CellID>& cells = getLocalCells();
892 for (auto& id : cells) {
893 if (mpiGrid[id]->sysBoundaryFlag == sysboundarytype::DO_NOT_COMPUTE) {
894 continue;
895 }
896 creal* const cellParams = &(mpiGrid[id]->parameters[0]);
897 creal dx = cellParams[CellParams::DX];
898 creal dy = cellParams[CellParams::DY];
899 creal dz = cellParams[CellParams::DZ];
900 creal x = cellParams[CellParams::XCRD] + 0.5 * dx;
901 creal y = cellParams[CellParams::YCRD] + 0.5 * dy;
902 creal z = cellParams[CellParams::ZCRD] + 0.5 * dz;
903
904 for(uint i=0; i<6; i++) {
905 isThisCellOnAFace[i] = false;
906 }
907 determineFace(isThisCellOnAFace.data(), x, y, z, dx, dy, dz);
908 // Comparison of the array defining which faces to use and the array telling on which faces this cell is
909 doAssign = false;
910 for (int j = 0; j < 6; j++) {
911 doAssign = doAssign || (facesToProcess[j] && isThisCellOnAFace[j]);
912 }
913 if (doAssign) {
914 mpiGrid[id]->sysBoundaryFlag = this->getIndex();
915 }
916 }
917 const auto index_local = this->getIndex();
918 const std::array<bool, 6> facesToProcess_local = facesToProcess;
919 const std::array<bool, 3> periodic_local = this->periodic;
920 // Assign boundary flags to local fsgrid cells
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) {
924 creal dx = P::dx_ini * pow(2, -technical[stencil.ooo()].refLevel);
925 creal dy = P::dy_ini * pow(2, -technical[stencil.ooo()].refLevel);
926 creal dz = P::dz_ini * pow(2, -technical[stencil.ooo()].refLevel);
927
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;
932
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]);
936 }
937 if (doAssign) {
938 technical[stencil.ooo()].sysBoundaryFlag = index_local;
939 }
940 });
941 }
942
943} // namespace SBC
for i
Definition Dispersion.m:24
dx
Definition Dispersion.m:38
#define gpuStream_t
#define gpuStreamSynchronize
#define gpuMemcpyHostToDevice
#define CHK_ERR(err)
#define gpuMemcpyAsync
#define gpuMallocHost
#define gpuFreeHost
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)
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 &copyMomentsOnly, 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 &copyMomentsOnly, const uint popID, const bool calculate_V_moments)
void setPeriodicity(std::array< bool, 3 > isFacePeriodic)
virtual uint getIndex() const =0
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)
void copyCellData(const SpatialCell *from, SpatialCell *to, const bool copyMomentsOnly, const uint popID, const bool copy_V_moments)
CellID & getTheClosestL1OutflowCell(const CellID &cellID)
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)
Definition common.cpp:90
const std::vector< CellID > & getLocalCells()
Definition main.cpp:39
const uint32_t cuint
Definition definitions.h:50
float Real
Definition definitions.h:41
const int cint
Definition definitions.h:45
uint64_t CellID
Definition definitions.h:54
T convert(const T &number)
Definition definitions.h:56
fsgrid::FsGrid< FS_STENCIL_WIDTH > FieldSolverGrid
Definition definitions.h:78
const float creal
Definition definitions.h:42
__host__ gpuStream_t gpu_getStream()
Definition gpu_base.cpp:244
const int j
const int k
const Realf dvz
ObjectWrapper & getObjectWrapper()
Definition main.cpp:33
#define index(i, j, k)
@ SYSBOUNDARIES
Definition common.h:84
@ VLASOV_SOLVER
Definition common.h:77
@ SYSBOUNDARIES_EXTENDED
Definition common.h:85
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
Definition common.h:434
std::span< std::array< Real, fsgrids::dmoments::N_DMOMENTS > > dmomentsspan
Definition common.h:448
std::span< technical > technicalspan
Definition common.h:452
std::span< std::array< Real, fsgrids::dperb::N_DPERB > > dperbspan
Definition common.h:442
std::span< const technical > consttechnicalspan
Definition common.h:453
@ dPERBZVOLdx
Definition common.h:413
@ dPERBXVOLdz
Definition common.h:409
@ dPERBZVOLdy
Definition common.h:414
@ dPERBZVOLdz
Definition common.h:415
@ dPERBYVOLdx
Definition common.h:410
@ dPERBYVOLdy
Definition common.h:411
@ dPERBXVOLdy
Definition common.h:408
@ dPERBYVOLdz
Definition common.h:412
@ dPERBXVOLdx
Definition common.h:407
@ dVydz
Definition common.h:363
@ dp11dz
Definition common.h:351
@ dVydx
Definition common.h:361
@ dp22dy
Definition common.h:353
@ drhomdy
Definition common.h:344
@ dp33dy
Definition common.h:356
@ dVzdz
Definition common.h:366
@ dVzdx
Definition common.h:364
@ dp11dy
Definition common.h:350
@ drhoqdz
Definition common.h:348
@ dp22dx
Definition common.h:352
@ dVxdy
Definition common.h:359
@ dp22dz
Definition common.h:354
@ dp11dx
Definition common.h:349
@ drhomdz
Definition common.h:345
@ dp33dz
Definition common.h:357
@ dp33dx
Definition common.h:355
@ dVxdz
Definition common.h:360
@ drhoqdx
Definition common.h:346
@ drhomdx
Definition common.h:343
@ dVzdy
Definition common.h:365
@ drhoqdy
Definition common.h:347
@ dVydy
Definition common.h:362
@ dVxdx
Definition common.h:358
@ PERBX
Definition common.h:275
std::span< std::array< Real, fsgrids::volfields::N_VOL > > volspan
Definition common.h:450
@ dPERBzdxy
Definition common.h:338
@ dPERBzdy
Definition common.h:329
@ dPERBzdyy
Definition common.h:337
@ dPERBzdxx
Definition common.h:336
@ dPERBydxx
Definition common.h:333
@ dPERBydx
Definition common.h:326
@ dPERBydxz
Definition common.h:335
@ dPERBzdx
Definition common.h:328
@ dPERBxdzz
Definition common.h:331
@ dPERBxdyz
Definition common.h:332
@ dPERBydzz
Definition common.h:334
@ dPERBxdy
Definition common.h:324
@ dPERBxdyy
Definition common.h:330
@ dPERBxdz
Definition common.h:325
@ dPERBydz
Definition common.h:327
ARCH_HOSTDEV Realf MaxwellianPhaseSpaceDensity(creal &vx, creal &vy, creal &vz, creal &T, creal &rho, creal &mass)
Definition project.h:45
@ OUTER_BOUNDARY_PADDING
Definition common.h:493
uint32_t LocalID
Definition definitions.h:60
uint32_t GlobalID
Definition definitions.h:59
const uint64_t INVALID_CELLID
Definition parameters.h:35
std::vector< species::Species > particleSpecies
static Real ymax
Definition parameters.h:41
static Real dz_ini
Definition parameters.h:46
static Real dx_ini
Definition parameters.h:44
static Real xmax
Definition parameters.h:39
static uint zcells_ini
Definition parameters.h:50
static Real zmax
Definition parameters.h:43
static Real ymin
Definition parameters.h:40
static uint ycells_ini
Definition parameters.h:49
static uint xcells_ini
Definition parameters.h:48
static Real xmin
Definition parameters.h:38
static Real zmin
Definition parameters.h:42
static Real dy_ini
Definition parameters.h:45
static ARCH_HOSTDEV VecSimple< T > min(VecSimple< T > const &l, VecSimple< T > const &r)