50#define QSS_MAX_SUBSTEPS 1000
58 G4int numberOfVariables = 6,
90 G4int numberOfVariables = 6,
94 G4int numberOfVariables = 6,
107 G4int numberOfVariables = 6,
110 void initialize_data_structs();
113 inline void update_field();
116 inline void realloc_substeps();
120 inline void recompute_derivatives(
int index);
121 inline void update_time();
123 inline G4double get_coeff() {
return fCoeff_local; }
125 inline void set_coeff(
G4double coeff) { fCoeff_local =
coeff; }
129 f_charge_c2 = q * cLight_local * cLight_local;
132 inline G4double get_qc2() {
return f_charge_c2; }
134 inline void set_mg() { fMassGamma = f_mass * fGamma2; }
136 inline void set_gamma2(
G4double gamma2) { fGamma2 = gamma2; }
137 inline void set_velocity(
G4double v) { fVelocity = v; }
139 inline void velocity_to_momentum(
G4double* state);
141 inline void set_gamma(
G4double p_sq)
143 set_gamma2(std::sqrt(p_sq / (f_mass * f_mass) + 1));
145 set_coeff(get_qc2() / fMassGamma);
159 static constexpr G4double cLight_local = 299.792458;
174 simulator(qss->getSimulator()),
178 fLastStepLength = -1.0;
187 this->initialize_data_structs();
188 this->SetPrecision(1e-4, 1e-7);
194 for (
auto & i : simulator->SD) {
free(i); }
197 free(this->simulator);
208 Stepper(yInput, dydx, hstep, yOutput, yError);
214 auto*
const sim = this->simulator;
216 sim->time = sim->nextStateTime[0];
219 if (sim->nextStateTime[1] < sim->time) {
220 sim->time = sim->nextStateTime[1];
223 if (sim->nextStateTime[2] < sim->time) {
224 sim->time = sim->nextStateTime[2];
227 if (sim->nextStateTime[3] < sim->time) {
228 sim->time = sim->nextStateTime[3];
231 if (sim->nextStateTime[4] < sim->time) {
232 sim->time = sim->nextStateTime[4];
235 if (sim->nextStateTime[5] < sim->time) {
236 sim->time = sim->nextStateTime[5];
253 const G4int coeffs = method->order() + 1;
260 G4int** SD = simulator->SD;
265 this->save_substep(0, length);
269 index = simulator->minIndex;
272 cf0 = index * coeffs;
273 elapsed = t - tx[index];
274 method->advance_time_x(cf0, elapsed);
276 lqu[index] = dQRel[index] * std::fabs(x[cf0]);
277 if (lqu[index] < dQMin[index]) {
278 lqu[index] = dQMin[index];
280 method->update_quantized_state(index);
282 method->next_time(index, t);
283 for (
G4int i = 0; i < 3; i++) {
284 G4int j = SD[index][i];
288 x[infCf0] = method->evaluate_x_poly(infCf0, elapsed, x);
293 this->update_field();
294 this->recompute_derivatives(index);
295 method->recompute_next_times(SD[index], t);
298 length += fVelocity * (t - prev_time);
299 if (length <= max_length) { this->save_substep(t, length); }
306 index = simulator->minIndex;
314 t = substep->start_time + (max_length - substep->len) / fVelocity;
316 this->get_state_from_poly(substep->x, substep->tx, t, yOut);
318 velocity_to_momentum(yOut);
320 const G4int numberOfVariables = GetNumberOfVariables();
321 for (
G4int i = 0; i < numberOfVariables; ++i) {
327 fLastStepLength = max_length;
346 G4double length = tau * fLastStepLength;
353 while (idx < k && i < j - 1) {
356 }
else if (length >=
SUBSTEP_LEN(simulator, idx + 1)) {
366 for (; idx < j && length >=
SUBSTEP_LEN(simulator, idx + 1); idx++) {;}
370 end_time = substep->start_time + (length - substep->len) / fVelocity;
372 this->get_state_from_poly(substep->x, substep->tx, end_time, yOut);
374 velocity_to_momentum(yOut);
392 set_gamma(momentum.
mag2());
393 G4double c_mg = cLight_local / fMassGamma;
394 set_velocity(momentum.
mag() * c_mg);
396 method->reset_state(PXidx, pos.getX());
397 method->reset_state(PYidx, pos.getY());
398 method->reset_state(PZidx, pos.getZ());
400 method->reset_state(VXidx, momentum.
getX() * c_mg);
401 method->reset_state(VYidx, momentum.
getY() * c_mg);
402 method->reset_state(VZidx, momentum.
getZ() * c_mg);
404 this->update_field();
405 method->full_definition(get_coeff());
407 method->recompute_all_state_times(0);
417 G4int n_vars = simulator->states;
419 if (dq_min <= 0) { dq_min = dq_rel * 1e-3; }
421 for (
G4int i = 0; i < n_vars; ++i) {
430 auto sim = this->simulator;
437 sim->SD[i] = (
G4int*)malloc(3 *
sizeof(
G4int));
440 sim->SD[0][states[0]++] = 3;
441 sim->SD[0][states[0]++] = 4;
442 sim->SD[0][states[0]++] = 5;
444 sim->SD[1][states[1]++] = 3;
445 sim->SD[1][states[1]++] = 4;
446 sim->SD[1][states[1]++] = 5;
448 sim->SD[2][states[2]++] = 3;
449 sim->SD[2][states[2]++] = 4;
450 sim->SD[2][states[2]++] = 5;
452 sim->SD[3][states[3]++] = 0;
453 sim->SD[3][states[3]++] = 4;
454 sim->SD[3][states[3]++] = 5;
456 sim->SD[4][states[4]++] = 1;
457 sim->SD[4][states[4]++] = 3;
458 sim->SD[4][states[4]++] = 5;
460 sim->SD[5][states[5]++] = 2;
461 sim->SD[5][states[5]++] = 3;
462 sim->SD[5][states[5]++] = 4;
479 const G4int coeffs = method->order() + 1;
483 e = simulator->time - simulator->tq[0];
484 if (
likely(e > 0)) { method->advance_time_q(idx, e); }
485 simulator->tq[0] = simulator->time;
488 e = simulator->time - simulator->tq[1];
489 if (
likely(e > 0)) { method->advance_time_q(idx, e); }
490 simulator->tq[1] = simulator->time;
493 e = simulator->time - simulator->tq[2];
494 if (
likely(e > 0)) { method->advance_time_q(idx, e); }
495 simulator->tq[2] = simulator->time;
498 e = simulator->time - simulator->tq[3];
499 if (
likely(e > 0)) { method->advance_time_q(idx, e); }
500 simulator->tq[3] = simulator->time;
503 e = simulator->time - simulator->tq[4];
504 if (
likely(e > 0)) { method->advance_time_q(idx, e); }
505 simulator->tq[4] = simulator->time;
508 e = simulator->time - simulator->tq[5];
509 if (
likely(e > 0)) { method->advance_time_q(idx, e); }
510 simulator->tq[5] = simulator->time;
512 method->dependencies(index, get_coeff());
522 const G4int order1 = method->order() + 1;
523 G4double*
const _field = simulator->alg;
524 G4double*
const _point = _field + order1;
530 this->GetEquationOfMotion()->GetFieldValue(_point, _field);
544 this->realloc_substeps();
551 const G4int prev_index =
MAX_SUBSTEP(simulator), new_index = 2 * prev_index;
562 unsigned int coeff_index = 0, i;
563 const unsigned int x_order = method->order(), x_order1 = x_order + 1;
566 assert(tx[i] <= time);
567 state[i] = method->evaluate_x_poly(coeff_index, time - tx[i], x);
568 coeff_index += x_order1;
struct QSS_simulator_ * QSS_simulator
struct QSSSubstep_ * QSSSubstep
#define LAST_SUBSTEP(sim)
#define SUBSTEP_STRUCT(sim, i)
#define SUBSTEP_LEN(sim, i)
#define LAST_SUBSTEP_STRUCT(sim)
#define CUR_SUBSTEP_X(sim)
#define CUR_SUBSTEP_LEN(sim)
#define CUR_SUBSTEP_START(sim)
G4double GetCharge() const
G4ThreeVector GetPosition() const
G4double GetRestMass() const
G4ThreeVector GetMomentum() const
static G4double Distline(const G4ThreeVector &OtherPnt, const G4ThreeVector &LinePntA, const G4ThreeVector &LinePntB)
G4EquationOfMotion * GetEquationOfMotion()
void Interpolate(G4double tau, G4double yOut[])
void SetupInterpolation()
static G4QSStepper< G4QSS2 > * build_QSS2(G4EquationOfMotion *EqRhs, G4int numberOfVariables=6, G4bool primary=true)
static G4QSStepper< G4QSS3 > * build_QSS3(G4EquationOfMotion *EqRhs, G4int numberOfVariables=6, G4bool primary=true)
G4QSStepper(G4EquationOfMotion *EqRhs, G4int numberOfVariables=6, G4bool primary=true)
G4double DistChord() const override
const field_utils::State & GetYOut() const
void Stepper(const G4double y[], const G4double dydx[], G4double h, G4double yout[], G4double yerr[]) override
G4double GetLastStepLength()
G4EquationOfMotion * GetSpecificEquation()
void reset(const G4FieldTrack *track)
G4int IntegratorOrder() const override
void SetPrecision(G4double dq_rel, G4double dq_min)
constexpr unsigned int PZidx
constexpr unsigned int PYidx
constexpr unsigned int VZidx
constexpr unsigned int VXidx
constexpr unsigned int VAR_IDX_END
constexpr unsigned int MIN_SUBSTEPS
constexpr unsigned int PXidx
constexpr unsigned int MAX_QSS_STEPPER_ORDER
constexpr unsigned int VYidx
G4double[G4FieldTrack::ncompSVEC] State