interpolate_3rd_order.h
Go to the documentation of this file.
1 /*
2 This file is part of the Ristra portage project.
3 Please see the license file at the root of this repository, or at:
4  https://github.com/laristra/portage/blob/master/LICENSE
5 */
6 
7 #ifndef SRC_INTERPOLATE_INTERPOLATE_3RD_ORDER_H_
8 #define SRC_INTERPOLATE_INTERPOLATE_3RD_ORDER_H_
9 
10 #include <cassert>
11 #include <stdexcept>
12 #include <algorithm>
13 #include <string>
14 #include <iostream>
15 #include <utility>
16 #include <vector>
17 
20 #include "portage/driver/parts.h"
21 
22 namespace Portage {
23 
45 template<int D, Entity_kind on_what,
46  typename SourceMeshType,
47  typename TargetMeshType,
48  typename SourceStateType,
49  typename TargetStateType = SourceStateType>
51 
52  public:
61  Interpolate_3rdOrder(SourceMeshType const & source_mesh,
62  TargetMeshType const & target_mesh,
63  SourceStateType const & source_state,
64  NumericTolerances_t num_tols) :
65  source_mesh_(source_mesh),
66  target_mesh_(target_mesh),
67  source_state_(source_state),
68  interp_var_name_("VariableNameNotSet"),
69  source_vals_(nullptr),
70  num_tols_(num_tols) {}
71 
73  // Interpolate_3rdOrder(const Interpolate_3rdOrder &) = delete;
74 
77 
79  ~Interpolate_3rdOrder() = default;
80 
81 
83 
84  void set_interpolation_variable(std::string const & interp_var_name,
85  Limiter_type limiter_type = NOLIMITER,
86  Boundary_Limiter_type boundary_limiter_type = BND_NOLIMITER,
87  Portage::vector<Vector<D>>* gradients = nullptr) {
88  interp_var_name_ = interp_var_name;
89 
90  // Extract the field data from the statemanager
91 
92  source_state_.mesh_get_data(on_what, interp_var_name, &source_vals_);
93 
94  // Compute the limited quadfits for the field
95 
97  limqfit(source_mesh_, source_state_, interp_var_name,
98  limiter_type, boundary_limiter_type);
99 
100 
101  int nentities = source_mesh_.end(on_what)-source_mesh_.begin(on_what);
102  quadfits_.resize(nentities);
103 
104  // call transform functor to take the values of the variable on
105  // the cells and compute a "limited" quadfit of the field on the
106  // cells (for transform definition, see portage.h)
107 
108  // Even though we defined Portage::transform (to be
109  // thrust::transform or boost::transform) in portage.h, the
110  // compiler is not able to disambiguate this call and is getting
111  // confused. So we will explicitly state that this is Portage::transform
112 
113  Portage::transform(source_mesh_.begin(on_what), source_mesh_.end(on_what),
114  quadfits_.begin(), limqfit);
115  }
116 
135  double operator() (int const targetCellID,
136  std::vector<Weights_t> const & sources_and_weights) const {
137  // not implemented for all types - see specialization for cells and nodes
138 
139  std::cerr << "Interpolation operator not implemented for this entity type"
140  << std::endl;
141  return 0.;
142  }
143 
144  constexpr static int order = 3;
145 
146  private:
147  SourceMeshType const & source_mesh_;
148  TargetMeshType const & target_mesh_;
149  SourceStateType const & source_state_;
150  std::string interp_var_name_;
151  double const * source_vals_;
152  NumericTolerances_t num_tols_;
153 
154  // Portage::vector is generalization of std::vector and
155  // Wonton::Vector<D*(D+3)/2> is a geometric vector
156  Portage::vector<Vector<D*(D+3)/2>> quadfits_;
157 };
158 
159 
160 
161 
163 
169 template<int D,
170  typename SourceMeshType,
171  typename TargetMeshType,
172  typename SourceStateType,
173  typename TargetStateType>
175  D, Entity_kind::CELL,
176  SourceMeshType, TargetMeshType,
177  SourceStateType, TargetStateType> {
178 
179  // useful aliases
180  using Parts = PartPair<
181  D, SourceMeshType, SourceStateType,
182  TargetMeshType, TargetStateType
183  >;
184 
185  public:
186  Interpolate_3rdOrder(SourceMeshType const & source_mesh,
187  TargetMeshType const & target_mesh,
188  SourceStateType const & source_state,
189  NumericTolerances_t num_tols,
190  const Parts* const parts = nullptr) :
191  source_mesh_(source_mesh),
192  target_mesh_(target_mesh),
193  source_state_(source_state),
194  interp_var_name_("VariableNameNotSet"),
195  source_vals_(nullptr),
196  num_tols_(num_tols),
197  parts_(parts) {}
198 
199 
201 
202  void set_interpolation_variable(std::string const & interp_var_name,
203  Limiter_type limiter_type = NOLIMITER,
204  Boundary_Limiter_type boundary_limiter_type = BND_NOLIMITER,
205  Portage::vector<Vector<D>>* gradients = nullptr) {
206 
207  interp_var_name_ = interp_var_name;
208 
209  // Extract the field data from the statemanager
210 
211  source_state_.mesh_get_data(Entity_kind::CELL, interp_var_name, &source_vals_);
212 
213  // Compute the limited quadfits for the field
214 
216  limqfit(source_mesh_, source_state_, interp_var_name_, limiter_type, boundary_limiter_type);
217 
218  int nentities = source_mesh_.end(Entity_kind::CELL)-source_mesh_.begin(Entity_kind::CELL);
219  quadfits_.resize(nentities);
220 
221  // call transform functor to take the values of the variable on
222  // the cells and compute a "limited" quadfit of the field on the
223  // cells (for transform definition, see portage.h)
224 
225  // Even though we defined Portage::transform (to be
226  // thrust::transform or boost::transform) in portage.h, the
227  // compiler is not able to disambiguate this call and is getting
228  // confused. So we will explicitly state that this is Portage::transform
229 
230  Portage::transform(source_mesh_.begin(Entity_kind::CELL), source_mesh_.end(Entity_kind::CELL),
231  quadfits_.begin(), limqfit);
232  }
233 
235  // Interpolate_3rdOrder(const Interpolate_3rdOrder &) = delete;
236 
239 
241  ~Interpolate_3rdOrder() = default;
242 
243 
267  double operator() (int const targetCellID,
268  std::vector<Weights_t> const & sources_and_weights) const {
269 
270  int nsrccells = sources_and_weights.size();
271  if (!nsrccells) {
272 #ifdef DEBUG
273  std::cerr << "WARNING: No source cells contribute to target cell." <<
274  std::endl;
275 #endif
276  return 0.0;
277  }
278 
279  double totalval = 0.0;
280 
281  // contribution of the source cell is its field value weighted by
282  // its "weight" (in this case, its 0th moment/area/volume)
283 
285 
286  for (int j = 0; j < nsrccells; ++j) {
287  int srccell = sources_and_weights[j].entityID;
288  // int N = D*(D+3)/2;
289  std::vector<double> xsect_weights = sources_and_weights[j].weights;
290  double xsect_volume = xsect_weights[0];
291 
292  if (xsect_volume <= num_tols_.min_absolute_volume)
293  continue; // no intersection
294 
295  Point<D> srccell_centroid;
296  source_mesh_.cell_centroid(srccell, &srccell_centroid);
297 
298  Point<D> xsect_centroid;
299  for (int i = 0; i < D; ++i)
300  xsect_centroid[i] = xsect_weights[1+i]/xsect_volume; // (1st moment)/vol
301 
302  Vector<D*(D+3)/2> quadfit = quadfits_[srccell];
303  Vector<D> vec = xsect_centroid - srccell_centroid;
304  Vector<D*(D+3)/2> dvec;
305  for (int j = 0; j < D; ++j) {
306  int j1 = D;
307  dvec[j] = vec[j];
308  // Add the quadratic terms
309  for (int k = 0; k <= j; ++k) {
310  dvec[j1] = dvec[k]*dvec[j];
311  j1 += 1;
312  //dvec[D+j+k] = dvec[k]*dvec[j];
313  }
314  }
315  double val = source_vals_[srccell] + dot(quadfit,dvec);
316  val *= xsect_volume;
317  totalval += val;
318  }
319 
320  // Normalize the value by sum of all the 0th weights (which is the
321  // same as the total volume of the source cell)
322 
323  totalval /= target_mesh_.cell_volume(targetCellID);
324 
325  return totalval;
326  }
327 
328  constexpr static int order = 3;
329 
330  private:
331  SourceMeshType const & source_mesh_;
332  TargetMeshType const & target_mesh_;
333  SourceStateType const & source_state_;
334  std::string interp_var_name_;
335  double const * source_vals_;
336  NumericTolerances_t num_tols_;
337  Parts const* parts_;
338 
339  // Portage::vector is generalization of std::vector and
340  // Wonton::Vector<D> is a geometric vector
341  Portage::vector<Vector<D*(D+3)/2>> quadfits_;
342 };
343 
345 
346 
347 
348 
350 
356 template<int D,
357  typename SourceMeshType,
358  typename TargetMeshType,
359  typename SourceStateType,
360  typename TargetStateType>
362  D, Entity_kind::NODE,
363  SourceMeshType, TargetMeshType,
364  SourceStateType, TargetStateType> {
365 
366  public:
367  Interpolate_3rdOrder(SourceMeshType const & source_mesh,
368  TargetMeshType const & target_mesh,
369  SourceStateType const & source_state,
370  NumericTolerances_t num_tols) :
371  source_mesh_(source_mesh),
372  target_mesh_(target_mesh),
373  source_state_(source_state),
374  interp_var_name_("VariableNameNotSet"),
375  source_vals_(nullptr),
376  num_tols_(num_tols) {}
377 
379  // Interpolate_3rdOrder(const Interpolate_3rdOrder &) = delete;
380 
383 
385  ~Interpolate_3rdOrder() = default;
386 
387 
389 
390  void set_interpolation_variable(std::string const & interp_var_name,
391  Limiter_type limiter_type = NOLIMITER,
392  Boundary_Limiter_type boundary_limiter_type = BND_NOLIMITER,
393  Portage::vector<Vector<D>>* gradients = nullptr) {
394 
395  interp_var_name_ = interp_var_name;
396 
397  // Extract the field data from the statemanager
398 
399  source_state_.mesh_get_data(Entity_kind::NODE, interp_var_name, &source_vals_);
400 
401  // Compute the limited quadfits for the field
402 
404  limqfit(source_mesh_, source_state_, interp_var_name, limiter_type, boundary_limiter_type);
405 
406  int nentities = source_mesh_.end(Entity_kind::NODE)-source_mesh_.begin(Entity_kind::NODE);
407  quadfits_.resize(nentities);
408 
409  // call transform functor to take the values of the variable on
410  // the cells and compute a "limited" quadfit of the field on the
411  // cells (for transform definition, see portage.h)
412 
413  // Even though we defined Portage::transform (to be
414  // thrust::transform or boost::transform) in portage.h, the
415  // compiler is not able to disambiguate this call and is getting
416  // confused. So we will explicitly state that this is Portage::transform
417 
418  Portage::transform(source_mesh_.begin(Entity_kind::NODE), source_mesh_.end(Entity_kind::NODE),
419  quadfits_.begin(), limqfit);
420  }
421 
422 
451  double operator() (const int targetNodeID,
452  std::vector<Weights_t> const & sources_and_weights) const {
453 
454  int nsrcnodes = sources_and_weights.size();
455  if (!nsrcnodes) {
456 #ifdef DEBUG
457  std::cerr << "WARNING: No source nodes contribute to target node." <<
458  std::endl;
459 #endif
460  return 0.0;
461  }
462 
463  double totalval = 0.0;
464 
465  // contribution of the source cell is its field value weighted by
466  // its "weight" (in this case, its 0th moment/area/volume)
467 
469 
470  for (int j = 0; j < nsrcnodes; ++j) {
471  int srcnode = sources_and_weights[j].entityID;
472  std::vector<double> xsect_weights = sources_and_weights[j].weights;
473  double xsect_volume = xsect_weights[0];
474 
475  if (xsect_volume <= num_tols_.min_absolute_volume)
476  continue; // no intersection
477 
478  // note: here we are getting the node coord, not the centroid of
479  // the dual cell
480  Point<D> srcnode_coord;
481  source_mesh_.node_get_coordinates(srcnode, &srcnode_coord);
482 
483  Point<D> xsect_centroid;
484  for (int i = 0; i < D; ++i)
485  // (1st moment)/(vol)
486  xsect_centroid[i] = xsect_weights[1+i]/xsect_volume;
487 
488  Vector<D*(D+3)/2> quadfit = quadfits_[srcnode];
489  Vector<D> vec = xsect_centroid - srcnode_coord;
490  Vector<D*(D+3)/2> dvec;
491  for (int j = 0; j < D; ++j) {
492  int j1 = D;
493  dvec[j] = vec[j];
494  // Add the quadratic terms
495  for (int k = 0; k <= j; ++k) {
496  dvec[j1] = dvec[k]*dvec[j];
497  j1 += 1;
498  // dvec[D+j+k] = dvec[k]*dvec[j];
499  }
500  }
501  double val = source_vals_[srcnode] + dot(quadfit,dvec);
502  val *= xsect_volume;
503  totalval += val;
504  }
505 
506  // Normalize the value by volume of the target dual cell
507 
508  totalval /= target_mesh_.dual_cell_volume(targetNodeID);
509 
510  return totalval;
511  }
512 
513  constexpr static int order = 3;
514 
515  private:
516  SourceMeshType const & source_mesh_;
517  TargetMeshType const & target_mesh_;
518  SourceStateType const & source_state_;
519  std::string interp_var_name_;
520  double const * source_vals_;
521  NumericTolerances_t num_tols_;
522 
523  // Portage::vector is generalization of std::vector and
524  // Wonton::Vector<D> is a geometric vector
525  Portage::vector<Vector<D*(D+3)/2>> quadfits_;
526 };
527 } // namespace Portage
528 
529 #endif // SRC_INTERPOLATE_INTERPOLATE_3RD_ORDER_H_
Boundary_Limiter_type
Boundary limiter type.
Definition: portage.h:91
std::vector< T > vector
Definition: portage.h:238
OutputIterator transform(InputIterator first, InputIterator last, OutputIterator result, UnaryFunction op)
Definition: portage.h:250
Interpolate_3rdOrder does a 3rd order interpolation of scalars.
Definition: interpolate_3rd_order.h:50
Intersection and other tolerances to handle tiny values.
Definition: portage.h:152
Interpolate_3rdOrder(SourceMeshType const &source_mesh, TargetMeshType const &target_mesh, SourceStateType const &source_state, NumericTolerances_t num_tols, const Parts *const parts=nullptr)
Definition: interpolate_3rd_order.h:186
static constexpr int order
Definition: interpolate_3rd_order.h:144
void set_interpolation_variable(std::string const &interp_var_name, Limiter_type limiter_type=NOLIMITER, Boundary_Limiter_type boundary_limiter_type=BND_NOLIMITER, Portage::vector< Vector< D >> *gradients=nullptr)
Set the name of the interpolation variable and the limiter type.
Definition: interpolate_3rd_order.h:84
Interpolate_3rdOrder(SourceMeshType const &source_mesh, TargetMeshType const &target_mesh, SourceStateType const &source_state, NumericTolerances_t num_tols)
Constructor.
Definition: interpolate_3rd_order.h:61
Manages source and target sub-meshes for part-by-part remap.
Interpolate_3rdOrder(SourceMeshType const &source_mesh, TargetMeshType const &target_mesh, SourceStateType const &source_state, NumericTolerances_t num_tols)
Definition: interpolate_3rd_order.h:367
Definition: portage.h:85
void set_interpolation_variable(std::string const &interp_var_name, Limiter_type limiter_type=NOLIMITER, Boundary_Limiter_type boundary_limiter_type=BND_NOLIMITER, Portage::vector< Vector< D >> *gradients=nullptr)
Set the name of the interpolation variable and the limiter type.
Definition: interpolate_3rd_order.h:202
Manages source and target sub-meshes for part-by-part remap. It detects boundaries mismatch and provi...
Definition: parts.h:234
Limiter_type
Limiter type.
Definition: portage.h:85
void set_interpolation_variable(std::string const &interp_var_name, Limiter_type limiter_type=NOLIMITER, Boundary_Limiter_type boundary_limiter_type=BND_NOLIMITER, Portage::vector< Vector< D >> *gradients=nullptr)
Set the name of the interpolation variable and the limiter type.
Definition: interpolate_3rd_order.h:390
Definition: coredriver.h:42
Compute limited quadfit of a field or components of a field.
Definition: quadfit.h:43
~Interpolate_3rdOrder()=default
Destructor.
Interpolate_3rdOrder & operator=(const Interpolate_3rdOrder &)=delete
Copy constructor (disabled)
double operator()(int const targetCellID, std::vector< Weights_t > const &sources_and_weights) const
Functor to do the actual interpolate calculation.
Definition: interpolate_3rd_order.h:135
Definition: portage.h:91