/* This file is part of MAUS: http://micewww.pp.rl.ac.uk/projects/maus
*
* MAUS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MAUS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MAUS. If not, see .
*
*/
#include
#include
#include
#include "gsl/gsl_odeiv.h"
#include "gsl/gsl_errno.h"
#include "src/legacy/BeamTools/BTFieldConstructor.hh"
#include "src/common_cpp/Utils/Globals.hh"
#include "src/common_cpp/FieldTools/BetaEvolver.hh"
namespace MAUS {
BTFieldConstructor* BetaEvolver::_field = NULL;
double BetaEvolver::_p = 200.;
int BetaEvolver::_maxNSteps = 10000;
double BetaEvolver::_absoluteError = 1e-3;
double BetaEvolver::_relativeError = 1e-3;
bool BetaEvolver::check_step_4_names() {
_field = Globals::GetMCFieldConstructor();
BTFieldGroup* mag_field = static_cast(_field->GetMagneticField());
std::string names[] = {
"EndCoil2_US",
"CenterCoil_US",
"EndCoil1_US",
"MatchCoil2_US",
"MatchCoil1_US",
"FocusCoil_US",
"FocusCoil_DS",
"MatchCoil1_DS",
"MatchCoil2_DS",
"EndCoil1_DS",
"CenterCoil_DS",
"EndCoil2_DS",
};
if (mag_field->GetFields().size() != 12)
throw(Exceptions::Exception(Exceptions::recoverable,
"Failed to find the correct number of fields",
"BetaEvolver::rescale_step_4_lattice"));
for (size_t i = 0; i < 12; ++i) {
std::string a_name = mag_field->GetFields()[i]->GetName();
if (a_name != names[i])
throw(Exceptions::Exception(Exceptions::recoverable,
"Field name mismatch; expected "+names[i]+" but found "+a_name,
"BetaEvolver::rescale_step_4_lattice"));
}
return true;
}
void BetaEvolver::rescale_step_4_lattice(double e2_us, double cc_us, double e1_us,
double m2_us, double m1_us, double fc_us,
double fc_ds, double m1_ds, double m2_ds,
double e1_ds, double cc_ds, double e2_ds) {
_field = Globals::GetMCFieldConstructor();
BTFieldGroup* mag_field = static_cast(_field->GetMagneticField());
mag_field->SetScaleFactor(0, e2_us);
mag_field->SetScaleFactor(1, cc_us);
mag_field->SetScaleFactor(2, e1_us);
mag_field->SetScaleFactor(3, m2_us);
mag_field->SetScaleFactor(4, m1_us);
mag_field->SetScaleFactor(5, fc_us);
mag_field->SetScaleFactor(6, fc_ds);
mag_field->SetScaleFactor(7, m1_ds);
mag_field->SetScaleFactor(8, m2_ds);
mag_field->SetScaleFactor(9, e1_ds);
mag_field->SetScaleFactor(10, cc_ds);
mag_field->SetScaleFactor(11, e2_ds);
}
std::vector BetaEvolver::integrate(double target_z, double z_in,
double beta_0, double alpha_0,
double p, double step_size) {
_field = Globals::GetMCFieldConstructor();
_p = p;
const gsl_odeiv_step_type * T = gsl_odeiv_step_rk4;
gsl_odeiv_step * step = gsl_odeiv_step_alloc(T, 3);
gsl_odeiv_control * control = gsl_odeiv_control_y_new(_absoluteError, _relativeError);
gsl_odeiv_evolve * evolve = gsl_odeiv_evolve_alloc(3);
// Probably not the most efficient, but only does it once per integrate call
_absoluteError = (*MAUS::Globals::GetInstance()->GetConfigurationCards())
["field_tracker_absolute_error"].asDouble();
_relativeError = (*MAUS::Globals::GetInstance()->GetConfigurationCards())
["field_tracker_relative_error"].asDouble();
double z = z_in;
gsl_odeiv_system system = {z_beta_differential_equation, NULL, 3, NULL};
double h = step_size;
int nsteps = 0;
double b[] = {beta_0, alpha_0, 0.};
while (fabs(z-target_z) > 1e-6) {
nsteps++;
int status = gsl_odeiv_evolve_apply(evolve, control, step, &system, &z, target_z, &h, b);
if (status != GSL_SUCCESS) {
throw(Exceptions::Exception(Exceptions::recoverable,
"Failed during tracking",
"BTTracker::integrate") );
break;
}
if (nsteps > _maxNSteps) {
std::stringstream ios;
ios << "Killing beta with step size " << h << " at step " << nsteps
<< " of " << _maxNSteps << "\n"
<< "b: " << b[0] << " b': " << b[1] << std::endl;
throw(Exceptions::Exception(Exceptions::recoverable, ios.str()+
" Exceeded maximum number of steps\n", "BetaEvolver::integrate") );
break;
}
}
gsl_odeiv_evolve_free(evolve);
gsl_odeiv_control_free(control);
gsl_odeiv_step_free(step);
std::vector beta_out(2, 0);
beta_out[0] = b[0]; // beta
beta_out[1] = b[1]; // beta prime
beta_out[2] = b[2]; // phi
return beta_out;
}
int BetaEvolver::z_beta_differential_equation(double z, const double b[2],
double dbdz[2], void* params) {
double field[6] = {0., 0., 0., 0., 0., 0.};
double xfield[4] = {0., 0., z, 0.};
_field->GetFieldValue(xfield, field);
double kappa = field[2]/2./_p*300.;
// beta'
dbdz[0] = b[1];
// beta''
dbdz[1] = (b[1]*b[1]-4*b[0]*b[0]*kappa*kappa+4)/2/b[0];
dbdz[2] = 1./b[0];
return GSL_SUCCESS;
}
}