Project
Loading...
Searching...
No Matches
testO2TPCPoissonSolver.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
16
17#define BOOST_TEST_MODULE Test TPC O2TPCSpaceCharge3DCalc class
18#define BOOST_TEST_MAIN
19#define BOOST_TEST_DYN_LINK
20#include <boost/test/unit_test.hpp>
25
26namespace o2
27{
28namespace tpc
29{
30
31using DataT = double; // using float actually takes alot longer than double (doesnt converge when using float)
32static constexpr DataT TOLERANCE = 3; // relative tolerance for 3D (maximum large error is at phi=90 since there the potential is 0!)
33static constexpr DataT TOLERANCE2D = 8.5; // relative tolerance for 2D TODO check why the difference between numerical and analyticial is larger than for 3D!
34static constexpr DataT ABSTOLERANCE = 0.01; // absolute tolerance is taken at small values near 0
35static constexpr unsigned short NR = 65; // grid in r
36static constexpr unsigned short NZ = 65; // grid in z
37static constexpr unsigned short NPHI = 180; // grid in phi
38static constexpr unsigned short NR2D = 129; // grid in r
39static constexpr unsigned short NZ2D = 129; // grid in z
40static constexpr unsigned short NPHI2D = 1; // grid in phi
41
44template <typename DataT>
45DataT getPhiVertex(const size_t indexPhi, const o2::tpc::RegularGrid3D<DataT>& grid)
46{
47 return grid.getPhiVertex(indexPhi);
48}
49
52template <typename DataT>
53DataT getRVertex(const size_t indexR, const o2::tpc::RegularGrid3D<DataT>& grid)
54{
55 return grid.getRVertex(indexR);
56}
57
60template <typename DataT>
61DataT getZVertex(const size_t indexZ, const o2::tpc::RegularGrid3D<DataT>& grid)
62{
63 return grid.getZVertex(indexZ);
64}
65
66template <typename DataT>
68{
69 for (size_t iPhi = 0; iPhi < density.getNPhi(); ++iPhi) {
70 const DataT phi = getPhiVertex<DataT>(iPhi, grid);
71 for (size_t iR = 0; iR < density.getNR(); ++iR) {
72 const DataT radius = getRVertex<DataT>(iR, grid);
73 for (size_t iZ = 0; iZ < density.getNZ(); ++iZ) {
74 const DataT z = getZVertex<DataT>(iZ, grid);
75 density(iZ, iR, iPhi) = formulas.evalDensity(z, radius, phi);
76 }
77 }
78 }
79}
80
81template <typename DataT>
83{
84 for (size_t iPhi = 0; iPhi < potential.getNPhi(); ++iPhi) {
85 const DataT phi = getPhiVertex<DataT>(iPhi, grid);
86 for (size_t iR = 0; iR < potential.getNR(); ++iR) {
87 const DataT radius = getRVertex<DataT>(iR, grid);
88 for (size_t iZ = 0; iZ < potential.getNZ(); ++iZ) {
89 const DataT z = getZVertex<DataT>(iZ, grid);
90 potential(iZ, iR, iPhi) = formulas.evalPotential(z, radius, phi);
91 }
92 }
93 }
94}
95
96template <typename DataT>
98{
99 for (size_t iPhi = 0; iPhi < potential.getNPhi(); ++iPhi) {
100 const DataT phi = getPhiVertex<DataT>(iPhi, grid);
101 for (size_t iZ = 0; iZ < potential.getNZ(); ++iZ) {
102 const DataT z = getZVertex<DataT>(iZ, grid);
103 const size_t iR = 0;
104 const DataT radius = getRVertex<DataT>(iR, grid);
105 potential(iZ, iR, iPhi) = formulas.evalPotential(z, radius, phi);
106 }
107 }
108
109 for (size_t iPhi = 0; iPhi < potential.getNPhi(); ++iPhi) {
110 const DataT phi = getPhiVertex<DataT>(iPhi, grid);
111 for (size_t iZ = 0; iZ < potential.getNZ(); ++iZ) {
112 const DataT z = getZVertex<DataT>(iZ, grid);
113 const size_t iR = potential.getNR() - 1;
114 const DataT radius = getRVertex<DataT>(iR, grid);
115 potential(iZ, iR, iPhi) = formulas.evalPotential(z, radius, phi);
116 }
117 }
118
119 for (size_t iPhi = 0; iPhi < potential.getNPhi(); ++iPhi) {
120 const DataT phi = getPhiVertex<DataT>(iPhi, grid);
121 for (size_t iR = 0; iR < potential.getNR(); ++iR) {
122 const DataT radius = getRVertex<DataT>(iR, grid);
123 const size_t iZ = 0;
124 const DataT z = getZVertex<DataT>(iZ, grid);
125 potential(iZ, iR, iPhi) = formulas.evalPotential(z, radius, phi);
126 }
127 }
128
129 for (size_t iPhi = 0; iPhi < potential.getNPhi(); ++iPhi) {
130 const DataT phi = getPhiVertex<DataT>(iPhi, grid);
131 for (size_t iR = 0; iR < potential.getNR(); ++iR) {
132 const DataT radius = getRVertex<DataT>(iR, grid);
133 const size_t iZ = potential.getNZ() - 1;
134 const DataT z = getZVertex<DataT>(iZ, grid);
135 potential(iZ, iR, iPhi) = formulas.evalPotential(z, radius, phi);
136 }
137 }
138}
139
140template <typename DataT>
142{
143 for (size_t iPhi = 0; iPhi < numerical.getNPhi(); ++iPhi) {
144 for (size_t iR = 0; iR < numerical.getNR(); ++iR) {
145 for (size_t iZ = 0; iZ < numerical.getNZ(); ++iZ) {
146 if (std::fabs(analytical(iZ, iR, iPhi)) < ABSTOLERANCE) {
147 BOOST_CHECK_SMALL(numerical(iZ, iR, iPhi) - analytical(iZ, iR, iPhi), ABSTOLERANCE);
148 } else {
149 BOOST_CHECK_CLOSE(numerical(iZ, iR, iPhi), analytical(iZ, iR, iPhi), TOLERANCE);
150 }
151 }
152 }
153 }
154}
155
156template <typename DataT>
158{
159 for (size_t iPhi = 0; iPhi < numerical.getNPhi(); ++iPhi) {
160 for (size_t iR = 0; iR < numerical.getNR(); ++iR) {
161 for (size_t iZ = 0; iZ < numerical.getNZ(); ++iZ) {
162 if (std::fabs(analytical(iZ, iR, iPhi)) < ABSTOLERANCE) {
163 BOOST_CHECK_SMALL(numerical(iZ, iR, iPhi) - analytical(iZ, iR, iPhi), ABSTOLERANCE);
164 } else {
165 BOOST_CHECK_CLOSE(numerical(iZ, iR, iPhi), analytical(iZ, iR, iPhi), TOLERANCE2D);
166 }
167 }
168 }
169 }
170}
171
172template <typename DataT>
174{
175 using GridProp = GridProperties<DataT>;
176 const ParamSpaceCharge params{NR, NZ, NPHI};
177 const o2::tpc::RegularGrid3D<DataT> grid3D{GridProp::ZMIN, GridProp::RMIN, GridProp::PHIMIN, GridProp::getGridSpacingZ(NZ), GridProp::getGridSpacingR(NR), GridProp::getGridSpacingPhi(NPHI), params};
178
179 using DataContainer = o2::tpc::DataContainer3D<DataT>;
180 DataContainer potentialNumerical(NZ, NR, NPHI);
181 DataContainer potentialAnalytical(NZ, NR, NPHI);
182 DataContainer charge(NZ, NR, NPHI);
183
184 const o2::tpc::AnalyticalFields<DataT> analyticalFields;
185 // set the boudnary and charge for numerical poisson solver
186 setChargeDensityFromFormula<DataT>(analyticalFields, grid3D, charge);
187 setPotentialBoundaryFromFormula<DataT>(analyticalFields, grid3D, potentialNumerical);
188
189 // set analytical potential
190 setPotentialFromFormula<DataT>(analyticalFields, grid3D, potentialAnalytical);
191
192 // calculate numerical potential
193 PoissonSolver<DataT> poissonSolver(grid3D);
194 const int symmetry = 0;
195 poissonSolver.poissonSolver3D(potentialNumerical, charge, symmetry);
196
197 // compare numerical with analytical solution of the potential
198 testAlmostEqualArray<DataT>(potentialAnalytical, potentialNumerical);
199}
200
201template <typename DataT>
203{
204 using GridProp = GridProperties<DataT>;
205 const ParamSpaceCharge params{NR2D, NZ2D, NPHI2D};
206 const o2::tpc::RegularGrid3D<DataT> grid3D{GridProp::ZMIN, GridProp::RMIN, GridProp::PHIMIN, GridProp::getGridSpacingZ(NZ2D), GridProp::getGridSpacingR(NR2D), GridProp::getGridSpacingPhi(NPHI2D), params};
207
208 using DataContainer = o2::tpc::DataContainer3D<DataT>;
209 DataContainer potentialNumerical(NZ2D, NR2D, NPHI2D);
210 DataContainer potentialAnalytical(NZ2D, NR2D, NPHI2D);
211 DataContainer charge(NZ2D, NR2D, NPHI2D);
212
213 // set the boudnary and charge for numerical poisson solver
214 const o2::tpc::AnalyticalFields<DataT> analyticalFields;
215 setChargeDensityFromFormula<DataT>(analyticalFields, grid3D, charge);
216 setPotentialBoundaryFromFormula<DataT>(analyticalFields, grid3D, potentialNumerical);
217
218 // set analytical potential
219 setPotentialFromFormula<DataT>(analyticalFields, grid3D, potentialAnalytical);
220
221 // calculate numerical potential
222 PoissonSolver<DataT> poissonSolver(grid3D);
223 poissonSolver.poissonSolver2D(potentialNumerical, charge);
224
225 // compare numerical with analytical solution of the potential
226 testAlmostEqualArray2D<DataT>(potentialAnalytical, potentialNumerical);
227}
228
229BOOST_AUTO_TEST_CASE(PoissonSolver3D_test)
230{
232 poissonSolver3D<DataT>();
233}
234
235BOOST_AUTO_TEST_CASE(PoissonSolver3D2D_test)
236{
237 o2::tpc::MGParameters::isFull3D = false; // 3D2D
238 poissonSolver3D<DataT>();
239}
240
241BOOST_AUTO_TEST_CASE(PoissonSolver2D_test)
242{
243 poissonSolver2D<DataT>();
244}
245
246} // namespace tpc
247} // namespace o2
This class provides a simple method to store values on a large 3-Dim grid with ROOT io functionality.
int16_t charge
Definition RawEventData.h:5
This class provides implementation of Poisson equation solver by MultiGrid Method Original version of...
This file provides all necesseray classes which are used during the calcution of the distortions and ...
DataT evalDensity(DataT z, DataT r, DataT phi) const
DataT evalPotential(DataT z, DataT r, DataT phi) const
void poissonSolver3D(DataContainer &matricesV, const DataContainer &matricesCharge, const int symmetry)
void poissonSolver2D(DataContainer &matricesV, const DataContainer &matricesCharge)
DataT getRVertex(const size_t vertexY) const
DataT getPhiVertex(const size_t vertexZ) const
DataT getZVertex(const size_t vertexX) const
GLenum const GLfloat * params
Definition glcorearb.h:272
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
BOOST_AUTO_TEST_CASE(ClusterHardware_test1)
void setChargeDensityFromFormula(const AnalyticalFields< DataT > &formulas, const o2::tpc::RegularGrid3D< DataT > &grid, o2::tpc::DataContainer3D< DataT > &density)
DataT getZVertex(const size_t indexZ, const o2::tpc::RegularGrid3D< DataT > &grid)
void testAlmostEqualArray(o2::tpc::DataContainer3D< DataT > &analytical, o2::tpc::DataContainer3D< DataT > &numerical)
DataT getRVertex(const size_t indexR, const o2::tpc::RegularGrid3D< DataT > &grid)
DataT getPhiVertex(const size_t indexPhi, const o2::tpc::RegularGrid3D< DataT > &grid)
void testAlmostEqualArray2D(o2::tpc::DataContainer3D< DataT > &analytical, o2::tpc::DataContainer3D< DataT > &numerical)
void setPotentialFromFormula(const AnalyticalFields< DataT > &formulas, const o2::tpc::RegularGrid3D< DataT > &grid, o2::tpc::DataContainer3D< DataT > &potential)
void setPotentialBoundaryFromFormula(const AnalyticalFields< DataT > &formulas, const o2::tpc::RegularGrid3D< DataT > &grid, o2::tpc::DataContainer3D< DataT > &potential)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
unsigned short getNZ() const
unsigned short getNR() const
unsigned short getNPhi() const
static bool isFull3D
< Parameters choice for MultiGrid algorithm