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