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