OPAL (Object Oriented Parallel Accelerator Library) 2024.2
OPAL
SectorField.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012, Chris Rogers
3 * All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * 1. Redistributions of source code must retain the above copyright notice,
7 * this list of conditions and the following disclaimer.
8 * 2. Redistributions in binary form must reproduce the above copyright notice,
9 * this list of conditions and the following disclaimer in the documentation
10 * and/or other materials provided with the distribution.
11 * 3. Neither the name of STFC nor the names of its contributors may be used to
12 * endorse or promote products derived from this software without specific
13 * prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "Fields/SectorField.h"
29
30#include <algorithm>
31#include <cmath>
32#include <limits>
33#include <string>
34#include <vector>
35
36#include "Physics/Physics.h"
38
39// note I don't use exactly max() as the bounding box because I don't want to
40// accidentally wrap around due to some unforeseen floating point precision
41// issue
42SectorField::SectorField(const std::string& /*file_name*/)
43 : bbMin_m(3, -std::numeric_limits<double>::max()/10.),
44 bbMax_m(3, std::numeric_limits<double>::max()/10.),
45 polarBBMin_m(3, 0), polarBBMax_m(3, 0) {
46 polarBBMin_m[1] = bbMin_m[1];
47 polarBBMax_m[1] = bbMax_m[1];
48 polarBBMax_m[0] = bbMax_m[0];
51}
52
54
55void SectorField::convertToPolar(double* position) {
56 double x = std::sqrt(position[0]*position[0]+position[2]*position[2]);
57 double z = std::atan2(position[2], position[0]);
58 position[0] = x;
59 position[2] = z;
60}
61
62void SectorField::convertToPolar(const double* position, double* value) {
63 double x = +value[0]*std::cos(position[2])
64 +value[2]*std::sin(position[2]);
65 double z = +value[2]*std::cos(position[2])
66 -value[0]*std::sin(position[2]);
67 value[0] = x;
68 value[2] = z;
69}
70
71void SectorField::convertToCartesian(double* position) {
72 double x = position[0]*std::cos(position[2]); // r cos(phi)
73 double z = position[0]*std::sin(position[2]); // r sin(phi)
74 position[0] = x;
75 position[2] = z;
76}
77
78void SectorField::convertToCartesian(const double* position, double* value) {
79 double x = +value[0]*std::cos(position[2])
80 -value[2]*std::sin(position[2]);
81 double z = +value[2]*std::cos(position[2])
82 +value[0]*std::sin(position[2]);
83 value[0] = x;
84 value[2] = z;
85}
86
88 (double bbMinR, double bbMinY, double bbMinPhi,
89 double bbMaxR, double bbMaxY, double bbMaxPhi,
90 double bbTolR, double bbTolY, double bbTolPhi) {
91 if (bbMinR > bbMaxR) {
92 throw(LogicalError(
93 "SectorField::SetPolarBoundingBox",
94 "Bounding box minimum radius was greater than maximum radius"));
95 }
96 if (bbMinR < 0.) {
97 throw(LogicalError(
98 "SectorField::SetPolarBoundingBox",
99 "Bounding box radius must be positive"
100 ));
101 }
102 if (bbMinY > bbMaxY) {
103 throw(LogicalError(
104 "SectorField::SetPolarBoundingBox",
105 "Bounding box minimum y was greater than maximum y"
106 ));
107 }
108 if (bbMinPhi > bbMaxPhi) {
109 throw(LogicalError(
110 "SectorField::SetPolarBoundingBox",
111 "Bounding box minimum angle was greater than maximum angle"
112 ));
113 }
114 if (bbMinPhi < -2.*Physics::pi || bbMinPhi > 2.*Physics::pi ||
115 bbMaxPhi < -2.*Physics::pi || bbMaxPhi > 2.*Physics::pi) {
116 throw(LogicalError(
117 "SectorField::SetPolarBoundingBox",
118 "Bounding box angles must be in range -2*Physics::pi < phi < 2*Physics::pi"
119 ));
120 }
121
122 polarBBMin_m[0] = bbMinR-bbTolR;
123 polarBBMin_m[1] = bbMinY-bbTolY;
124 polarBBMin_m[2] = bbMinPhi-bbTolPhi;
125
126 polarBBMax_m[0] = bbMaxR+bbTolR;
127 polarBBMax_m[1] = bbMaxY+bbTolY;
128 polarBBMax_m[2] = bbMaxPhi+bbTolPhi;
129
130 // bounding box from corner coordinates
131 std::vector< std::vector<double> > corner_coords(
132 getCorners(bbMinR, bbMinPhi, bbMaxR, bbMaxPhi));
133 bbMin_m[0] =
134 *std::min_element(corner_coords[0].begin(), corner_coords[0].end());
135 bbMax_m[0] =
136 *std::max_element(corner_coords[0].begin(), corner_coords[0].end());
137 bbMin_m[1] = bbMinY;
138 bbMax_m[1] = bbMaxY;
139 bbMin_m[2] =
140 *std::min_element(corner_coords[1].begin(), corner_coords[1].end());
141 bbMax_m[2] =
142 *std::max_element(corner_coords[1].begin(), corner_coords[1].end());
143
144 // if the magnet crosses an axis, then the corners are no longer at the max
145 // extent
146 if ( (bbMaxPhi > 0.5*Physics::pi && bbMinPhi < 0.5*Physics::pi) ||
147 (bbMaxPhi > -1.5*Physics::pi && bbMinPhi < -1.5*Physics::pi) ) {
148 bbMax_m[2] = bbMaxR;
149 }
150 if ((bbMaxPhi > Physics::pi && bbMinPhi < Physics::pi) ||
151 (bbMaxPhi > -Physics::pi && bbMinPhi < -Physics::pi)) {
152 bbMin_m[0] = -bbMaxR;
153 }
154 if ((bbMaxPhi > 1.5*Physics::pi && bbMinPhi < 1.5*Physics::pi) ||
155 (bbMaxPhi > -0.5*Physics::pi && bbMinPhi < -0.5*Physics::pi)) {
156 bbMin_m[2] = -bbMaxR;
157 }
158 if ((bbMaxPhi > 0.*Physics::pi && bbMinPhi < 0.*Physics::pi)) {
159 bbMax_m[0] = bbMaxR;
160 }
161}
162
163std::vector< std::vector<double> > SectorField::getCorners
164 (double bbMinR, double bbMinPhi, double bbMaxR, double bbMaxPhi) {
165 std::vector< std::vector<double> > corner_coords(2);
166 corner_coords[0] = std::vector<double>(4);
167 corner_coords[1] = std::vector<double>(4);
168 // corners in polar coordinates
169 double corner_0[3] = {bbMinR, 0., bbMinPhi};
170 double corner_1[3] = {bbMinR, 0., bbMaxPhi};
171 double corner_2[3] = {bbMaxR, 0., bbMaxPhi};
172 double corner_3[3] = {bbMaxR, 0., bbMinPhi};
173 convertToCartesian(corner_0);
174 convertToCartesian(corner_1);
175 convertToCartesian(corner_2);
176 convertToCartesian(corner_3);
177 // corners in rectangular coordinates (ignore y)
178 corner_coords[0][0] = corner_0[0];
179 corner_coords[0][1] = corner_1[0];
180 corner_coords[0][2] = corner_2[0];
181 corner_coords[0][3] = corner_3[0];
182 corner_coords[1][0] = corner_0[2];
183 corner_coords[1][1] = corner_1[2];
184 corner_coords[1][2] = corner_2[2];
185 corner_coords[1][3] = corner_3[2];
186 return corner_coords;
187}
188
189
190std::vector<double> SectorField::getPolarBoundingBoxMin() const {
191 return polarBBMin_m;
192}
193
194std::vector<double> SectorField::getPolarBoundingBoxMax() const {
195 return polarBBMax_m;
196}
197
198void SectorField::getFieldDimensions(double &zBegin, double &zEnd,
199 double &rBegin, double &rEnd) const {
200 zBegin = polarBBMin_m[2]*(polarBBMin_m[0]+polarBBMax_m[0])/2.;
201 zEnd = polarBBMax_m[2]*(polarBBMin_m[0]+polarBBMax_m[0])/2.;
202 rBegin = polarBBMin_m[0];
203 rEnd = polarBBMin_m[2];
204}
205
206void SectorField::getFieldDimensions(double &xIni, double &xFinal,
207 double &yIni, double &yFinal,
208 double &zIni, double &zFinal) const {
209 xIni = bbMin_m[0];
210 yIni = bbMin_m[1];
211 zIni = bbMin_m[2];
212 xFinal = bbMax_m[0];
213 yFinal = bbMax_m[1];
214 zFinal = bbMax_m[2];
215}
PartBunchBase< T, Dim >::ConstIterator end(PartBunchBase< T, Dim > const &bunch)
PartBunchBase< T, Dim >::ConstIterator begin(PartBunchBase< T, Dim > const &bunch)
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
constexpr double two_pi
The value of.
Definition Physics.h:33
constexpr double pi
The value of.
Definition Physics.h:30
std::vector< double > bbMin_m
std::vector< std::vector< double > > getCorners(double bbMinR, double bbMinPhi, double bbMaxR, double bbMaxPhi)
std::vector< double > polarBBMin_m
void getFieldDimensions(double &zBegin, double &zEnd, double &rBegin, double &rEnd) const
virtual std::vector< double > getPolarBoundingBoxMin() const
static void convertToCartesian(double *position)
std::vector< double > polarBBMax_m
virtual ~SectorField()
std::vector< double > bbMax_m
SectorField(const std::string &file_name)
virtual std::vector< double > getPolarBoundingBoxMax() const
static void convertToPolar(double *position)
void setPolarBoundingBox(double bbMinR, double bbMinY, double bbMinPhi, double bbMaxR, double bbMaxY, double bbMaxPhi, double bbTolR, double bbTolY, double bbTolPhi)
Logical error exception.