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>
33 # include <cmath>
34 # include <math.h>
35 # include <limits>
36 # include <boost/math/special_functions/erf.hpp>
37 # include <boost/math/special_functions/gamma.hpp>
38 # include <boost/shared_ptr.hpp>
39 # include <boost/enable_shared_from_this.hpp>
40 
41 
42 # ifdef NEBO_REPORT_BACKEND
43 # include <iostream>
44 # endif
45  /* NEBO_REPORT_BACKEND */
46 
47 # ifdef ENABLE_THREADS
49 # include <vector>
50 # include <boost/bind.hpp>
51 # include <spatialops/ThreadPool.h>
53 # include <spatialops/Semaphore.h>
54 # endif
55  /* ENABLE_THREADS */
56 
57 # ifdef __CUDACC__
58 # include <sstream>
59 # include <spatialops/structured/MemoryTypes.h>
60 # endif
61  /* __CUDACC__ */
62 
63  namespace SpatialOps {
64  /* Meta-programming compiler flags */
65  struct All;
66  struct InteriorOnly;
67 
68  /* Optional Compile Time Args */
69  template<typename ... Args>
71  namespace CompileTimeOptionalArgsNamespace
72  {
73  struct HasBCOnX;
74  struct HasBCOnY;
75  struct HasBCOnZ;
76  }
77 
78  inline GhostData calculate_actual_ghost(bool const useGhost,
79  GhostData const & lhs,
80  BoundaryCellInfo const & bc,
81  GhostData const & rhs) {
82  if(bc.has_bc(0,PLUS_SIDE) && rhs.get_plus(0) < bc.has_extra(0)) {
83  std::ostringstream msg;
84  msg << "Nebo error in " << "Nebo Ghost Checking" << ":\n";
85  msg << "Not enough valid extra cells to validate all interior ";
86  msg << "cells in the X direction";
87  msg << "\n";
88  msg << "\t - " << __FILE__ << " : " << __LINE__;
89  throw(std::runtime_error(msg.str()));;
90  };
91 
92  if(bc.has_bc(1,PLUS_SIDE) && rhs.get_plus(1) < bc.has_extra(1)) {
93  std::ostringstream msg;
94  msg << "Nebo error in " << "Nebo Ghost Checking" << ":\n";
95  msg << "Not enough valid extra cells to validate all interior ";
96  msg << "cells in the Y direction";
97  msg << "\n";
98  msg << "\t - " << __FILE__ << " : " << __LINE__;
99  throw(std::runtime_error(msg.str()));;
100  };
101 
102  if(bc.has_bc(2,PLUS_SIDE) && rhs.get_plus(2) < bc.has_extra(2)) {
103  std::ostringstream msg;
104  msg << "Nebo error in " << "Nebo Ghost Checking" << ":\n";
105  msg << "Not enough valid extra cells to validate all interior ";
106  msg << "cells in the Z direction";
107  msg << "\n";
108  msg << "\t - " << __FILE__ << " : " << __LINE__;
109  throw(std::runtime_error(msg.str()));;
110  };
111 
112  return ((useGhost
113  ? min((lhs + point_to_ghost(bc.has_extra())), rhs)
114  : GhostData(IntVec(0, 0, 0),
115  bc.has_extra()))
116  - point_to_ghost(bc.has_extra()));
117  };
118 
119  template<typename Type1, typename Type2>
121 
122  template<typename T>
123  struct NeboFieldCheck<SpatialOps::SpatialField<SpatialOps::SingleValue, T>,
124  SpatialOps::SpatialField<SpatialOps::SingleValue, T> > {};
125 
126  template<typename Type>
127  struct NeboFieldCheck<Type, Type> { Type typedef Result; };
128 
129  inline IntVec nebo_find_partition(IntVec const & extent,
130  int const thread_count) {
131  int x = 1;
132  int y = 1;
133  int z = 1;
134 
135  if(thread_count <= extent[2]) { z = thread_count; }
136  else if(thread_count <= extent[1]) { y = thread_count; }
137  else if(thread_count <= extent[0]) { x = thread_count; };
138 
139  return IntVec(x, y, z);
140  };
141 
142  inline int nebo_partition_count(IntVec const & split) {
143  return split[0] * split[1] * split[2];
144  };
145 
146  inline void nebo_set_up_extents(IntVec const & current,
147  IntVec const & split,
148  GhostData & localLimits,
149  GhostData const & limits) {
150 
151  //full extent indexed from 0 rather than DLow (which is nonpositive - zero or below)
152  IntVec const fullExtent(limits.get_plus(0) - limits.get_minus(0),
153  limits.get_plus(1) - limits.get_minus(1),
154  limits.get_plus(2) - limits.get_minus(2));
155 
156  //sanity checks
157 # ifndef NDEBUG
158  for( size_t i=0; i<3; ++i ){
159  assert( fullExtent[i] >= split[i] );
160  assert( split[i] > 0 );
161  assert( current[i] < split[i] );
162  assert( current[i] >= 0 );
163  }
164 # endif
165 
166  //extent of a partition
167  IntVec const stdExtent = fullExtent / split;
168 
169  //number of partitions with an extra cell (to cover what is not covered by stdExtent)
170  IntVec const nExtra(fullExtent[0] % split[0],
171  fullExtent[1] % split[1],
172  fullExtent[2] % split[2]);
173 
174  //number of previous paritions with an extra cell
175  IntVec const pastExtra(current[0] < nExtra[0] ? current[0] : nExtra[0],
176  current[1] < nExtra[1] ? current[1] : nExtra[1],
177  current[2] < nExtra[2] ? current[2] : nExtra[2]);
178 
179  //does current partition have an extra cell
180  IntVec const currentExtra(current[0] < nExtra[0] ? 1 : 0,
181  current[1] < nExtra[1] ? 1 : 0,
182  current[2] < nExtra[2] ? 1 : 0);
183 
184  //calculate current partition's low and high
185  IntVec const low = stdExtent * current + pastExtra;
186  IntVec const high = low + stdExtent + currentExtra;
187 
188  //shift back to indexing from DLow rather than zero
189  localLimits = GhostData(low[0] + limits.get_minus(0),
190  high[0] + limits.get_minus(0),
191  low[1] + limits.get_minus(1),
192  high[1] + limits.get_minus(1),
193  low[2] + limits.get_minus(2),
194  high[2] + limits.get_minus(2));
195  };
196 
197  inline IntVec nebo_next_partition(IntVec const & current,
198  IntVec const & split) {
199  IntVec result;
200 
201  if(current[2] < split[2] - 1)
202  result = IntVec(current[0], current[1], 1 + current[2]);
203  else if(current[1] < split[1] - 1)
204  result = IntVec(current[0], 1 + current[1], 0);
205  else result = IntVec(1 + current[0], 0, 0);
206 
207  return result;
208  };
209 
210  template<typename Operand, typename FieldType>
211  struct NeboExpression {
212  public:
213  FieldType typedef field_type;
214 
215  Operand typedef Expression;
216 
217  NeboExpression(Operand const & given)
218  : expr_(given)
219  {}
220 
221  inline Operand const & expr(void) const { return expr_; }
222 
223  private:
224  Operand expr_;
225  };
226 
227  template<typename Operand, typename T>
229  public:
231 
232  Operand typedef Expression;
233 
234  NeboSingleValueExpression(Operand const & given)
235  : expr_(given)
236  {}
237 
238  inline Operand const & expr(void) const { return expr_; }
239 
240  private:
241  Operand expr_;
242  };
243 
244  template<typename Operand, typename FieldType>
246  public:
247  FieldType typedef field_type;
248 
249  Operand typedef Expression;
250 
251  NeboBooleanExpression(Operand const & given)
252  : expr_(given)
253  {}
254 
255  inline Operand const & expr(void) const { return expr_; }
256 
257  private:
258  Operand expr_;
259  };
260 
261  template<typename Operand, typename T>
263  public:
265 
266  Operand typedef Expression;
267 
268  NeboBooleanSingleValueExpression(Operand const & given)
269  : expr_(given)
270  {}
271 
272  inline Operand const & expr(void) const { return expr_; }
273 
274  private:
275  Operand expr_;
276  };
277 
313  {
314  public:
315  NeboOptionalArg (int * idx, double * mappedValueRef)
316  : outerIndex_(idx), mappedValueRef_(mappedValueRef)
317  {}
318 
319  inline int * outerIndex (void) const { return outerIndex_; }
320 
321  inline void setOuterIndex (const int x, const int y, const int z) {
322  outerIndex_[0] = x;
323  outerIndex_[1] = y;
324  outerIndex_[2] = z;
325  }
326 
327  inline NeboOptionalArg& setMappedValueRef (double * mappedValue) {
328  mappedValueRef_ = mappedValue;
329 
330  return *this;
331  }
332 
333  inline double * mappedValueRef (void) { return mappedValueRef_; }
334 
335  private:
336  int * const outerIndex_;
337  double * mappedValueRef_;
338  };
339 
340  /* Modes: */
341  struct Initial;
342 # ifdef ENABLE_THREADS
343  struct Resize;
344 # endif
345  /* ENABLE_THREADS */
346  struct SeqWalk;
347 # ifdef __CUDACC__
348  struct GPUWalk;
349 # endif
350  /* __CUDACC__ */
351  } /* SpatialOps */
352 
353 #endif
354 /* NEBO_BASIC_H */
355 
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
Parameter used to initialize Nebo expression operands across modes. The argument only stores informat...
Definition: NeboBasic.h:312
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.