32 #include "mithra/classes.h"
33 #include "mithra/database.h"
34 #include "mithra/datainput.h"
35 #include "mithra/fdtdSC.h"
36 #include "mithra/fieldvector.h"
37 #include "mithra/readdata.h"
38 #include "mithra/stdinclude.h"
48 lambda_m(right.lambda_m),
49 numPeriods_m(right.numPeriods_m),
50 angle_m(right.angle_m),
51 fname_m(right.fname_m),
52 meshLength_m(right.meshLength_m),
53 meshResolution_m(right.meshResolution_m),
54 truncationOrder_m(right.truncationOrder_m),
55 totalTime_m(right.totalTime_m),
56 dtBunch_m(right.dtBunch_m),
57 hasBeenSimulated_m(right.hasBeenSimulated_m) {
68 meshResolution_m(3, 0.0),
72 hasBeenSimulated_m(false) {
79 visitor.visitUndulator(*
this);
89 Inform msg(
"MITHRA FW solver ", *gmsg);
92 const unsigned int localNum = itsBunch->
getLocalNum();
93 for (
unsigned int i = 0; i < localNum; ++i) {
94 itsBunch->
R[i] = refToLocalCSTrafo.
transformTo(itsBunch->
R[i]);
95 itsBunch->
P[i] = refToLocalCSTrafo.
rotateTo(itsBunch->
P[i]);
99 msg <<
"Bunch before undulator in local coordinate system: " <<
endl;
100 itsBunch->
print(msg);
102 MITHRA::helloMessage();
105 MITHRA::BunchInitialize bunchInit;
106 bunchInit.bunchType_ =
"other";
107 bunchInit.numberOfParticles_ = itsBunch->
getTotalNum();
108 bunchInit.cloudCharge_ =
110 bunchInit.initialGamma_ = itsBunch->
get_gamma();
111 for (
unsigned int d = 0; d < 3; ++d)
112 bunchInit.initialDirection_[d] = itsBunch->
get_pmean()[d];
115 bunch.bunchInit_.push_back(bunchInit);
117 msg <<
"Bunch parameters have been transferred to the full-wave solver." <<
endl;
119 MITHRA::Undulator undulator;
120 undulator.k_ =
getK();
124 double lFringe = 2 * undulator.lu_;
126 std::vector<MITHRA::Undulator> undulators;
127 undulators.push_back(undulator);
128 msg <<
"Undulator parameters have been transferred to the full-wave solver." <<
endl;
132 mesh.lengthScale_ = 1.0;
133 mesh.timeScale_ = 1.0;
134 mesh.meshCenter_ = MITHRA::FieldVector<double>(0.0);
139 if (mesh.totalTime_ == 0)
140 mesh.totalDist_ = lFringe + undulator.lu_ * undulator.length_;
142 mesh.spaceCharge_ =
true;
143 mesh.optimizePosition_ =
true;
144 msg <<
"Mesh parameters have been transferred to the full-wave solver." <<
endl;
148 std::vector<MITHRA::ExtField> externalFields;
149 std::vector<MITHRA::FreeElectronLaser> FELs;
153 std::list<std::string> jobFile = MITHRA::read_file(
fname_m.c_str());
154 MITHRA::cleanJobFile(jobFile);
155 MITHRA::ParseDarius parser(jobFile, mesh, bunch, seed, undulators, externalFields, FELs);
156 parser.setJobParameters();
159 MITHRA::FdTdSC solver(mesh, bunch, seed, undulators, externalFields, FELs);
162 MITHRA::Charge charge;
164 for (
unsigned int i = 0; i < localNum; ++i) {
165 for (
unsigned int d = 0; d < 3; ++d) {
166 charge.rnp[d] = itsBunch->
R[i][d];
167 charge.gbnp[d] = itsBunch->
P[i][d];
169 solver.chargeVectorn_.push_back(charge);
171 itsBunch->
destroy(localNum, 0,
true);
172 msg <<
"Particles have been transferred to the full-wave solver." <<
endl;
178 for (
unsigned int i = 0; i < undulators.size(); i++) {
179 undulators[i].show();
181 for (
unsigned int i = 0; i < externalFields.size(); i++) {
182 externalFields[i].show();
186 timeval simulationStart;
187 gettimeofday(&simulationStart,
nullptr);
191 timeval simulationEnd;
192 gettimeofday(&simulationEnd,
nullptr);
193 double deltaTime = (simulationEnd.tv_usec - simulationStart.tv_usec) *
Units::us2s;
194 deltaTime += (simulationEnd.tv_sec - simulationStart.tv_sec);
195 msg <<
"::: Total full wave simulation time [seconds] = " << deltaTime <<
endl;
200 for (
auto iter = solver.chargeVectorn_.begin(); iter != solver.chargeVectorn_.end(); iter++) {
201 zMin =
std::min(zMin, iter->rnp[2]);
203 allreduce(&zMin, 1, std::less<double>());
205 const double gammaBeta = solver.gamma_ * solver.beta_;
206 const double factor = gammaBeta * solver.c0_ * (solver.timeBunch_ + solver.dt_) + lFringe;
207 for (
auto iter = solver.chargeVectorn_.begin(); iter != solver.chargeVectorn_.end(); iter++) {
208 double dist = zMin - iter->rnp[2];
210 iter->rnp[2] = solver.gamma_ * iter->rnp[2] + factor;
212 solver.gamma_ * iter->gbnp[2] + gammaBeta *
std::sqrt(1 + iter->gbnp.norm2());
214 double gammaParticle =
std::sqrt(1 + iter->gbnp.norm2());
215 iter->rnp[0] += iter->gbnp[0] / gammaParticle * dist * gammaBeta;
216 iter->rnp[1] += iter->gbnp[1] / gammaParticle * dist * gammaBeta;
217 iter->rnp[2] += iter->gbnp[2] / gammaParticle * dist * gammaBeta;
222 solver.gamma_ * (solver.time_ + solver.beta_ / solver.c0_ * (zMin - bunch.zu_));
225 msg <<
"Transferring particles back to OPAL bunch." <<
endl;
226 itsBunch->
create(solver.chargeVectorn_.size());
227 const double dt = itsBunch->
getdT();
228 const unsigned int newLocalNum = itsBunch->
getLocalNum();
230 for (
unsigned int i = 0; i < newLocalNum; ++i) {
231 for (
unsigned int d = 0; d < 3; ++d) {
232 itsBunch->
R[i][d] = iter->rnp[d];
233 itsBunch->
P[i][d] = iter->gbnp[d];
236 itsBunch->
dt[i] = dt;
239 itsBunch->
setT(itsBunch->
getT() + mesh.totalTime_);
243 for (
unsigned int i = 0; i < newLocalNum; ++i) {
244 itsBunch->
R[i] = localToRefCSTrafo.
transformTo(itsBunch->
R[i]);
245 itsBunch->
P[i] = localToRefCSTrafo.
rotateTo(itsBunch->
P[i]);
254 msg <<
"Bunch after undulator in reference coordinate system: " <<
endl;
255 itsBunch->
print(msg);
double getTotalTime() const
unsigned int numPeriods_m
Number of periods.
Tps< T > sqrt(const Tps< T > &x)
Square root.
virtual bool bends() const
int seed
The current random seed.
std::vector< double > meshLength_m
Size of computational domain.
void setAngle(double theta)
bool getHasBeenSimulated() const
void setFilename(const std::string &fname)
double dtBunch_m
Time step for the bunch position update.
const std::string & getFilename() const
virtual void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField)
void setDtBunch(double dtb)
CoordinateSystemTrafo inverted() const
ParticleAttrib< Vector_t > P
void setTruncationOrder(unsigned int trunOrder)
bool hasBeenSimulated_m
Boolean to indicate whether this undulator has already been simulated.
void destroy(size_t M, size_t I, bool doNow=false)
Inform & print(Inform &os)
Vector_t get_centroid() const
Vector_t get_pmean() const
void calcBeamParameters()
void setMeshResolution(const std::vector< double > &mr)
PartBunchBase< double, 3 > * RefPartBunch_m
std::vector< double > getMeshLength() const
void setNumPeriods(unsigned int np)
double totalTime_m
Total time to run undulator.
Inform & endl(Inform &inf)
virtual void accept(BeamlineVisitor &) const
Apply visitor to Undulator.
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
std::string fname_m
Mithra file with output information.
void setLambda(double lambda)
CoordinateSystemTrafo toLabTrafo_m
virtual ElementType getType() const
Get element type std::string.
unsigned int getTruncationOrder() const
virtual void getDimensions(double &zBegin, double &zEnd) const
std::string::iterator iterator
std::vector< double > meshResolution_m
Mesh dx, dy, dz.
T euclidean_norm(const Vector< T > &)
Euclidean norm.
void apply(PartBunchBase< double, 3 > *itsBunch, CoordinateSystemTrafo const &refToLocalCSTrafo)
size_t getTotalNum() const
Vector_t rotateTo(const Vector_t &r) const
size_t getLocalNum() const
void allreduce(const T *input, T *output, int count, Op op)
double lambda_m
Undulator period.
double getDtBunch() const
ParticleAttrib< double > Q
void setTotalTime(double tt)
constexpr double q_e
The elementary charge in As.
Vector_t transformTo(const Vector_t &r) const
std::vector< double > getMeshResolution() const
ParticleAttrib< double > dt
double getChargePerParticle() const
get the macro particle charge
unsigned int getNumPeriods() const
void setMeshLength(const std::vector< double > &ml)
double angle_m
Polarisation angle of the undulator field.
double k_m
The undulator parameter.
Interface for a single beam element.
Vector_t get_maxExtent() const
unsigned int truncationOrder_m
First or second order absorbing boundary conditions.
void setHasBeenSimulated(bool hbs)