OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
NDGrid.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017, 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 <cmath>
29#include <iomanip>
33
34namespace interpolation {
36NDGrid::NDGrid() : coord_m(), maps_m(), constantSpacing_m(false) {
37}
38
39NDGrid::NDGrid(const NDGrid& rhs) : coord_m(rhs.coord_m), maps_m(rhs.maps_m),
40 constantSpacing_m(rhs.constantSpacing_m) {
41}
42
43NDGrid::NDGrid(std::vector<int> size, std::vector<const double *> gridCoordinates)
44 : coord_m(), maps_m(), constantSpacing_m(false) {
45 for (unsigned int i=0; i<size.size(); i++) {
46 if (size[i] < 1) {
47 throw(OpalException("NDGrid::NDGrid(...)",
48 "ND Grid must be at least 1x1x...x1 grid"));
49 }
50 coord_m.push_back(std::vector<double>(gridCoordinates[i],
51 gridCoordinates[i] + size[i]));
52 }
54}
55
56NDGrid::NDGrid(int nDimensions, int* size, double* spacing, double* min)
57 : coord_m(nDimensions), maps_m(), constantSpacing_m(true) {
58 for (int i=0; i<nDimensions; i++) {
59 if (size[i] < 1) {
60 throw(OpalException("NDGrid::NDGrid(...)",
61 "ND Grid must be at least 1x1x...x1 grid"));
62 }
63 coord_m[i] = std::vector<double>(size[i]);
64 for (unsigned int j=0; j<coord_m[i].size(); j++) {
65 coord_m[i][j] = min[i] + j*spacing[i];
66 }
67 }
68}
69
70NDGrid::NDGrid(std::vector< std::vector<double> > gridCoordinates)
71 : coord_m(gridCoordinates), maps_m(), constantSpacing_m(false) {
72 for (unsigned int i=0; i<gridCoordinates.size(); i++) {
73 if (gridCoordinates[i].size() < 1) {
74 throw (OpalException("NDGrid::NDGrid(...)",
75 "ND Grid must be at least 1x1x...x1 grid"));
76 }
77 }
79}
80
81
82double* NDGrid::newCoordArray ( const int& dimension) const {
83 double * array = new double[coord_m[dimension].size() ];
84 for (unsigned int i=0; i<coord_m[dimension].size(); i++) {
85 array[i] = coord_m[dimension][i];
86 }
87 return array;
88}
89
90//Mesh::Iterator wraps around a std::vector<int>
91//it[0] is least significant, it[max] is most signifcant
92Mesh::Iterator& NDGrid::addEquals(Mesh::Iterator& lhs, int difference) const {
93 if (difference < 0) {
94 return subEquals(lhs, -difference);
95 }
96 std::vector<int> index(coord_m.size(),0);
97 std::vector<int> content(coord_m.size(),1);
98 for (int i = int(index.size()-2); i >= 0; i--) {
99 content[i] = content[i+1]*coord_m[i+1].size(); //content could be member variable
100 }
101 for (int i = 0; i < int(index.size()); i++) {
102 index[i] = difference/content[i];
103 difference -= index[i] * content[i];
104 }
105 for (unsigned int i=0; i<index.size(); i++) {
106 lhs.state_m[i] += index[i];
107 }
108 for (int i = int(index.size())-1; i > 0; i--) {
109 if (lhs.state_m[i] > int(coord_m[i].size())) {
110 lhs.state_m[i-1]++;
111 lhs.state_m[i] -= coord_m[i].size();
112 }
113 }
114
115 return lhs;
116}
117
118Mesh::Iterator& NDGrid::subEquals(Mesh::Iterator& lhs, int difference) const {
119 if (difference < 0) {
120 return addEquals(lhs, -difference);
121 }
122 std::vector<int> index(coord_m.size(),0);
123 std::vector<int> content(coord_m.size(),1);
124 for (int i = int(index.size()-2); i >= 0; i--) {
125 content[i] = content[i+1]*coord_m[i+1].size(); //content could be member variable
126 }
127 for (int i = 0; i < int(index.size()); i++) {
128 index[i] = difference/content[i];
129 difference -= index[i] * content[i];
130 }
131 for (unsigned int i = 0; i < index.size(); i++) {
132 lhs.state_m[i] -= index[i];
133 }
134 for (int i=int(index.size())-1; i>0; i--) {
135 if (lhs.state_m[i] < 1) {
136 lhs.state_m[i-1]--;
137 lhs.state_m[i] += coord_m[i].size();
138 }
139 }
140 return lhs;
141}
142
144 return addEquals(lhs, rhs.toInteger());
145}
146
148 return subEquals(lhs, rhs.toInteger());
149}
150
152 int i = coord_m.size()-1;
153 while (lhs[i] == int(coord_m[i].size()) && i>0) {
154 lhs[i]=1; i--;
155 }
156 lhs[i]++;
157 return lhs;
158}
159
161 lhs[coord_m.size()-1] -= 1;
162
163 int i = coord_m.size()-1;
164 while (lhs[i] == 0 && i>0) {
165 lhs.state_m[i] = coord_m[i].size();
166 i--;
167 lhs.state_m[i]--;
168 }
169 return lhs;
170}
171
172void NDGrid::setConstantSpacing(double tolerance_m) {
173 constantSpacing_m = true;
174 for (unsigned int i = 0; i < coord_m.size(); i++) {
175 for (unsigned int j = 0; j < coord_m[i].size()-1; j++) {
176 double coord_j1 = coord_m[i][j+1];
177 double coord_j0 = coord_m[i][j];
178 double coord_1 = coord_m[i][1];
179 double coord_0 = coord_m[i][0];
180 if (std::abs(1-(coord_j1-coord_j0)/(coord_1-coord_0)) > tolerance_m) {
181 constantSpacing_m = false;
182 return;
183 }
184 }
185 }
186}
187
188bool NDGrid::isGreater(const Mesh::Iterator& lhs, const Mesh::Iterator& rhs) const {
189 unsigned int i = 0;
190 // if all equal; rhs[i] = rhs.last
191 while (i < rhs.state_m.size()-1 && lhs.state_m[i] == rhs.state_m[i]) {
192 i++;
193 }
194 return (lhs[i] > rhs[i]);
195}
196
197int NDGrid::toInteger(const Mesh::Iterator& lhs) const {
198 int difference = 0;
199 std::vector<int> index (coord_m.size(),0);
200 std::vector<int> content(coord_m.size(),1);
201 for (int i = int(index.size()-2); i >= 0; i--) {
202 content[i] = content[i+1]*coord_m[i+1].size();
203 }
204 for (int i = 0; i < int(index.size()); i++) {
205 difference += (lhs.state_m[i]-1) * (content[i]);
206 }
207 return difference;
208}
209
210Mesh::Iterator NDGrid::getNearest(const double* position) const {
211 std::vector<int> index(coord_m.size());
212 std::vector<double> pos(position, position+coord_m.size());
213 lowerBound(pos, index);
214 for (unsigned int i = 0; i < coord_m.size(); i++)
215 {
216 if (index[i] < int(coord_m[i].size()-1) && index[i] >= 0) {
217 index[i] += (2*(position[i] - coord_m[i][index[i]]) > coord_m[i][index[i]+1]-coord_m[i][index[i]] ? 2 : 1);
218 } else {
219 index[i]++;
220 }
221 if (index[i] < 1) {
222 index[i] = 1;
223 }
224 if (index[i] > int(coord_m[i].size())) {
225 index[i] = coord_m[i].size();
226 }
227 }
228 return Mesh::Iterator(index, this);
229}
230
231
233 std::vector<std::vector<double> > coord(coord_m.size());
234 for (size_t i = 0; i < coord.size(); ++i) {
235 if (coord_m[i].size() <= 1) {
236 throw(OpalException("NDGrid::dual(...)",
237 "ND Grid must be at least 2x2x...x2 grid"));
238 }
239 coord[i] = std::vector<double>(coord_m[i].size()-1);
240 for (size_t j = 0; j < coord[i].size(); ++j) {
241 coord[i][j] = (coord_m[i][j] + coord_m[i][j+1])/2.;
242 }
243 }
244 return new NDGrid(coord);
245}
246
247
249}
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:76
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
Base class for meshing routines.
Definition: Mesh.h:49
std::vector< int > state_m
Definition: Mesh.h:270
virtual Mesh::Iterator & addEquals(Mesh::Iterator &lhs, int difference) const
Definition: NDGrid.cpp:92
virtual Mesh::Iterator & addOne(Mesh::Iterator &lhs) const
Definition: NDGrid.cpp:151
virtual Mesh::Iterator & subOne(Mesh::Iterator &lhs) const
Definition: NDGrid.cpp:160
int toInteger(const Mesh::Iterator &lhs) const
Definition: NDGrid.cpp:197
std::vector< std::vector< double > > coord_m
Definition: NDGrid.h:281
Mesh::Iterator getNearest(const double *position) const
Definition: NDGrid.cpp:210
double min(const int &dimension) const
Definition: NDGrid.h:342
double * newCoordArray(const int &dimension) const
Definition: NDGrid.cpp:82
NDGrid()
////// NDGrid ///////
Definition: NDGrid.cpp:36
void lowerBound(const std::vector< double > &pos, std::vector< int > &xIndex) const
Definition: NDGrid.h:335
void setConstantSpacing(bool spacing)
Definition: NDGrid.h:384
virtual Mesh::Iterator & subEquals(Mesh::Iterator &lhs, int difference) const
Definition: NDGrid.cpp:118
Mesh * dual() const
Definition: NDGrid.cpp:232
int size(const int &dimension) const
Definition: NDGrid.h:310
double & coord(const int &index, const int &dimension)
Definition: NDGrid.h:302
virtual bool isGreater(const Mesh::Iterator &lhs, const Mesh::Iterator &rhs) const
Definition: NDGrid.cpp:188
The base class for all OPAL exceptions.
Definition: OpalException.h:28