OPAL (Object Oriented Parallel Accelerator Library) 2024.2
OPAL
AmrPartBunch.cpp
Go to the documentation of this file.
1//
2// Class AmrPartBunch
3// This class is used to represent a bunch in AMR mode.
4//
5// Copyright (c) 2017 - 2019, Matthias Frey, Paul Scherrer Institut, Villigen PSI, Switzerland
6// All rights reserved
7//
8// Implemented as part of the PhD thesis
9// "Precise Simulations of Multibunches in High Intensity Cyclotrons"
10//
11// This file is part of OPAL.
12//
13// OPAL is free software: you can redistribute it and/or modify
14// it under the terms of the GNU General Public License as published by
15// the Free Software Foundation, either version 3 of the License, or
16// (at your option) any later version.
17//
18// You should have received a copy of the GNU General Public License
19// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
20//
21#include "AmrPartBunch.h"
22
24
26 : PartBunchBase<double, 3>(new AmrPartBunch::pbase_t(new AmrLayout_t()), ref)
27 , amrobj_mp(nullptr)
28 , amrpbase_mp(dynamic_cast<AmrPartBunch::pbase_t*>(pbase_m.get()))
29 , fieldlayout_m(nullptr)
30{
31 amrpbase_mp->initializeAmr();
32}
33
35 : PartBunchBase<double, 3>(new AmrPartBunch::pbase_t(new AmrLayout_t(&pbase_p->getAmrLayout())), ref)
36 , amrobj_mp(nullptr)
37 , amrpbase_mp(dynamic_cast<AmrPartBunch::pbase_t*>(pbase_m.get()))
38 , fieldlayout_m(nullptr)
39{
40 amrpbase_mp->initializeAmr();
41}
42
44
45
49
50
54
55
57// Layout_t* layout = static_cast<Layout_t*>(&getLayout());
58}
59
60
62
63 if ( amrobj_mp && !amrobj_mp->isRefined() ) {
64 /* In the first call to this function we
65 * intialize all fine levels
66 */
67 amrobj_mp->initFineLevels();
68
69 } else {
70 bool isForbidTransform = amrpbase_mp->isForbidTransform();
71
72 if ( !isForbidTransform ) {
73 /*
74 * regrid in boosted frame
75 */
76 this->updateLorentzFactor();
77 // Lorentz transform + mapping to [-1,1]
78 amrpbase_mp->domainMapping();
79 amrpbase_mp->setForbidTransform(true);
80 }
81
82 this->update();
83
84 if ( !isForbidTransform ) {
85 amrpbase_mp->setForbidTransform(false);
86 // map particles back + undo Lorentz transform
87 amrpbase_mp->domainMapping(true);
88 }
89 }
90}
91
92
94 const double& scalefactor = amrpbase_mp->getScalingFactor();
95 return hr_m * scalefactor;
96}
97
98
100 // set dh_m = dh
102
103 // update base geometry with new mesh enlargement
104 AmrLayout_t* layout_p = &amrpbase_mp->getAmrLayout();
105 layout_p->setBoundingBox(dh);
106
107 // if amrobj_mp != nullptr --> we need to regrid
108 this->do_binaryRepart();
109}
110
111
115
116double AmrPartBunch::getRho(int x, int y, int z) {
117 /* This function is called in
118 * H5PartWrapperForPC::writeStepData(PartBunchBase<double, 3>* bunch)
119 * and
120 * H5PartWrapperForPT::writeStepData(PartBunchBase<double, 3>* bunch)
121 * in case of Options::rhoDump = true.
122 *
123 * Currently, we do not support writing multilevel grid data that's why
124 * we average the values down to the coarsest level.
125 */
126 return amrobj_mp->getRho(x, y, z);
127}
128
129
131 //TODO Implement
132 throw GeneralClassicException("AmrPartBunch::getFieldLayout", "Not yet Implemented.");
133 return *fieldlayout_m;
134}
135
136
139 //if(!R.isDirty() && stateOfLastBoundP_ == unit_state_) return;
140 if ( !(R.isDirty() || ID.isDirty() ) && stateOfLastBoundP_ == unit_state_) return; //-DW
141
143
144 if ( amrobj_mp ) {
145 /* we do an explicit domain mapping of the particles and then
146 * forbid it during the regrid process, this way it's only
147 * executed ones --> saves computation
148 */
149 bool isForbidTransform = amrpbase_mp->isForbidTransform();
150
151 if ( !isForbidTransform ) {
152 this->updateLorentzFactor();
153 // Lorentz transform + mapping to [-1,1]
154 amrpbase_mp->domainMapping();
155 amrpbase_mp->setForbidTransform(true);
156 }
157
158 this->update();
159
160 if ( !isForbidTransform ) {
161 amrpbase_mp->setForbidTransform(false);
162 // map particles back + undo Lorentz transform
163 amrpbase_mp->domainMapping(true);
164 }
165
166 } else {
167 // At this point an amrobj_mp needs already be set
168 throw GeneralClassicException("AmrPartBunch::boundp",
169 "AmrObject pointer is not set.");
170 }
171
172 R.resetDirtyFlag();
173
175}
176
177
180
181 if ( !fs_m->hasValidSolver() )
182 throw GeneralClassicException("AmrPartBunch::computeSelfFields",
183 "No field solver.");
184
185 amrobj_mp->computeSelfFields();
186
188}
189
190
196
197
203
204
207
208 /* make sure it is refined in multi-bunch case
209 */
210 if ( !amrobj_mp->isRefined() ) {
211 amrobj_mp->initFineLevels();
212 }
213
214 amrobj_mp->computeSelfFields_cycl(bin);
215
217}
218
219
220void AmrPartBunch::setAmrDomainRatio(const std::vector<double>& ratio) {
221 AmrLayout_t* layout_p = &amrpbase_mp->getAmrLayout();
222 layout_p->setDomainRatio(ratio);
223}
224
226 int nLevel = amrobj_mp->maxLevel() + 1;
227
228 std::unique_ptr<size_t[]> partPerLevel( new size_t[nLevel] );
229 globalPartPerLevel_m.reset( new size_t[nLevel] );
230
231 for (int i = 0; i < nLevel; ++i)
232 partPerLevel[i] = globalPartPerLevel_m[i] = 0.0;
233
234 // do not modify LocalNumPerLevel in here!!!
235 auto& LocalNumPerLevel = amrpbase_mp->getLocalNumPerLevel();
236
237 for (size_t i = 0; i < LocalNumPerLevel.size(); ++i)
238 partPerLevel[i] = LocalNumPerLevel[i];
239
240 reduce(*partPerLevel.get(),
242 nLevel, std::plus<size_t>());
243}
244
245
246const size_t& AmrPartBunch::getLevelStatistics(int l) const {
247 return globalPartPerLevel_m[l];
248}
249
250
252 double gamma = this->get_gamma();
253
254 if ( this->weHaveBins() ) {
255 gamma = this->getBinGamma(bin);
256 }
257
258 /* At the beginning of simulation the Lorentz factor
259 * is not yet set since PartBunchBase::calcBeamParameters
260 * is not yet called. Therefore, we do this ugly workaround.
261 */
262 bool init = true;
263 if ( gamma >= 1.0 ) {
264 init = false;
265 }
266
267 if ( init ) {
268 gamma = 1.0;
269 }
270
271 updateLorentzFactor(gamma);
272}
273
274
276 // keep all 1.0, except longitudinal direction
277 Vector_t lorentzFactor(1.0, 1.0, 1.0);
278
279 if (OpalData::getInstance()->isInOPALCyclMode()) {
280 lorentzFactor[1] = gamma;
281 } else {
282 lorentzFactor[2] = gamma;
283 }
284
285 amrpbase_mp->setLorentzFactor(lorentzFactor);
286}
287
288
290
292 grid = amrobj_mp->getBaseLevelGridPoints();
293}
294
295
296void AmrPartBunch::updateFields(const Vector_t& /*hr*/, const Vector_t& /*origin*/) {
297 //TODO regrid; called in boundp()
298// amrobj_mp->updateMesh();
299}
CenteredFieldLayout< 3, Mesh_t, Center_t > FieldLayout_t
Definition PBunchDefs.h:28
BoxLibLayout< double, 3 > AmrLayout_t
Definition PBunchDefs.h:37
bool reduce(Communicate &, InputIterator, InputIterator, OutputIterator, const ReduceOp &, bool *IncludeVal=0)
std::shared_ptr< AbstractParticle< double, Dim > > pbase_m
virtual void set_meshEnlargement(double dh)
IpplTimings::TimerRef boundpTimer_m
PartBunchBase(AbstractParticle< double, Dim > *pb, const PartData *ref)
std::pair< Vector_t, Vector_t > VectorPair_t
IpplTimings::TimerRef selfFieldTimer_m
static OpalData * getInstance()
Definition OpalData.cpp:196
void setBoundingBox(double dh)
void setDomainRatio(const std::vector< double > &ratio)
void computeSelfFields_cycl(double gamma)
void updateDomainLength(Vektor< int, 3 > &grid)
void initialize(FieldLayout_t *fLayout)
void updateLorentzFactor(int bin=0)
void computeSelfFields()
AmrPartBunch(const PartData *ref)
VectorPair_t getEExtrema()
FieldLayout_t * fieldlayout_m
void set_meshEnlargement(double dh)
void do_binaryRepart()
const size_t & getLevelStatistics(int l) const
Vector_t get_hr() const
pbase_t * amrpbase_mp
AmrObject * amrobj_mp
std::unique_ptr< size_t[]> globalPartPerLevel_m
void gatherLevelStatistics()
AmrParticle_t pbase_t
void updateFieldContainers_m()
void setAmrDomainRatio(const std::vector< double > &ratio)
void updateFields(const Vector_t &hr, const Vector_t &origin)
pbase_t * getAmrParticleBase()
double getRho(int x, int y, int z)
FieldLayout_t & getFieldLayout()
static void stopTimer(TimerRef t)
static void startTimer(TimerRef t)
Vektor< double, 3 > Vector_t