OPALX (Object Oriented Parallel Accelerator Library for Exascale) MINIorX
OPALX
Distribution.cpp
Go to the documentation of this file.
1//
2// Class Distribution
3// This class defines the initial beam that is injected or emitted into the simulation.
4//
5// Copyright (c) 2008 - 2022, Paul Scherrer Institut, Villigen PSI, Switzerland
6// All rights reserved
7//
8// This file is part of OPAL.
9//
10// OPAL is free software: you can redistribute it and/or modify
11// it under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// You should have received a copy of the GNU General Public License
16// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
17//
22#include "Algorithms/PartBins.h"
23#include "BasicActions/Option.h"
26#include "OPALTypes.h"
27#include "Physics/Physics.h"
28#include "Physics/Units.h"
32#include "Utilities/Options.h"
33#include "Utilities/Util.h"
34#include "Utility/IpplTimings.h"
35
36#include <gsl/gsl_linalg.h>
37#include <gsl/gsl_randist.h>
38#include <gsl/gsl_rng.h>
39#include <gsl/gsl_sf_erf.h>
40
41#include <boost/filesystem.hpp>
42#include <boost/numeric/odeint/stepper/runge_kutta4.hpp>
43#include <boost/regex.hpp>
44
45#include <sys/time.h>
46
47#include <cfloat>
48#include <cmath>
49#include <iomanip>
50#include <iostream>
51#include <map>
52#include <numeric>
53
54extern Inform* gmsg;
55
56using GeneratorPool = typename Kokkos::Random_XorShift64_Pool<>;
57
59
61
62namespace DISTRIBUTION {
66}
67
68/*
69namespace {
70 matrix_t getUnit6x6() {
71 matrix_t unit6x6(6, 6, 0.0); // Initialize a 6x6 matrix with all elements as 0.0
72 for (unsigned int i = 0; i < 6u; ++i) {
73 unit6x6(i, i) = 1.0; // Set diagonal elements to 1.0
74 }
75 return unit6x6;
76 }
77}
78*/
79
81 : Definition(
82 DISTRIBUTION::SIZE, "DISTRIBUTION",
83 "The DISTRIBUTION statement defines data for the 6D particle distribution."),
84 distrTypeT_m(DistributionType::NODIST) {
86 Attributes::makePredefinedString("TYPE", "Distribution type.", {"GAUSS", "MULTIVARIATEGAUSS", "FLATTOP", "FROMFILE"});
87
89 Attributes::makeString("FNAME", "File for reading in 6D particle coordinates.", "");
90
91 // Parameters for defining an initial distribution.
92 itsAttr[DISTRIBUTION::SIGMAX] = Attributes::makeReal("SIGMAX", "SIGMAx (m)", 0.0);
93 itsAttr[DISTRIBUTION::SIGMAY] = Attributes::makeReal("SIGMAY", "SIGMAy (m)", 0.0);
94 itsAttr[DISTRIBUTION::SIGMAZ] = Attributes::makeReal("SIGMAZ", "SIGMAz (m)", 0.0);
95 itsAttr[DISTRIBUTION::SIGMAPX] = Attributes::makeReal("SIGMAPX", "SIGMApx", 0.0);
96 itsAttr[DISTRIBUTION::SIGMAPY] = Attributes::makeReal("SIGMAPY", "SIGMApy", 0.0);
97 itsAttr[DISTRIBUTION::SIGMAPZ] = Attributes::makeReal("SIGMAPZ", "SIGMApz", 0.0);
98
99 itsAttr[DISTRIBUTION::CORR] = Attributes::makeRealArray("CORR", "r correlation");
100
101 itsAttr[DISTRIBUTION::CUTOFFPX] = Attributes::makeReal("CUTOFFPX", "Distribution cutoff px dimension in units of sigma.", 3.0);
102 itsAttr[DISTRIBUTION::CUTOFFPY] = Attributes::makeReal("CUTOFFPY", "Distribution cutoff py dimension in units of sigma.", 3.0);
103 itsAttr[DISTRIBUTION::CUTOFFPZ] = Attributes::makeReal("CUTOFFPZ", "Distribution cutoff pz dimension in units of sigma.", 3.0);
104
105 itsAttr[DISTRIBUTION::CUTOFFX] = Attributes::makeReal("CUTOFFX", "Distribution cutoff x direction in units of sigma.", 3.0);
106 itsAttr[DISTRIBUTION::CUTOFFY] = Attributes::makeReal("CUTOFFY", "Distribution cutoff r direction in units of sigma.", 3.0);
107 itsAttr[DISTRIBUTION::CUTOFFLONG] = Attributes::makeReal("CUTOFFLONG", "Distribution cutoff z or t direction in units of sigma.", 3.0);
108
109 itsAttr[DISTRIBUTION::CORRX] = Attributes::makeReal("CORRX", "x/px correlation, (R12 in transport notation).", 0.0);
110 itsAttr[DISTRIBUTION::CORRY] = Attributes::makeReal("CORRY", "y/py correlation, (R34 in transport notation).", 0.0);
111 itsAttr[DISTRIBUTION::CORRZ] = Attributes::makeReal("CORRZ", "z/pz correlation, (R56 in transport notation).", 0.0);
112 itsAttr[DISTRIBUTION::CORRT] = Attributes::makeReal("CORRT", "t/pt correlation, (R56 in transport notation).", 0.0);
113
114 itsAttr[DISTRIBUTION::SIGMAT] = Attributes::makeReal("SIGMAT", "SIGMAt (m)", 0.0);
115 itsAttr[DISTRIBUTION::TPULSEFWHM] = Attributes::makeReal("TPULSEFWHM", "Pulse FWHM for emitted distribution.", 0.0);
116 itsAttr[DISTRIBUTION::TRISE] = Attributes::makeReal("TRISE", "Rise time for emitted distribution.", 0.0);
117 itsAttr[DISTRIBUTION::TFALL] = Attributes::makeReal("TFALL", "Fall time for emitted distribution.", 0.0);
118
120 = Attributes::makeReal("FTOSCAMPLITUDE", "Amplitude of oscillations superimposed "
121 "on flat top portion of emitted GAUSS "
122 "distribtuion (in percent of flat top "
123 "amplitude)",0.0);
124
126 = Attributes::makeReal("FTOSCPERIODS", "Number of oscillations superimposed on "
127 "flat top portion of emitted GAUSS "
128 "distribution", 0.0);
129
131 = Attributes::makeBool("EMITTED", "Emitted beam, from cathode, as opposed to "
132 "an injected beam.", false);
133
135}
136
137Distribution::Distribution(const std::string& name, Distribution* parent)
138 : Definition(name, parent) {
139}
140
142}
143
153 size_t locNumber = n / ippl::Comm->size();
154
155 // make sure the total number is exact
156 size_t remainder = n % ippl::Comm->size();
157 size_t myNode = ippl::Comm->rank();
158 if (myNode < remainder)
159 ++locNumber;
160
161 return locNumber;
162}
163
166 return dynamic_cast<Distribution*>(object) != 0;
167}
168
169Distribution* Distribution::clone(const std::string& name) {
170 return new Distribution(name, this);
171}
172
175 update();
176}
177
178Distribution* Distribution::find(const std::string& name) {
179 Distribution* dist = dynamic_cast<Distribution*>(OpalData::getInstance()->find(name));
180
181 if (dist == 0) {
182 throw OpalException("Distribution::find()", "Distribution \"" + name + "\" not found.");
183 }
184
185 return dist;
186}
187
189 os << "\n"
190 << "* ************* D I S T R I B U T I O N ********************************************"
191 << endl;
192 os << "* " << endl;
193 if (OpalData::getInstance()->inRestartRun()) {
194 os << "* In restart. Distribution read in from .h5 file." << endl;
195 } else {
196 switch (distrTypeT_m) {
198 printDistGauss(os);
199 break;
202 break;
205 break;
206 default:
207 throw OpalException("Distribution Param", "Unknown \"TYPE\" of \"DISTRIBUTION\"");
208 }
209 os << "* " << endl;
210 os << "* Distribution is injected." << endl;
211 }
212 os << "* " << endl;
213 os << "* **********************************************************************************"
214 << endl;
215
216 return os;
217}
218
219void Distribution::setAvrgPz(double avrgpz){
220 avrgpz_m = avrgpz;
221}
222
223void Distribution::setTEmission(double tEmission) {
224 tEmission_m = tEmission;
225}
226
228 return tEmission_m;
229}
230
232 /*
233 * Set distribution parameters. Do all the necessary checks depending
234 * on the input attributes.
235 * In case of DistributionType::MATCHEDGAUSS we only need to set the cutoff parameters
236 */
237
238 cutoffR_m = 3.;
239 cutoffP_m = 3.;
240 /*
241 cutoffP_m = ippl::Vector<double, 3>(Attributes::getReal(itsAttr[DISTRIBUTION::CUTOFFPX]),
242 Attributes::getReal(itsAttr[DISTRIBUTION::CUTOFFPY]),
243 Attributes::getReal(itsAttr[DISTRIBUTION::CUTOFFPZ]));
244
245
246 cutoffR_m = ippl::Vector<double, 3>(Attributes::getReal(itsAttr[DISTRIBUTION::CUTOFFX]),
247 Attributes::getReal(itsAttr[DISTRIBUTION::CUTOFFY]),
248 Attributes::getReal(itsAttr[DISTRIBUTION::CUTOFFLONG]));
249 */
250
251 //if (std::abs(Attributes::getReal(itsAttr[Attrib::Distribution::SIGMAR])) > 0.0) {
252 // cutoffR_m[0] = Attributes::getReal(itsAttr[Attrib::Distribution::CUTOFFR]);
253 // cutoffR_m[1] = Attributes::getReal(itsAttr[Attrib::Distribution::CUTOFFR]);
254 //}
255
256 setSigmaR_m();
257 setSigmaP_m();
258
259 avrgpz_m = 0.0;
260}
261
263
264 cutoffR_m = 3.;
265 cutoffP_m = 3.;
266
267 // initialize the covariance matrix to identity
268 for (unsigned int i = 0; i < 6; ++ i) {
269 for (unsigned int j = 0; j < 6; ++ j) {
270 if (i==j)
271 correlationMatrix_m[i][j] = 1.0;
272 else
273 correlationMatrix_m[i][j] = 0.0;
274 }
275 }
276
277 // set diagonal elements first
278 setSigmaR_m();
279 setSigmaP_m();
280
281 for (unsigned int i = 0; i < 3; ++ i){
282 correlationMatrix_m[2*i ][2*i ] = sigmaR_m[i]*sigmaR_m[i];
283 correlationMatrix_m[2*i+1][2*i+1] = sigmaP_m[i]*sigmaP_m[i];
284 }
285
286 std::vector<double> cr = Attributes::getRealArray(itsAttr[DISTRIBUTION::CORR]);
287
288 if (!cr.empty()) {
289 // read off-diagonal correlation matrix from input file
290 if (cr.size() == 15) {
291 *gmsg << "* Use r to specify correlations" << endl;
292 unsigned int k = 0;
293 for (unsigned int i = 0; i < 5; ++ i) {
294 for (unsigned int j = i + 1; j < 6; ++ j, ++ k) {
295 correlationMatrix_m[j][i] = cr.at(k)*cr.at(k);
296 correlationMatrix_m[i][j] = correlationMatrix_m[j][i]; // impose symmetry
297 }
298 }
299 }
300 else {
301 throw OpalException("Distribution::SetDistParametersGauss",
302 "Inconsistent set of correlations specified, check manual");
303 }
304 }
305
306 avrgpz_m = 0.0;
307}
308
310
311 cutoffR_m = 3.;
312 cutoffP_m = 3.;
313
314 // set diagonal elements first
315 setSigmaR_m();
316 setSigmaP_m();
317
318 // initialize the covariance matrix to identity
319 for (unsigned int i = 0; i < 6; ++ i) {
320 for (unsigned int j = 0; j < 6; ++ j) {
321 if (i==j)
322 correlationMatrix_m[i][j] = 1.0;
323 else
324 correlationMatrix_m[i][j] = 0.0;
325 }
326 }
327
332
336
339
341
342 if (emitting_m) {
343 sigmaR_m[2] = 0.0;
344
348
351
352 // If TRISE and TFALL are defined > 0.0 then these attributes
353 // override SIGMAT.
354 //
356 || std::abs(Attributes::getReal(itsAttr[DISTRIBUTION::TFALL])) > 0.0) {
357
358 double timeRatio = std::sqrt(2.0 * std::log(10.0)) - std::sqrt(2.0 * std::log(10.0 / 9.0));
359
360 if (std::abs(Attributes::getReal(itsAttr[DISTRIBUTION::TRISE])) > 0.0)
362 / timeRatio;
363
364 if (std::abs(Attributes::getReal(itsAttr[DISTRIBUTION::TFALL])) > 0.0)
366 / timeRatio;
367 }
368
369 // For an emitted beam, the longitudinal cutoff >= 0.
370 cutoffR_m[2] = std::abs(cutoffR_m[2]);
371
372 }
373}
374
376 os << "* Distribution type: GAUSS" << endl;
377 os << "* " << endl;
378 os << "* SIGMAX = " << sigmaR_m[0] << " [m]" << endl;
379 os << "* SIGMAY = " << sigmaR_m[1] << " [m]" << endl;
380 os << "* SIGMAZ = " << sigmaR_m[2] << " [m]" << endl;
381 os << "* SIGMAPX = " << sigmaP_m[0] << " [Beta Gamma]" << endl;
382 os << "* SIGMAPY = " << sigmaP_m[1] << " [Beta Gamma]" << endl;
383 os << "* SIGMAPZ = " << sigmaP_m[2] << " [Beta Gamma]" << endl;
384}
385
387 os << "* Distribution type: MULTIVARIATEGAUSS" << endl;
388 os << "* " << endl;
389 os << "* SIGMAX = " << sigmaR_m[0] << " [m]" << endl;
390 os << "* SIGMAY = " << sigmaR_m[1] << " [m]" << endl;
391 os << "* SIGMAZ = " << sigmaR_m[2] << " [m]" << endl;
392 os << "* SIGMAPX = " << sigmaP_m[0] << " [Beta Gamma]" << endl;
393 os << "* SIGMAPY = " << sigmaP_m[1] << " [Beta Gamma]" << endl;
394 os << "* SIGMAPZ = " << sigmaP_m[2] << " [Beta Gamma]" << endl;
395
396 os << "* input cov matrix = ";
397 for (unsigned int i = 0; i < 6; ++ i) {
398 for (unsigned int j = 0; j < 6; ++ j) {
399 os << correlationMatrix_m[i][j] << " ";
400 }
401 os << endl << " ";
402 }
403}
404
406 os << "* Distribution type: FLATTOP" << endl;
407 os << "* " << endl;
408 os << "* SIGMAX = " << sigmaR_m[0] << " [m]" << endl;
409 os << "* SIGMAY = " << sigmaR_m[1] << " [m]" << endl;
410
411 if (emitting_m) {
412 os << "* Sigma Time Rise = " << sigmaTRise_m
413 << " [sec]" << endl;
414 os << "* TPULSEFWHM = " << tPulseLengthFWHM_m
415 << " [sec]" << endl;
416 os << "* Sigma Time Fall = " << sigmaTFall_m
417 << " [sec]" << endl;
418 os << "* Longitudinal cutoff = " << cutoffR_m[2]
419 << " [units of Sigma Time]" << endl;
420 //os << "* Flat top modulation amplitude = "
421 // << Attributes::getReal(itsAttr[DISTRIBUTION::FTOSCAMPLITUDE])
422 // << " [Percent of distribution amplitude]" << endl;
423 //os << "* Flat top modulation periods = "
424 // << std::abs(Attributes::getReal(itsAttr[DISTRIBUTION::FTOSCPERIODS]))
425 // << endl;
426 }
427 else{
428 os << "* SIGMAZ = " << sigmaR_m[2] << " [m]" << endl;
429 }
430}
431
433 setDist();
434}
435
437 // set distribution type
438 setDistType();
439 // set distribution parameters
440 switch (distrTypeT_m) {
443 break;
446 break;
449 break;
450 default:
451 throw OpalException("Distribution Param", "Unknown \"TYPE\" of \"DISTRIBUTION\"");
452 }
453}
454
456 static const std::map<std::string, DistributionType> typeStringToDistType_s = {
457 {"NODIST", DistributionType::NODIST},
458 {"GAUSS", DistributionType::GAUSS},
459 {"MULTIVARIATEGAUSS", DistributionType::MULTIVARIATEGAUSS},
460 {"FLATTOP", DistributionType::FLATTOP}
461 };
462
464
465 if (distT_m.empty()) {
466 throw OpalException(
467 "Distribution::setDistType",
468 "The attribute \"TYPE\" isn't set for the \"DISTRIBUTION\"!");
469 } else {
470 distrTypeT_m = typeStringToDistType_s.at(distT_m);
471 }
472}
473
479}
480
486}
487
@ SIZE
Definition: IndexMap.cpp:173
typename Kokkos::Random_XorShift64_Pool<> GeneratorPool
typename ippl::detail::ViewType< ippl::Vector< double, Dim >, 1 >::view_type view_type
Inform * gmsg
Definition: changes.cpp:7
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
Attribute makeBool(const std::string &name, const std::string &help)
Make logical attribute.
Definition: Attributes.cpp:90
double getReal(const Attribute &attr)
Return real value.
Definition: Attributes.cpp:252
Attribute makePredefinedString(const std::string &name, const std::string &help, const std::initializer_list< std::string > &predefinedStrings)
Make predefined string attribute.
Definition: Attributes.cpp:409
Attribute makeReal(const std::string &name, const std::string &help)
Make real attribute.
Definition: Attributes.cpp:240
bool getBool(const Attribute &attr)
Return logical value.
Definition: Attributes.cpp:100
Attribute makeRealArray(const std::string &name, const std::string &help)
Create real array attribute.
Definition: Attributes.cpp:289
std::vector< double > getRealArray(const Attribute &attr)
Get array value.
Definition: Attributes.cpp:294
std::string getString(const Attribute &attr)
Get string value.
Definition: Attributes.cpp:343
Attribute makeString(const std::string &name, const std::string &help)
Make string attribute.
Definition: Attributes.cpp:332
std::unique_ptr< mpi::Communicator > Comm
Definition: Ippl.h:22
The base class for all OPAL definitions.
Definition: Definition.h:30
The base class for all OPAL objects.
Definition: Object.h:48
void registerOwnership(const AttributeHandler::OwnerType &itsClass) const
Definition: Object.cpp:189
virtual void update()
Update this object.
Definition: Object.cpp:261
std::vector< Attribute > itsAttr
The object attributes.
Definition: Object.h:216
Object * find(const std::string &name)
Find entry.
Definition: OpalData.cpp:563
static OpalData * getInstance()
Definition: OpalData.cpp:195
static Distribution * find(const std::string &name)
ippl::Vector< double, 3 > sigmaR_m
void printDistFlatTop(Inform &os) const
ippl::Vector< double, 3 > sigmaP_m
virtual void execute()
Execute the command.
double getTEmission() const
Distribution is an emitted, and is currently emitting, rather than an injected, beam.
void setSigmaR_m()
virtual bool canReplaceBy(Object *object)
Distribution can only be replaced by another distribution.
ippl::Vector< double, 3 > cutoffR_m
virtual ~Distribution()
void setSigmaP_m()
void setDistParametersMultiVariateGauss()
virtual Distribution * clone(const std::string &name)
Return a clone.
void printDistMultiVariateGauss(Inform &os) const
ippl::Vector< double, 3 > cutoffP_m
void setAttributes()
void setDistType()
size_t getNumOfLocalParticlesToCreate(size_t n)
Calculate the local number of particles evenly and adjust node 0 such that n is matched exactly.
void setTEmission(double tEmission)
void setDistParametersFlatTop()
void setAvrgPz(double avrgpz)
void printDistGauss(Inform &os) const
Inform & printInfo(Inform &os) const
void setDistParametersGauss()
The base class for all OPAL exceptions.
Definition: OpalException.h:28
Definition: Inform.h:40