interpolate_1st_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 PORTAGE_INTERPOLATE_INTERPOLATE_1ST_ORDER_H_
8 #define PORTAGE_INTERPOLATE_INTERPOLATE_1ST_ORDER_H_
9 
10 
11 #include <cassert>
12 #include <string>
13 #include <iostream>
14 #include <utility>
15 #include <vector>
16 #include <cmath>
17 
18 // portage includes
21 #include "portage/driver/parts.h"
22 
23 // wonton includes
24 #include "wonton/support/CoordinateSystem.h"
25 
26 #ifdef HAVE_TANGRAM
27 #include "tangram/driver/driver.h"
28 #include "tangram/driver/CellMatPoly.h"
29 #include "tangram/support/MatPoly.h"
30 #endif
31 
32 namespace Portage {
33 
88 template<int D,
89  Entity_kind on_what,
90  typename SourceMeshType,
91  typename TargetMeshType,
92  typename SourceStateType,
93  typename TargetStateType,
94  typename T,
95  template<class, int, class, class>
96  class InterfaceReconstructorType = DummyInterfaceReconstructor,
97  class Matpoly_Splitter = void,
98  class Matpoly_Clipper = void,
99  class CoordSys = Wonton::DefaultCoordSys
100  >
102 
103 #ifdef HAVE_TANGRAM
104  using InterfaceReconstructor =
105  Tangram::Driver<InterfaceReconstructorType, D, SourceMeshType,
106  Matpoly_Splitter, Matpoly_Clipper>;
107 #endif
108 
109  public:
110 
111  // Constructor with interface reconstructor
112 #ifdef HAVE_TANGRAM
113  Interpolate_1stOrder(SourceMeshType const & source_mesh,
114  TargetMeshType const & target_mesh,
115  SourceStateType const & source_state,
116  NumericTolerances_t num_tols,
117  std::shared_ptr<InterfaceReconstructor> ir) :
118  source_mesh_(source_mesh),
119  target_mesh_(target_mesh),
120  source_state_(source_state),
121  interp_var_name_("VariableNameNotSet"),
122  source_vals_(nullptr),
123  num_tols_(num_tols),
124  interface_reconstructor_(ir) {}
125 #endif
126 
137  Interpolate_1stOrder(SourceMeshType const & source_mesh,
138  TargetMeshType const & target_mesh,
139  SourceStateType const & source_state,
140  NumericTolerances_t num_tols) :
141  source_mesh_(source_mesh),
142  target_mesh_(target_mesh),
143  source_state_(source_state),
144  interp_var_name_("VariableNameNotSet"),
145  source_vals_(nullptr),
146  num_tols_(num_tols) {}
147 
148 
150  // Interpolate_1stOrder(const Interpolate_1stOrder &) = delete;
151 
153  // Interpolate_1stOrder & operator = (const Interpolate_1stOrder &) = delete;
154 
156  ~Interpolate_1stOrder() = default;
157 
159 
160  void set_material(int m) {
161  matid_ = m;
162  } // set_material
163 
165 
166  // Even though 1st order accurate interpolation does not require
167  // limiters and only higher order ones do, we need to have the
168  // limiter_type as an argument. This is because the templated driver
169  // does not know whether its being called with 1st order or higher
170  // order interpolators and so all interpolators need to have a
171  // uniform interface
172 
173  void set_interpolation_variable(std::string const & interp_var_name,
174  Portage::vector<Wonton::Vector<D>>* gradients = nullptr) {
175  interp_var_name_ = interp_var_name;
176  field_type_ = source_state_.field_type(Entity_kind::CELL, interp_var_name);
177  if (field_type_ == Field_type::MESH_FIELD)
178  source_state_.mesh_get_data(Entity_kind::CELL, interp_var_name,
179  &source_vals_);
180  else
181  source_state_.mat_get_celldata(interp_var_name, matid_, &source_vals_);
182  } // set_interpolation_variable
183 
200  T operator() (int const targetEntityId,
201  std::vector<Weights_t> const & sources_and_weights) const {
202  std::cerr << "Interpolation operator not implemented for this entity type"
203  << std::endl;
204  return T(0.0);
205  }
206 
207  constexpr static int order = 1;
208 
209  private:
210  SourceMeshType const & source_mesh_;
211  TargetMeshType const & target_mesh_;
212  SourceStateType const & source_state_;
213  std::string interp_var_name_;
214  T const * source_vals_;
215  int matid_ = 0;
216  Field_type field_type_ = Field_type::UNKNOWN_TYPE_FIELD;
217  NumericTolerances_t num_tols_;
218 #ifdef HAVE_TANGRAM
219  std::shared_ptr<InterfaceReconstructor> interface_reconstructor_;
220 #endif
221 }; // interpolate_1st_order base
222 
223 
224 
226 
230 template<int D,
231  typename SourceMeshType,
232  typename TargetMeshType,
233  typename SourceStateType,
234  typename TargetStateType,
235  typename T,
236  template<class, int, class, class> class InterfaceReconstructorType,
237  class Matpoly_Splitter,
238  class Matpoly_Clipper,
239  class CoordSys>
241  D, Entity_kind::CELL,
242  SourceMeshType, TargetMeshType,
243  SourceStateType, TargetStateType,
244  T,
245  InterfaceReconstructorType,
246  Matpoly_Splitter, Matpoly_Clipper, CoordSys> {
247 
248  // useful aliases
249  using Parts = PartPair<D,
250  SourceMeshType, SourceStateType,
251  TargetMeshType, TargetStateType
252  >;
253 
254 #ifdef HAVE_TANGRAM
255  using InterfaceReconstructor =
256  Tangram::Driver<InterfaceReconstructorType, D, SourceMeshType,
257  Matpoly_Splitter, Matpoly_Clipper>;
258 #endif
259 
260  public:
261 
262 #ifdef HAVE_TANGRAM
263  Interpolate_1stOrder(SourceMeshType const & source_mesh,
264  TargetMeshType const & target_mesh,
265  SourceStateType const & source_state,
266  NumericTolerances_t num_tols,
267  std::shared_ptr<InterfaceReconstructor> ir,
268  const Parts* const parts = nullptr) :
269  source_mesh_(source_mesh),
270  target_mesh_(target_mesh),
271  source_state_(source_state),
272  interp_var_name_("VariableNameNotSet"),
273  source_vals_(nullptr),
274  num_tols_(num_tols),
275  interface_reconstructor_(ir),
276  parts_(parts) {}
277 #endif
278 
286  Interpolate_1stOrder(SourceMeshType const & source_mesh,
287  TargetMeshType const & target_mesh,
288  SourceStateType const & source_state,
289  NumericTolerances_t num_tols,
290  const Parts* const parts = nullptr) :
291  source_mesh_(source_mesh),
292  target_mesh_(target_mesh),
293  source_state_(source_state),
294  interp_var_name_("VariableNameNotSet"),
295  source_vals_(nullptr),
296  num_tols_(num_tols),
297  parts_(parts) {}
298 
299 
301  // Interpolate_1stOrder(const Interpolate_1stOrder &) = delete;
302 
304  // Interpolate_1stOrder & operator = (const Interpolate_1stOrder &) = delete;
305 
307  ~Interpolate_1stOrder() = default;
308 
309 
311 
312  void set_material(int m) {
313  matid_ = m;
314  } // set_material
315 
317 
318 
319  // Even though 1st order accurate interpolation does not require
320  // limiters and only higher order ones do, we need to have the
321  // limiter_type as an argument. This is because the templated driver
322  // does not know whether its being called with 1st order or higher
323  // order interpolators and so all interpolators need to have a
324  // uniform interface
325 
326  void set_interpolation_variable(std::string const & interp_var_name,
327  Portage::vector<Wonton::Vector<D>>* gradients = nullptr) {
328  interp_var_name_ = interp_var_name;
329  field_type_ = source_state_.field_type(Entity_kind::CELL, interp_var_name);
330  if (field_type_ == Field_type::MESH_FIELD)
331  source_state_.mesh_get_data(Entity_kind::CELL, interp_var_name,
332  &source_vals_);
333  else
334  source_state_.mat_get_celldata(interp_var_name, matid_, &source_vals_);
335  } // set_interpolation_variable
336 
337 
354  T operator() (int const targetCellID,
355  std::vector<Weights_t> const & sources_and_weights) const
356  {
357  int nsrccells = sources_and_weights.size();
358  if (!nsrccells) return T(0.0);
359 
360  // contribution of the source cell is its field value weighted by
361  // its "weight" (in this case, its 0th moment/area/volume)
362 
363  T val(0.0);
364  double wtsum0 = 0.0;
365 
366  int nsummed = 0;
367  if (field_type_ == Field_type::MESH_FIELD) {
368  for (auto const& wt : sources_and_weights) {
369  int srccell = wt.entityID;
370  std::vector<double> pair_weights = wt.weights;
371  if (fabs(pair_weights[0]) < num_tols_.min_absolute_volume)
372  continue; // skip small intersections
373  val += source_vals_[srccell] * pair_weights[0];
374  wtsum0 += pair_weights[0];
375  nsummed++;
376  }
377  } else if (field_type_ == Field_type::MULTIMATERIAL_FIELD) {
378  for (auto const& wt : sources_and_weights) {
379  int srccell = wt.entityID;
380  std::vector<double> pair_weights = wt.weights;
381  if (fabs(pair_weights[0]) < num_tols_.min_absolute_volume)
382  continue; // skip small intersections
383  int matcell = source_state_.cell_index_in_material(srccell, matid_);
384  val += source_vals_[matcell] * pair_weights[0]; // 1st order
385  wtsum0 += pair_weights[0];
386  nsummed++;
387  }
388  }
389 
390  // Normalize the value by the volume of the intersection of the
391  // target cells with the source mesh. This will do the right thing
392  // for single-material and multi-material remap (conservative and
393  // constant preserving) if there is NO mismatch between source and
394  // target mesh boundaries. IF THERE IS A MISMATCH, THIS WILL
395  // PRESERVE CONSTANT VALUES BUT NOT BE CONSERVATIVE. THEN WE HAVE
396  // TO DO A SEMI-LOCAL OR GLOBAL REPAIR.
397 
398  // We use the * operator instead of / so as to reduce the number
399  // of requirements on generic variable type
400 
401  if (nsummed)
402  val *= (1.0/wtsum0);
403 
404  return val;
405  } // operator()
406 
407  constexpr static int order = 1;
408 
409  private:
410  SourceMeshType const & source_mesh_;
411  TargetMeshType const & target_mesh_;
412  SourceStateType const & source_state_;
413  std::string interp_var_name_;
414  T const * source_vals_;
415  int matid_ = 0;
416  Field_type field_type_ = Field_type::UNKNOWN_TYPE_FIELD;
417  NumericTolerances_t num_tols_;
418 #ifdef HAVE_TANGRAM
419  std::shared_ptr<InterfaceReconstructor> interface_reconstructor_;
420 #endif
421  Parts const* parts_;
422 }; // interpolate_1st_order specialization for cell
423 
425 
426 
427 
429 
433 template<int D,
434  typename SourceMeshType,
435  typename TargetMeshType,
436  typename SourceStateType,
437  typename TargetStateType,
438  typename T,
439  template<class, int, class, class> class InterfaceReconstructorType,
440  class Matpoly_Splitter,
441  class Matpoly_Clipper,
442  class CoordSys>
444  D, Entity_kind::NODE,
445  SourceMeshType, TargetMeshType,
446  SourceStateType, TargetStateType,
447  T,
448  InterfaceReconstructorType,
449  Matpoly_Splitter, Matpoly_Clipper, CoordSys> {
450 
451  // useful aliases
452 #ifdef HAVE_TANGRAM
453  using InterfaceReconstructor =
454  Tangram::Driver<InterfaceReconstructorType, D, SourceMeshType,
455  Matpoly_Splitter, Matpoly_Clipper>;
456 #endif
457 
458  public:
459 
460  // Constructor with interface reconstructor
461 #ifdef HAVE_TANGRAM
462  Interpolate_1stOrder(SourceMeshType const & source_mesh,
463  TargetMeshType const & target_mesh,
464  SourceStateType const & source_state,
465  NumericTolerances_t num_tols,
466  std::shared_ptr<InterfaceReconstructor> ir) :
467  source_mesh_(source_mesh),
468  target_mesh_(target_mesh),
469  source_state_(source_state),
470  interp_var_name_("VariableNameNotSet"),
471  source_vals_(nullptr),
472  num_tols_(num_tols),
473  interface_reconstructor_(ir) {}
474 #endif
475 
484  Interpolate_1stOrder(SourceMeshType const & source_mesh,
485  TargetMeshType const & target_mesh,
486  SourceStateType const & source_state,
487  NumericTolerances_t num_tols) :
488  source_mesh_(source_mesh),
489  target_mesh_(target_mesh),
490  source_state_(source_state),
491  interp_var_name_("VariableNameNotSet"),
492  source_vals_(nullptr),
493  num_tols_(num_tols) {}
494 
495 
497  // Interpolate_1stOrder(const Interpolate_1stOrder &) = delete;
498 
500  // Interpolate_1stOrder & operator = (const Interpolate_1stOrder &) = delete;
501 
503  ~Interpolate_1stOrder() = default;
504 
506 
507  void set_material(int m) {
508  matid_ = m;
509  } // set_material
510 
512 
513  // Even though 1st order accurate interpolation does not require
514  // limiters and only higher order ones do, we need to have the
515  // limiter_type as an argument. This is because the templated driver
516  // does not know whether its being called with 1st order or higher
517  // order interpolators and so all interpolators need to have a
518  // uniform interface
519 
520  void set_interpolation_variable(std::string const & interp_var_name,
521  Portage::vector<Wonton::Vector<D>>* gradients = nullptr) {
522  interp_var_name_ = interp_var_name;
523  field_type_ = source_state_.field_type(Entity_kind::NODE, interp_var_name);
524  if (field_type_ == Field_type::MESH_FIELD)
525  source_state_.mesh_get_data(Entity_kind::NODE, interp_var_name,
526  &source_vals_);
527  else {
528  source_state_.mat_get_celldata(interp_var_name, matid_, &source_vals_);
529  std::cerr << "Cannot remap NODE-centered multi-material data" << "\n";
530  }
531  } // set_interpolation_variable
532 
533 
550  T operator() (int const targetNodeID,
551  std::vector<Weights_t> const & sources_and_weights) const
552  {
553  if (field_type_ != Field_type::MESH_FIELD) return T(0.0);
554 
555  int nsrcdualcells = sources_and_weights.size();
556  if (!nsrcdualcells) return T(0.0);
557 
558  // contribution of the source node (dual cell) is its field value
559  // weighted by its "weight" (in this case, the 0th
560  // moment/area/volume of its intersection with the target dual cell)
561 
562  T val(0.0);
563  double wtsum0 = 0.0;
564  int nsummed = 0;
565  for (auto const& wt : sources_and_weights) {
566  int srcnode = wt.entityID;
567  std::vector<double> pair_weights = wt.weights;
568  if (fabs(pair_weights[0]) < num_tols_.min_absolute_volume)
569  continue; // skip small intersections
570  val += source_vals_[srcnode] * pair_weights[0]; // 1st order
571  wtsum0 += pair_weights[0];
572  nsummed++;
573  }
574 
575  // Normalize the value by the volume of the intersection of the
576  // target cells with the source mesh. This will do the right thing
577  // for single-material and multi-material remap (conservative and
578  // constant preserving) if there is NO mismatch between source and
579  // target mesh boundaries. IF THERE IS A MISMATCH, THIS WILL
580  // PRESERVE CONSTANT VALUES BUT NOT BE CONSERVATIVE. THEN WE HAVE
581  // TO DO A SEMI-LOCAL OR GLOBAL REPAIR.
582 
583  // We use the * operator instead of / so as to reduce the number
584  // of requirements on generic variable type
585 
586  if (nsummed)
587  val *= (1.0/wtsum0);
588 
589  return val;
590  } // operator()
591 
592  constexpr static int order = 1;
593 
594  private:
595  SourceMeshType const & source_mesh_;
596  TargetMeshType const & target_mesh_;
597  SourceStateType const & source_state_;
598  std::string interp_var_name_;
599  T const * source_vals_;
600  int matid_ = 0;
601  Field_type field_type_ = Field_type::UNKNOWN_TYPE_FIELD;
602  NumericTolerances_t num_tols_;
603 #ifdef HAVE_TANGRAM
604  std::shared_ptr<InterfaceReconstructor> interface_reconstructor_;
605 #endif
606 }; // interpolate_1st_order specialization for nodes
607 
609 
610 
611 } // namespace Portage
612 
613 #endif // PORTAGE_INTERPOLATE_INTERPOLATE_1ST_ORDER_H_
void set_material(int m)
Set the material we are operating on.
Definition: interpolate_1st_order.h:160
T operator()(int const targetEntityId, std::vector< Weights_t > const &sources_and_weights) const
Functor to do the actual interpolation.
Definition: interpolate_1st_order.h:200
std::vector< T > vector
Definition: portage.h:238
Intersection and other tolerances to handle tiny values.
Definition: portage.h:152
~Interpolate_1stOrder()=default
Copy constructor (disabled)
Manages source and target sub-meshes for part-by-part remap.
Interpolate_1stOrder(SourceMeshType const &source_mesh, TargetMeshType const &target_mesh, SourceStateType const &source_state, NumericTolerances_t num_tols)
Constructor without interface reconstructor.
Definition: interpolate_1st_order.h:137
Manages source and target sub-meshes for part-by-part remap. It detects boundaries mismatch and provi...
Definition: parts.h:234
void set_interpolation_variable(std::string const &interp_var_name, Portage::vector< Wonton::Vector< D >> *gradients=nullptr)
Set the variable name to be interpolated.
Definition: interpolate_1st_order.h:173
static constexpr int order
Definition: interpolate_1st_order.h:207
Definition: coredriver.h:42
Interpolate_1stOrder(SourceMeshType const &source_mesh, TargetMeshType const &target_mesh, SourceStateType const &source_state, NumericTolerances_t num_tols, const Parts *const parts=nullptr)
Constructor.
Definition: interpolate_1st_order.h:286
Interpolate_1stOrder does a 1st order interpolation of scalars.
Definition: interpolate_1st_order.h:101
Interpolate_1stOrder(SourceMeshType const &source_mesh, TargetMeshType const &target_mesh, SourceStateType const &source_state, NumericTolerances_t num_tols)
Constructor without interface reconstructor.
Definition: interpolate_1st_order.h:484
void set_interpolation_variable(std::string const &interp_var_name, Portage::vector< Wonton::Vector< D >> *gradients=nullptr)
Set the variable name to be interpolated.
Definition: interpolate_1st_order.h:520
void set_interpolation_variable(std::string const &interp_var_name, Portage::vector< Wonton::Vector< D >> *gradients=nullptr)
Set the variable name to be interpolated.
Definition: interpolate_1st_order.h:326