SpatialOps
NeboBasic.h
1 /*
2  * Copyright (c) 2014 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  inline GhostData calculate_actual_ghost(bool const useGhost,
65  GhostData const & lhs,
66  BoundaryCellInfo const & bc,
67  GhostData const & rhs) {
68  if(bc.has_bc(0) && rhs.get_plus(0) < bc.has_extra(0)) {
69  std::ostringstream msg;
70  msg << "Nebo error in " << "Nebo Ghost Checking" << ":\n";
71  msg << "Not enough valid extra cells to validate all interior ";
72  msg << "cells in the X direction";
73  msg << "\n";
74  msg << "\t - " << __FILE__ << " : " << __LINE__;
75  throw(std::runtime_error(msg.str()));;
76  };
77 
78  if(bc.has_bc(1) && rhs.get_plus(1) < bc.has_extra(1)) {
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 Y direction";
83  msg << "\n";
84  msg << "\t - " << __FILE__ << " : " << __LINE__;
85  throw(std::runtime_error(msg.str()));;
86  };
87 
88  if(bc.has_bc(2) && rhs.get_plus(2) < bc.has_extra(2)) {
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 Z direction";
93  msg << "\n";
94  msg << "\t - " << __FILE__ << " : " << __LINE__;
95  throw(std::runtime_error(msg.str()));;
96  };
97 
98  return ((useGhost
99  ? min((lhs + point_to_ghost(bc.has_extra())), rhs)
100  : GhostData(IntVec(0, 0, 0),
101  bc.has_extra()))
102  - point_to_ghost(bc.has_extra()));
103  };
104 
105  template<typename Type1, typename Type2>
107 
108  template<typename T>
109  struct NeboFieldCheck<SpatialOps::SpatialField<SpatialOps::SingleValue, T>,
110  SpatialOps::SpatialField<SpatialOps::SingleValue, T> > {};
111 
112  template<typename Type>
113  struct NeboFieldCheck<Type, Type> { Type typedef Result; };
114 
115  inline IntVec nebo_find_partition(IntVec const & extent,
116  int const thread_count) {
117  int x = 1;
118  int y = 1;
119  int z = 1;
120 
121  if(thread_count <= extent[2]) { z = thread_count; }
122  else if(thread_count <= extent[1]) { y = thread_count; }
123  else if(thread_count <= extent[0]) { x = thread_count; };
124 
125  return IntVec(x, y, z);
126  };
127 
128  inline int nebo_partition_count(IntVec const & split) {
129  return split[0] * split[1] * split[2];
130  };
131 
132  inline void nebo_set_up_extents(IntVec const & current,
133  IntVec const & split,
134  GhostData & localLimits,
135  GhostData const & limits) {
136 
137  //full extent indexed from 0 rather than DLow (which is nonpositive - zero or below)
138  IntVec const fullExtent(limits.get_plus(0) - limits.get_minus(0),
139  limits.get_plus(1) - limits.get_minus(1),
140  limits.get_plus(2) - limits.get_minus(2));
141 
142  //sanity checks
143 # ifndef NDEBUG
144  for( size_t i=0; i<3; ++i ){
145  assert( fullExtent[i] >= split[i] );
146  assert( split[i] > 0 );
147  assert( current[i] < split[i] );
148  assert( current[i] >= 0 );
149  }
150 # endif
151 
152  //extent of a partition
153  IntVec const stdExtent = fullExtent / split;
154 
155  //number of partitions with an extra cell (to cover what is not covered by stdExtent)
156  IntVec const nExtra(fullExtent[0] % split[0],
157  fullExtent[1] % split[1],
158  fullExtent[2] % split[2]);
159 
160  //number of previous paritions with an extra cell
161  IntVec const pastExtra(current[0] < nExtra[0] ? current[0] : nExtra[0],
162  current[1] < nExtra[1] ? current[1] : nExtra[1],
163  current[2] < nExtra[2] ? current[2] : nExtra[2]);
164 
165  //does current partition have an extra cell
166  IntVec const currentExtra(current[0] < nExtra[0] ? 1 : 0,
167  current[1] < nExtra[1] ? 1 : 0,
168  current[2] < nExtra[2] ? 1 : 0);
169 
170  //calculate current partition's low and high
171  IntVec const low = stdExtent * current + pastExtra;
172  IntVec const high = low + stdExtent + currentExtra;
173 
174  //shift back to indexing from DLow rather than zero
175  localLimits = GhostData(low[0] + limits.get_minus(0),
176  high[0] + limits.get_minus(0),
177  low[1] + limits.get_minus(1),
178  high[1] + limits.get_minus(1),
179  low[2] + limits.get_minus(2),
180  high[2] + limits.get_minus(2));
181  };
182 
183  inline IntVec nebo_next_partition(IntVec const & current,
184  IntVec const & split) {
185  IntVec result;
186 
187  if(current[2] < split[2] - 1)
188  result = IntVec(current[0], current[1], 1 + current[2]);
189  else if(current[1] < split[1] - 1)
190  result = IntVec(current[0], 1 + current[1], 0);
191  else result = IntVec(1 + current[0], 0, 0);
192 
193  return result;
194  };
195 
196  template<typename Operand, typename FieldType>
197  struct NeboExpression {
198  public:
199  FieldType typedef field_type;
200 
201  Operand typedef Expression;
202 
203  NeboExpression(Operand const & given)
204  : expr_(given)
205  {}
206 
207  inline Operand const & expr(void) const { return expr_; }
208 
209  private:
210  Operand expr_;
211  };
212 
213  template<typename Operand, typename T>
215  public:
217 
218  Operand typedef Expression;
219 
220  NeboSingleValueExpression(Operand const & given)
221  : expr_(given)
222  {}
223 
224  inline Operand const & expr(void) const { return expr_; }
225 
226  private:
227  Operand expr_;
228  };
229 
230  template<typename Operand, typename FieldType>
232  public:
233  FieldType typedef field_type;
234 
235  Operand typedef Expression;
236 
237  NeboBooleanExpression(Operand const & given)
238  : expr_(given)
239  {}
240 
241  inline Operand const & expr(void) const { return expr_; }
242 
243  private:
244  Operand expr_;
245  };
246 
247  template<typename Operand, typename T>
249  public:
251 
252  Operand typedef Expression;
253 
254  NeboBooleanSingleValueExpression(Operand const & given)
255  : expr_(given)
256  {}
257 
258  inline Operand const & expr(void) const { return expr_; }
259 
260  private:
261  Operand expr_;
262  };
263 
264  /* Modes: */
265  struct Initial;
266 # ifdef ENABLE_THREADS
267  struct Resize;
268 # endif
269  /* ENABLE_THREADS */
270  struct SeqWalk;
271 # ifdef __CUDACC__
272  struct GPUWalk;
273 # endif
274  /* __CUDACC__ */
275  } /* SpatialOps */
276 
277 #endif
278 /* NEBO_BASIC_H */
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