SpatialOps
NeboBasic.h
1 /*
2  * Copyright (c) 2014-2017 The University of Utah
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to
6  * deal in the Software without restriction, including without limitation the
7  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8  * sell copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20  * IN THE SOFTWARE.
21  */
22 
23 #ifndef NEBO_BASIC_H
24 # define NEBO_BASIC_H
25 
26 # include <spatialops/SpatialOpsConfigure.h>
30 # include <spatialops/structured/SpatialMask.h>
32 # include <cmath>
33 # include <math.h>
34 # include <limits>
35 # include <boost/math/special_functions/erf.hpp>
36 # include <boost/math/special_functions/gamma.hpp>
37 
38 # ifdef NEBO_REPORT_BACKEND
39 # include <iostream>
40 # endif
41  /* NEBO_REPORT_BACKEND */
42 
43 # ifdef ENABLE_THREADS
45 # include <vector>
46 # include <boost/bind.hpp>
47 # include <spatialops/ThreadPool.h>
49 # include <spatialops/Semaphore.h>
50 # endif
51  /* ENABLE_THREADS */
52 
53 # ifdef __CUDACC__
54 # include <sstream>
55 # include <spatialops/structured/MemoryTypes.h>
56 # endif
57  /* __CUDACC__ */
58 
59  namespace SpatialOps {
60  /* Meta-programming compiler flags */
61  struct All;
62  struct InteriorOnly;
63 
64  /* Optional Compile Time Args */
65  template<typename ... Args>
67  namespace CompileTimeOptionalArgsNamespace
68  {
69  struct HasBCOnX;
70  struct HasBCOnY;
71  struct HasBCOnZ;
72  }
73 
74  inline GhostData calculate_actual_ghost(bool const useGhost,
75  GhostData const & lhs,
76  BoundaryCellInfo const & bc,
77  GhostData const & rhs) {
78  if(bc.has_bc(0,PLUS_SIDE) && rhs.get_plus(0) < bc.has_extra(0)) {
79  std::ostringstream msg;
80  msg << "Nebo error in " << "Nebo Ghost Checking" << ":\n";
81  msg << "Not enough valid extra cells to validate all interior ";
82  msg << "cells in the X direction";
83  msg << "\n";
84  msg << "\t - " << __FILE__ << " : " << __LINE__;
85  throw(std::runtime_error(msg.str()));;
86  };
87 
88  if(bc.has_bc(1,PLUS_SIDE) && rhs.get_plus(1) < bc.has_extra(1)) {
89  std::ostringstream msg;
90  msg << "Nebo error in " << "Nebo Ghost Checking" << ":\n";
91  msg << "Not enough valid extra cells to validate all interior ";
92  msg << "cells in the Y direction";
93  msg << "\n";
94  msg << "\t - " << __FILE__ << " : " << __LINE__;
95  throw(std::runtime_error(msg.str()));;
96  };
97 
98  if(bc.has_bc(2,PLUS_SIDE) && rhs.get_plus(2) < bc.has_extra(2)) {
99  std::ostringstream msg;
100  msg << "Nebo error in " << "Nebo Ghost Checking" << ":\n";
101  msg << "Not enough valid extra cells to validate all interior ";
102  msg << "cells in the Z direction";
103  msg << "\n";
104  msg << "\t - " << __FILE__ << " : " << __LINE__;
105  throw(std::runtime_error(msg.str()));;
106  };
107 
108  return ((useGhost
109  ? min((lhs + point_to_ghost(bc.has_extra())), rhs)
110  : GhostData(IntVec(0, 0, 0),
111  bc.has_extra()))
112  - point_to_ghost(bc.has_extra()));
113  };
114 
115  template<typename Type1, typename Type2>
117 
118  template<typename T>
119  struct NeboFieldCheck<SpatialOps::SpatialField<SpatialOps::SingleValue, T>,
120  SpatialOps::SpatialField<SpatialOps::SingleValue, T> > {};
121 
122  template<typename Type>
123  struct NeboFieldCheck<Type, Type> { Type typedef Result; };
124 
125  inline IntVec nebo_find_partition(IntVec const & extent,
126  int const thread_count) {
127  int x = 1;
128  int y = 1;
129  int z = 1;
130 
131  if(thread_count <= extent[2]) { z = thread_count; }
132  else if(thread_count <= extent[1]) { y = thread_count; }
133  else if(thread_count <= extent[0]) { x = thread_count; };
134 
135  return IntVec(x, y, z);
136  };
137 
138  inline int nebo_partition_count(IntVec const & split) {
139  return split[0] * split[1] * split[2];
140  };
141 
142  inline void nebo_set_up_extents(IntVec const & current,
143  IntVec const & split,
144  GhostData & localLimits,
145  GhostData const & limits) {
146 
147  //full extent indexed from 0 rather than DLow (which is nonpositive - zero or below)
148  IntVec const fullExtent(limits.get_plus(0) - limits.get_minus(0),
149  limits.get_plus(1) - limits.get_minus(1),
150  limits.get_plus(2) - limits.get_minus(2));
151 
152  //sanity checks
153 # ifndef NDEBUG
154  for( size_t i=0; i<3; ++i ){
155  assert( fullExtent[i] >= split[i] );
156  assert( split[i] > 0 );
157  assert( current[i] < split[i] );
158  assert( current[i] >= 0 );
159  }
160 # endif
161 
162  //extent of a partition
163  IntVec const stdExtent = fullExtent / split;
164 
165  //number of partitions with an extra cell (to cover what is not covered by stdExtent)
166  IntVec const nExtra(fullExtent[0] % split[0],
167  fullExtent[1] % split[1],
168  fullExtent[2] % split[2]);
169 
170  //number of previous paritions with an extra cell
171  IntVec const pastExtra(current[0] < nExtra[0] ? current[0] : nExtra[0],
172  current[1] < nExtra[1] ? current[1] : nExtra[1],
173  current[2] < nExtra[2] ? current[2] : nExtra[2]);
174 
175  //does current partition have an extra cell
176  IntVec const currentExtra(current[0] < nExtra[0] ? 1 : 0,
177  current[1] < nExtra[1] ? 1 : 0,
178  current[2] < nExtra[2] ? 1 : 0);
179 
180  //calculate current partition's low and high
181  IntVec const low = stdExtent * current + pastExtra;
182  IntVec const high = low + stdExtent + currentExtra;
183 
184  //shift back to indexing from DLow rather than zero
185  localLimits = GhostData(low[0] + limits.get_minus(0),
186  high[0] + limits.get_minus(0),
187  low[1] + limits.get_minus(1),
188  high[1] + limits.get_minus(1),
189  low[2] + limits.get_minus(2),
190  high[2] + limits.get_minus(2));
191  };
192 
193  inline IntVec nebo_next_partition(IntVec const & current,
194  IntVec const & split) {
195  IntVec result;
196 
197  if(current[2] < split[2] - 1)
198  result = IntVec(current[0], current[1], 1 + current[2]);
199  else if(current[1] < split[1] - 1)
200  result = IntVec(current[0], 1 + current[1], 0);
201  else result = IntVec(1 + current[0], 0, 0);
202 
203  return result;
204  };
205 
206  template<typename Operand, typename FieldType>
207  struct NeboExpression {
208  public:
209  FieldType typedef field_type;
210 
211  Operand typedef Expression;
212 
213  NeboExpression(Operand const & given)
214  : expr_(given)
215  {}
216 
217  inline Operand const & expr(void) const { return expr_; }
218 
219  private:
220  Operand expr_;
221  };
222 
223  template<typename Operand, typename T>
225  public:
227 
228  Operand typedef Expression;
229 
230  NeboSingleValueExpression(Operand const & given)
231  : expr_(given)
232  {}
233 
234  inline Operand const & expr(void) const { return expr_; }
235 
236  private:
237  Operand expr_;
238  };
239 
240  template<typename Operand, typename FieldType>
242  public:
243  FieldType typedef field_type;
244 
245  Operand typedef Expression;
246 
247  NeboBooleanExpression(Operand const & given)
248  : expr_(given)
249  {}
250 
251  inline Operand const & expr(void) const { return expr_; }
252 
253  private:
254  Operand expr_;
255  };
256 
257  template<typename Operand, typename T>
259  public:
261 
262  Operand typedef Expression;
263 
264  NeboBooleanSingleValueExpression(Operand const & given)
265  : expr_(given)
266  {}
267 
268  inline Operand const & expr(void) const { return expr_; }
269 
270  private:
271  Operand expr_;
272  };
273 
274  /* Modes: */
275  struct Initial;
276 # ifdef ENABLE_THREADS
277  struct Resize;
278 # endif
279  /* ENABLE_THREADS */
280  struct SeqWalk;
281 # ifdef __CUDACC__
282  struct GPUWalk;
283 # endif
284  /* __CUDACC__ */
285  } /* SpatialOps */
286 
287 #endif
288 /* NEBO_BASIC_H */
bool has_bc(const int dir, const BCSide side) const
query to see if a physical boundary is present in the given direction (0=x, 1=y, 2=z) and the specifi...
int has_extra(const int dir) const
obtain the number of extra cells actually present on this field due to presence of physical boundarie...
IntVec get_plus() const
obtain the IntVec containing the number of ghost cells on the (+) faces
Definition: GhostData.h:145
Holds information about the number of ghost cells on each side of the domain.
Definition: GhostData.h:54
Abstracts a field.
Definition: SpatialField.h:132
IntVec get_minus() const
obtain the IntVec containing the number of ghost cells on the (-) faces
Definition: GhostData.h:135
Provides information about boundary cells for various fields.