/* 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 "gtest/gtest.h"
#include "src/common_cpp/FieldTools/DerivativesSolenoid.hh"
namespace MAUS {
EndFieldModel* test_end_field() {
return new BTMultipole::TanhEndField(1., 0.1, 3);
}
TEST(DerivativesSolenoidTest, TestConstructorDestructor) {
DerivativesSolenoid sol_default;
EXPECT_EQ(sol_default.GetPeakField(), 0.);
EXPECT_EQ(sol_default.GetRMax(), 0.);
EXPECT_EQ(sol_default.GetZMax(), 0.);
EXPECT_EQ(sol_default.GetHighestOrder(), 0);
EXPECT_EQ
(sol_default.GetEndFieldModel(), static_cast(NULL));
DerivativesSolenoid sol_null(2., 10., 11., 3, NULL);
EXPECT_EQ(sol_null.GetPeakField(), 2.);
EXPECT_EQ(sol_null.GetRMax(), 10.);
EXPECT_EQ(sol_null.GetZMax(), 11.);
EXPECT_EQ(sol_null.GetHighestOrder(), 3);
EXPECT_EQ(sol_null.GetEndFieldModel(), static_cast(NULL));
EndFieldModel* end = test_end_field();
DerivativesSolenoid sol_value(2., 10., 11., 3, end);
EXPECT_EQ(sol_value.GetPeakField(), 2.);
EXPECT_EQ(sol_value.GetRMax(), 10.);
EXPECT_EQ(sol_value.GetZMax(), 11.);
EXPECT_EQ(sol_value.GetHighestOrder(), 3);
EXPECT_EQ(sol_value.GetEndFieldModel(), end);
EXPECT_EQ(sol_value.BoundingBoxMin()[0], -10.);
EXPECT_EQ(sol_value.BoundingBoxMin()[1], -10.);
EXPECT_EQ(sol_value.BoundingBoxMin()[2], -11.);
EXPECT_EQ(sol_value.BoundingBoxMax()[0], +10.);
EXPECT_EQ(sol_value.BoundingBoxMax()[1], +10.);
EXPECT_EQ(sol_value.BoundingBoxMax()[2], +11.);
}
// all
TEST(DerivativesSolenoidTest, TestNullCopyConstructorCloneEquality) {
DerivativesSolenoid sol_null;
DerivativesSolenoid sol_null_copy(sol_null);
EXPECT_EQ(sol_null.GetPeakField(), sol_null_copy.GetPeakField());
EXPECT_EQ(sol_null.GetRMax(), sol_null_copy.GetRMax());
EXPECT_EQ(sol_null.GetZMax(), sol_null_copy.GetZMax());
EXPECT_EQ(sol_null.GetHighestOrder(), sol_null_copy.GetHighestOrder());
EXPECT_EQ(sol_null.GetEndFieldModel(), sol_null_copy.GetEndFieldModel());
DerivativesSolenoid sol_null_equ; // force gcc not to use copy ctor
EXPECT_EQ(sol_null_equ.GetHighestOrder(), 0);
sol_null_equ = sol_null;
EXPECT_EQ(sol_null.GetPeakField(), sol_null_equ.GetPeakField());
EXPECT_EQ(sol_null.GetRMax(), sol_null_equ.GetRMax());
EXPECT_EQ(sol_null.GetZMax(), sol_null_equ.GetZMax());
EXPECT_EQ(sol_null.GetHighestOrder(), sol_null_equ.GetHighestOrder());
EXPECT_EQ(sol_null.GetEndFieldModel(), sol_null_equ.GetEndFieldModel());
DerivativesSolenoid& sol_null_clone = *sol_null.Clone();
EXPECT_EQ(sol_null.GetPeakField(), sol_null_clone.GetPeakField());
EXPECT_EQ(sol_null.GetRMax(), sol_null_clone.GetRMax());
EXPECT_EQ(sol_null.GetZMax(), sol_null_clone.GetZMax());
EXPECT_EQ(sol_null.GetHighestOrder(), sol_null_clone.GetHighestOrder());
EXPECT_EQ(sol_null.GetEndFieldModel(), sol_null_clone.GetEndFieldModel());
}
// In all these checks, I only check that copying end_field produces something,
// never check that it is right
TEST(DerivativesSolenoidTest, TestCopyConstructorCloneEquality) {
EndFieldModel* end = test_end_field();
DerivativesSolenoid sol(2., 10., 11., 3, end);
DerivativesSolenoid sol_copy(sol);
EXPECT_EQ(sol.GetPeakField(), sol_copy.GetPeakField());
EXPECT_EQ(sol.GetRMax(), sol_copy.GetRMax());
EXPECT_EQ(sol.GetZMax(), sol_copy.GetZMax());
EXPECT_EQ(sol.GetHighestOrder(), sol_copy.GetHighestOrder());
EXPECT_NE(sol.GetEndFieldModel(), sol_copy.GetEndFieldModel());
EXPECT_NE(sol_copy.GetEndFieldModel(), static_cast(NULL));
DerivativesSolenoid sol_equ; // force gcc not to use copy ctor
EXPECT_EQ(sol_equ.GetHighestOrder(), 0);
sol_equ = sol;
EXPECT_EQ(sol.GetPeakField(), sol_equ.GetPeakField());
EXPECT_EQ(sol.GetRMax(), sol_equ.GetRMax());
EXPECT_EQ(sol.GetZMax(), sol_equ.GetZMax());
EXPECT_EQ(sol.GetHighestOrder(), sol_equ.GetHighestOrder());
EXPECT_NE(sol.GetEndFieldModel(), sol_equ.GetEndFieldModel());
EXPECT_NE(sol_equ.GetEndFieldModel(), static_cast(NULL));
DerivativesSolenoid& sol_clone = *sol.Clone();
EXPECT_EQ(sol.GetPeakField(), sol_clone.GetPeakField());
EXPECT_EQ(sol.GetRMax(), sol_clone.GetRMax());
EXPECT_EQ(sol.GetZMax(), sol_clone.GetZMax());
EXPECT_EQ(sol.GetHighestOrder(), sol_clone.GetHighestOrder());
EXPECT_NE(sol.GetEndFieldModel(), sol_clone.GetEndFieldModel());
EXPECT_NE(sol_clone.GetEndFieldModel(), static_cast(NULL));
EXPECT_EQ(sol_clone.BoundingBoxMin()[0], -10.);
EXPECT_EQ(sol_clone.BoundingBoxMin()[1], -10.);
EXPECT_EQ(sol_clone.BoundingBoxMin()[2], -11.);
EXPECT_EQ(sol_clone.BoundingBoxMax()[0], +10.);
EXPECT_EQ(sol_clone.BoundingBoxMax()[1], +10.);
EXPECT_EQ(sol_clone.BoundingBoxMax()[2], +11.);
}
std::vector test_get_field_value
(DerivativesSolenoid& sol, double x, double y, double z) {
double point[4] = {x, y, z, 0};
std::vector field(6);
for (size_t i = 0; i < 6; ++i) {
field[i] = 0.;
}
sol.GetFieldValue(point, &field[0]);
return field;
}
TEST(DerivativesSolenoidTest, TestBoundingBox) {
EndFieldModel* end = test_end_field();
DerivativesSolenoid sol(2., 2., 1., 3, end);
// centre
EXPECT_NEAR(test_get_field_value(sol, 0., 0., 0.)[2], 2., 1e-6);
// in bounding box
EXPECT_GT(test_get_field_value(sol, 2.-1e-9, 0., 1.-1e-9)[2], 1e-3);
EXPECT_GT(test_get_field_value(sol, 2.-1e-9, 0., 1.-1e-9)[0], 1e-3);
// out of bounding box
EXPECT_NEAR(test_get_field_value(sol, 2.-1e-9, 0., 1.+1e-9)[0], 0., 1e-12);
EXPECT_NEAR(test_get_field_value(sol, 2.-1e-9, 0., 1.+1e-9)[2], 0., 1e-12);
// out of bounding box
EXPECT_NEAR(test_get_field_value(sol, 2.+1e-9, 0., 1.-1e-9)[0], 0., 1e-12);
EXPECT_NEAR(test_get_field_value(sol, 2.+1e-9, 0., 1.-1e-9)[2], 0., 1e-12);
}
TEST(DerivativesSolenoidTest, TestFieldOnAxis) {
EndFieldModel* end = test_end_field();
DerivativesSolenoid sol(2., 2., 10., 3, end);
for (double z = -10.; z < 10.; z+= 0.1)
EXPECT_NEAR(
test_get_field_value(sol, 0., 0., z)[2], end->Function(z, 0)*2., 1e-9);
}
TEST(DerivativesSolenoidTest, TestFieldMaxwellianness) {
EndFieldModel* end = test_end_field();
DerivativesSolenoid sol(2., 1.e9, 1.e9, 3, end);
double dr = 0.001;
double z = 1.;
for (double r = 0.; r < 0.1; r+= dr) {
double dbxdx = (test_get_field_value(sol, r+dr/2., 0., z)[0]
-test_get_field_value(sol, r-dr/2., 0., z)[0]);
double dbydy = (test_get_field_value(sol, r, +dr/2., z)[1]
-test_get_field_value(sol, r, -dr/2., z)[1]);
double dbzdz = (test_get_field_value(sol, r, 0., z+dr/2.)[2]
-test_get_field_value(sol, r, 0., z-dr/2.)[2]);
double div_b = dbxdx+dbydy+dbzdz;
double sum_delta_b = fabs(dbxdx)+fabs(dbydy)+fabs(dbzdz);
// std::cerr << r << " ** " << dbxdx << " " << dbydy << " " << dbzdz
// << " ** " << div_b << std::endl;
EXPECT_LT(fabs(div_b), 1e-4*sum_delta_b);
}
}
}