/* 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 "math.h"
#include "gsl/gsl_sf_gamma.h"
#include "gsl/gsl_sf_pow_int.h"
#include "Utils/Squeak.hh"
#include "src/common_cpp/FieldTools/DerivativesSolenoid.hh"
namespace MAUS {
DerivativesSolenoid::DerivativesSolenoid(double peak_field, double r_max,
double z_max, int highest_order,
EndFieldModel* end_field)
: BTField(-r_max, -r_max, -z_max, +r_max, +r_max, +z_max),
_peak_field(peak_field), _r_max(r_max), _z_max(z_max),
_highest_order(highest_order), _end_field(end_field) {
}
DerivativesSolenoid::~DerivativesSolenoid() {
if (_end_field != NULL) {
delete _end_field;
}
}
DerivativesSolenoid* DerivativesSolenoid::Clone() const {
return new DerivativesSolenoid(*this);
}
DerivativesSolenoid::DerivativesSolenoid(const DerivativesSolenoid& rhs)
: _end_field(NULL) { // make _end_field NULL to avoid deletion on assignment
*this = rhs;
}
DerivativesSolenoid& DerivativesSolenoid::operator=
(const DerivativesSolenoid& rhs) {
if (this == &rhs) {
return *this;
}
_peak_field = rhs._peak_field;
_r_max = rhs._r_max;
_z_max = rhs._z_max;
_highest_order = rhs._highest_order;
if (_end_field != NULL) {
delete _end_field;
}
if (rhs._end_field != NULL) {
_end_field = rhs._end_field->Clone();
} else {
_end_field = NULL;
}
double bb[] = {-_r_max, -_r_max, -_z_max, _r_max, _r_max, _z_max};
BTField::bbMin = std::vector(&bb[0], &bb[3]);
BTField::bbMax = std::vector(&bb[3], &bb[6]);
return *this;
}
DerivativesSolenoid::DerivativesSolenoid()
: _peak_field(0), _r_max(0), _z_max(0), _highest_order(0),
_end_field(NULL) {
}
void DerivativesSolenoid::
GetFieldValue(const double Point[4], double *Bfield) const {
if (fabs(Point[2]) > _z_max) return;
double r = sqrt(Point[0]*Point[0]+Point[1]*Point[1]);
if (r > _r_max) return;
double Br = 0;
int n = 0;
while (n < _highest_order) {
double n_fact = static_cast(gsl_sf_fact(n));
double deltaBr = -pow(-1, n)*pow(r/2., 2*n+1)*
BzDifferential(Point[2], 2*n+1)
/n_fact/static_cast(gsl_sf_fact(n+1));
double deltaBz = pow(-1, n)*pow(r/2., 2*n)*
BzDifferential(Point[2], 2*n)/n_fact/n_fact;
Bfield[2] += deltaBz;
Br += deltaBr;
n++;
}
Br *= _peak_field;
Bfield[2] *= _peak_field;
if (r > 0.) {
Bfield[0] = Br*Point[0]/r;
Bfield[1] = Br*Point[1]/r;
}
}
void DerivativesSolenoid::Print(std::ostream &out) const {
out << "DerivativesSolenoid PeakField: " << _peak_field
<< " Order: " << _highest_order << " ";
_end_field->Print(out);
this->BTField::Print(out);
}
const EndFieldModel* DerivativesSolenoid::GetEndFieldModel() const {
return _end_field;
}
double DerivativesSolenoid::GetPeakField() const {
return _peak_field;
}
double DerivativesSolenoid::GetRMax() const {
return _r_max;
}
double DerivativesSolenoid::GetZMax() const {
return _z_max;
}
int DerivativesSolenoid::GetHighestOrder() const {
return _highest_order;
}
/*
THIS ALL LOOKS OKAY - BUT NOT TESTED
void DerivativesSolenoid::GetVectorPotential(const double point[4],
double * potential) const
{
if (fabs(point[2]) > _z_max) return;
double r2 = point[0]*point[0]+point[1]*point[1];
if (r2 > _r_max*_r_max) return;
double deltaPot = 0.;
for (int n = 0; n < _highest_order; n++) {
deltaPot += pow(-r2/4., n)*BzDifferential(point[2], 2*n)
/double(gsl_sf_fact(n))/double(gsl_sf_fact(n))/2./double(n+1.);
}
potential[0] = point[1]*deltaPot;
potential[1] = -point[0]*deltaPot;
}
void DerivativesSolenoid::GetVectorPotentialDifferential
(const double point[4], double * diff, int axis) const
{
if (fabs(point[2]) > _z_max) return;
double r2 = point[0]*point[0]+point[1]*point[1];
double deltapot1 = 0.;
double deltapot2 = 0.;
switch (axis)
{
case 0:
for (int n = 0; n < _highest_order; n++) {
double b2n = BzDifferential(point[2], 2*n);
double nfact = gsl_sf_fact(n);
if (n > 0) {
deltapot1 += b2n/8./(n+1.)/double(nfact*nfact)*pow(-r2/4., n-1)*n;
}
deltapot2 += b2n/2./(n+1.)/double(nfact*nfact)*pow(-r2/4., n); //ok
}
diff[0] = -2.*point[0]*point[1]*deltapot1; //dAx/dx
diff[1] = +2.*point[0]*point[0]*deltapot1 - deltapot2; //dAy/dx
break;
case 1:
for (int n = 0; n < _highest_order; n++) {
double b2n = BzDifferential(point[2], 2*n);
double nfact = gsl_sf_fact(n);
if (n > 0) {
deltapot1 += b2n/8./(n+1.)/double(nfact*nfact)*pow(-r2/4., n-1)*n;
}
deltapot2 += b2n/2./(n+1.)/double(nfact*nfact)*pow(-r2/4., n); //ok
}
diff[0] = -2.*point[1]*point[1]*deltapot1 + deltapot2; //dAx/dy
diff[1] = +2.*point[0]*point[1]*deltapot1; //dAy/dy
break;
case 2:
for(int n=0; n<_highest_order; n++) {
deltapot1 += pow(-r2/4., n)*BzDifferential(point[2], 2*n+1)
/double(pow(gsl_sf_fact(n), 2))/2./double(n+1.);
}
diff[0] = deltapot1 * point[1]; //dAx/dz
diff[1] = -deltapot1 * point[0]; //dAy/dz
break;
default:
break;
}
}
*/
}