OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
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
29#include <cmath>
30#include <iomanip>
33
34namespace interpolation {
36 NDGrid::NDGrid() : coord_m(), maps_m(), constantSpacing_m(false) {}
37
39 : coord_m(rhs.coord_m), maps_m(rhs.maps_m), constantSpacing_m(rhs.constantSpacing_m) {}
40
41 NDGrid::NDGrid(std::vector<int> size, std::vector<const double*> gridCoordinates)
42 : coord_m(), maps_m(), constantSpacing_m(false) {
43 for (unsigned int i = 0; i < size.size(); i++) {
44 if (size[i] < 1) {
45 throw(OpalException(
46 "NDGrid::NDGrid(...)", "ND Grid must be at least 1x1x...x1 grid"));
47 }
48 coord_m.push_back(
49 std::vector<double>(gridCoordinates[i], gridCoordinates[i] + size[i]));
50 }
52 }
53
54 NDGrid::NDGrid(int nDimensions, int* size, double* spacing, double* min)
55 : coord_m(nDimensions), maps_m(), constantSpacing_m(true) {
56 for (int i = 0; i < nDimensions; i++) {
57 if (size[i] < 1) {
58 throw(OpalException(
59 "NDGrid::NDGrid(...)", "ND Grid must be at least 1x1x...x1 grid"));
60 }
61 coord_m[i] = std::vector<double>(size[i]);
62 for (unsigned int j = 0; j < coord_m[i].size(); j++) {
63 coord_m[i][j] = min[i] + j * spacing[i];
64 }
65 }
66 }
67
68 NDGrid::NDGrid(std::vector<std::vector<double> > gridCoordinates)
69 : coord_m(gridCoordinates), maps_m(), constantSpacing_m(false) {
70 for (unsigned int i = 0; i < gridCoordinates.size(); i++) {
71 if (gridCoordinates[i].size() < 1) {
72 throw(OpalException(
73 "NDGrid::NDGrid(...)", "ND Grid must be at least 1x1x...x1 grid"));
74 }
75 }
77 }
78
79 double* NDGrid::newCoordArray(const int& dimension) const {
80 double* array = new double[coord_m[dimension].size()];
81 for (unsigned int i = 0; i < coord_m[dimension].size(); i++) {
82 array[i] = coord_m[dimension][i];
83 }
84 return array;
85 }
86
87 // Mesh::Iterator wraps around a std::vector<int>
88 // it[0] is least significant, it[max] is most signifcant
89 Mesh::Iterator& NDGrid::addEquals(Mesh::Iterator& lhs, int difference) const {
90 if (difference < 0) {
91 return subEquals(lhs, -difference);
92 }
93 std::vector<int> index(coord_m.size(), 0);
94 std::vector<int> content(coord_m.size(), 1);
95 for (int i = int(index.size() - 2); i >= 0; i--) {
96 content[i] = content[i + 1] * coord_m[i + 1].size(); // content could be member
97 // variable
98 }
99 for (int i = 0; i < int(index.size()); i++) {
100 index[i] = difference / content[i];
101 difference -= index[i] * content[i];
102 }
103 for (unsigned int i = 0; i < index.size(); i++) {
104 lhs.state_m[i] += index[i];
105 }
106 for (int i = int(index.size()) - 1; i > 0; i--) {
107 if (lhs.state_m[i] > int(coord_m[i].size())) {
108 lhs.state_m[i - 1]++;
109 lhs.state_m[i] -= coord_m[i].size();
110 }
111 }
112
113 return lhs;
114 }
115
116 Mesh::Iterator& NDGrid::subEquals(Mesh::Iterator& lhs, int difference) const {
117 if (difference < 0) {
118 return addEquals(lhs, -difference);
119 }
120 std::vector<int> index(coord_m.size(), 0);
121 std::vector<int> content(coord_m.size(), 1);
122 for (int i = int(index.size() - 2); i >= 0; i--) {
123 content[i] = content[i + 1] * coord_m[i + 1].size(); // content could be member
124 // variable
125 }
126 for (int i = 0; i < int(index.size()); i++) {
127 index[i] = difference / content[i];
128 difference -= index[i] * content[i];
129 }
130 for (unsigned int i = 0; i < index.size(); i++) {
131 lhs.state_m[i] -= index[i];
132 }
133 for (int i = int(index.size()) - 1; i > 0; i--) {
134 if (lhs.state_m[i] < 1) {
135 lhs.state_m[i - 1]--;
136 lhs.state_m[i] += coord_m[i].size();
137 }
138 }
139 return lhs;
140 }
141
143 return addEquals(lhs, rhs.toInteger());
144 }
145
147 return subEquals(lhs, rhs.toInteger());
148 }
149
151 int i = coord_m.size() - 1;
152 while (lhs[i] == int(coord_m[i].size()) && i > 0) {
153 lhs[i] = 1;
154 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
172 void 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
188 bool 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
197 int 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
210 Mesh::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 if (index[i] < int(coord_m[i].size() - 1) && index[i] >= 0) {
216 index[i] +=
217 (2 * (position[i] - coord_m[i][index[i]])
218 > coord_m[i][index[i] + 1] - coord_m[i][index[i]]
219 ? 2
220 : 1);
221 } else {
222 index[i]++;
223 }
224 if (index[i] < 1) {
225 index[i] = 1;
226 }
227 if (index[i] > int(coord_m[i].size())) {
228 index[i] = coord_m[i].size();
229 }
230 }
231 return Mesh::Iterator(index, this);
232 }
233
235 std::vector<std::vector<double> > coord(coord_m.size());
236 for (size_t i = 0; i < coord.size(); ++i) {
237 if (coord_m[i].size() <= 1) {
238 throw(OpalException(
239 "NDGrid::dual(...)", "ND Grid must be at least 2x2x...x2 grid"));
240 }
241 coord[i] = std::vector<double>(coord_m[i].size() - 1);
242 for (size_t j = 0; j < coord[i].size(); ++j) {
243 coord[i][j] = (coord_m[i][j] + coord_m[i][j + 1]) / 2.;
244 }
245 }
246 return new NDGrid(coord);
247 }
248
250} // namespace interpolation
std::vector< int > state_m
Definition Mesh.h:235
Base class for meshing routines.
Definition Mesh.h:49
virtual Mesh::Iterator & addEquals(Mesh::Iterator &lhs, int difference) const
Definition NDGrid.cpp:89
virtual Mesh::Iterator & addOne(Mesh::Iterator &lhs) const
Definition NDGrid.cpp:150
virtual Mesh::Iterator & subOne(Mesh::Iterator &lhs) const
Definition NDGrid.cpp:160
int toInteger(const Mesh::Iterator &lhs) const
Definition NDGrid.cpp:197
Mesh::Iterator getNearest(const double *position) const
Definition NDGrid.cpp:210
std::vector< std::vector< double > > coord_m
Definition NDGrid.h:280
double min(const int &dimension) const
Definition NDGrid.h:339
double * newCoordArray(const int &dimension) const
Definition NDGrid.cpp:79
NDGrid()
////// NDGrid ///////
Definition NDGrid.cpp:36
void lowerBound(const std::vector< double > &pos, std::vector< int > &xIndex) const
Definition NDGrid.h:332
void setConstantSpacing(bool spacing)
Definition NDGrid.h:373
virtual Mesh::Iterator & subEquals(Mesh::Iterator &lhs, int difference) const
Definition NDGrid.cpp:116
Mesh * dual() const
Definition NDGrid.cpp:234
int size(const int &dimension) const
Definition NDGrid.h:309
double & coord(const int &index, const int &dimension)
Definition NDGrid.h:301
virtual bool isGreater(const Mesh::Iterator &lhs, const Mesh::Iterator &rhs) const
Definition NDGrid.cpp:188