coredriver.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_CORE_DRIVER_H_
8 #define PORTAGE_CORE_DRIVER_H_
9 
10 #include <ctime>
11 #include <algorithm>
12 #include <vector>
13 #include <iterator>
14 #include <string>
15 #include <utility>
16 #include <iostream>
17 #include <type_traits>
18 #include <memory>
19 #include <limits>
20 
21 
22 #ifdef HAVE_TANGRAM
23 #include "tangram/driver/driver.h"
24 #endif
25 
29 #include "wonton/support/Point.h"
30 #include "wonton/support/CoordinateSystem.h"
31 #include "portage/driver/parts.h"
33 
42 namespace Portage {
43 
44 using Wonton::Entity_kind;
45 using Wonton::CELL;
46 using Wonton::NODE;
47 using Wonton::UNKNOWN_KIND;
48 using Wonton::Entity_type;
49 using Wonton::PARALLEL_OWNED;
50 using Wonton::ALL;
51 using Wonton::Point;
52 
53 // Forward declaration of remap driver on particular entity kind
54 
55 template <int D,
56  Entity_kind ONWHAT,
57  class SourceMesh, class SourceState,
58  class TargetMesh, class TargetState,
59  template <class, int, class, class> class InterfaceReconstructorType,
60  class Matpoly_Splitter,
61  class Matpoly_Clipper,
62  class CoordSys
63  >
64 class CoreDriver;
65 
66 
97 template<int D,
98  class SourceMesh, class SourceState,
99  class TargetMesh, class TargetState,
100  template <class, int, class, class> class InterfaceReconstructorType,
101  class Matpoly_Splitter,
102  class Matpoly_Clipper,
103  class CoordSys
104  >
106 
107  template<Entity_kind ONWHAT>
108  using CoreDriverType = CoreDriver<D, ONWHAT, SourceMesh, SourceState,
109  TargetMesh, TargetState,
110  InterfaceReconstructorType,
111  Matpoly_Splitter, Matpoly_Clipper,
112  CoordSys>;
113 
114  public:
115  CoreDriverBase() = default;
116  virtual ~CoreDriverBase() = default; // Necessary
117 
118  // Entity kind that a derived class is defined on
119  virtual Entity_kind onwhat() = 0;
120 
131  template<Entity_kind ONWHAT,
132  template <int, Entity_kind, class, class> class Search>
134  search() {
135  assert(ONWHAT == onwhat());
136  auto derived_class_ptr = static_cast<CoreDriverType<ONWHAT> *>(this);
137  return derived_class_ptr->template search<Search>();
138  }
139 
140 
152  template<
153  Entity_kind ONWHAT,
154  template <Entity_kind, class, class, class,
155  template <class, int, class, class> class,
156  class, class> class Intersect
157  >
158  Portage::vector<std::vector<Portage::Weights_t>>
159  intersect_meshes(Portage::vector<std::vector<int>> const& intersection_candidates) {
160  assert(ONWHAT == onwhat());
161  auto derived_class_ptr = static_cast<CoreDriverType<ONWHAT> *>(this);
162  return derived_class_ptr->template intersect_meshes<Intersect>(intersection_candidates);
163  }
164 
165 
166 
167 
179  template<
180  template <Entity_kind, class, class, class,
181  template <class, int, class, class> class,
182  class, class> class Intersect
183  >
184  std::vector<Portage::vector<std::vector<Portage::Weights_t>>>
185  intersect_materials(Portage::vector<std::vector<int>> const& intersection_candidates) {
186  assert(onwhat() == CELL);
187  auto derived_class_ptr = static_cast<CoreDriverType<CELL> *>(this);
188  return derived_class_ptr->template intersect_materials<Intersect>(intersection_candidates);
189  }
190 
200  template<Entity_kind ONWHAT>
202  std::string const field_name,
203  Limiter_type limiter_type = NOLIMITER,
204  Boundary_Limiter_type boundary_limiter_type = BND_NOLIMITER,
205  int material_id = 0,
206  const Part<SourceMesh, SourceState>* source_part = nullptr) {
207 
208  assert(ONWHAT == onwhat());
209  auto derived_class_ptr = static_cast<CoreDriverType<ONWHAT> *>(this);
210  return derived_class_ptr->compute_source_gradient(field_name, limiter_type,
211  boundary_limiter_type,
212  material_id, source_part);
213  }
214 
233  template<typename T = double,
234  Entity_kind ONWHAT,
235  template<int, Entity_kind, class, class, class, class, class,
236  template <class, int, class, class> class,
237  class, class, class> class Interpolate
238  >
239  void interpolate_mesh_var(std::string srcvarname, std::string trgvarname,
240  Portage::vector<std::vector<Weights_t>> const& sources_and_weights,
241  Portage::vector<Vector<D>>* gradients = nullptr) {
242  assert(ONWHAT == onwhat());
243  auto derived_class_ptr = static_cast<CoreDriverType<ONWHAT> *>(this);
244  derived_class_ptr->
245  template interpolate_mesh_var<T, Interpolate>(srcvarname, trgvarname,
246  sources_and_weights,
247  gradients);
248  }
249 
272  template<typename T = double,
273  Entity_kind ONWHAT,
274  template<int, Entity_kind, class, class, class, class, class,
275  template <class, int, class, class> class,
276  class, class, class> class Interpolate>
277  typename std::enable_if<ONWHAT == CELL, void>
278  interpolate_mesh_var(std::string srcvarname, std::string trgvarname,
279  Portage::vector<std::vector<Weights_t>> const& sources_and_weights,
280  const PartPair<D, SourceMesh, SourceState,
281  TargetMesh, TargetState>* parts_pair,
282  Portage::vector<Vector<D>>* gradients = nullptr) {
283  assert(ONWHAT == onwhat());
284  auto derived_class_ptr = static_cast<CoreDriverType<ONWHAT> *>(this);
285  derived_class_ptr->
286  template interpolate_mesh_var<T, Interpolate>(srcvarname, trgvarname,
287  sources_and_weights,
288  parts_pair,
289  gradients);
290  }
291 
292 
303  template <typename T = double,
304  template<int, Entity_kind, class, class, class, class, class,
305  template <class, int, class, class> class,
306  class, class, class> class Interpolate>
307  void interpolate_mat_var(std::string srcvarname, std::string trgvarname,
308  std::vector<Portage::vector<std::vector<Weights_t>>> const& sources_and_weights_by_mat,
309  std::vector<Portage::vector<Vector<D>>>* gradients = nullptr) {
310 
311  auto derived_class_ptr = static_cast<CoreDriverType<CELL> *>(this);
312  derived_class_ptr->
313  template interpolate_mat_var<T, Interpolate>(srcvarname,
314  trgvarname,
315  sources_and_weights_by_mat,
316  gradients);
317  }
318 
319 
330  template<Entity_kind ONWHAT>
331  bool
332  check_mismatch(Portage::vector<std::vector<Weights_t>> const& source_weights) {
333  assert(ONWHAT == onwhat());
334  auto derived_class_ptr = static_cast<CoreDriverType<ONWHAT> *>(this);
335  return derived_class_ptr->check_mismatch(source_weights);
336  }
337 
338 
346  template<Entity_kind ONWHAT>
347  bool
349  assert(ONWHAT == onwhat());
350  auto derived_class_ptr = static_cast<CoreDriverType<ONWHAT> *>(this);
351  return derived_class_ptr->has_mismatch();
352  }
353 
354 
362  template<Entity_kind ONWHAT>
363  bool
364  fix_mismatch(std::string const & src_var_name,
365  std::string const & trg_var_name,
366  double global_lower_bound = -std::numeric_limits<double>::max(),
367  double global_upper_bound = std::numeric_limits<double>::max(),
368  double conservation_tol = 1e2*std::numeric_limits<double>::epsilon(),
369  int maxiter = 5,
370  Partial_fixup_type partial_fixup_type =
372  Empty_fixup_type empty_fixup_type =
374  assert(ONWHAT == onwhat());
375  auto derived_class_ptr = static_cast<CoreDriverType<ONWHAT> *>(this);
376  return derived_class_ptr->fix_mismatch(src_var_name,
377  trg_var_name,
378  global_lower_bound,
379  global_upper_bound,
380  conservation_tol,
381  maxiter,
382  partial_fixup_type,
383  empty_fixup_type);
384 }
385 
386 
397  template<Entity_kind ONWHAT>
398  void
399  set_num_tols(const double min_absolute_distance,
400  const double min_absolute_volume) {
401  assert(ONWHAT == onwhat());
402  auto derived_class_ptr = static_cast<CoreDriverType<ONWHAT> *>(this);
403  derived_class_ptr->set_num_tols(min_absolute_distance, min_absolute_volume);
404  }
405 
414  template<Entity_kind ONWHAT>
415  void
417  assert(ONWHAT == onwhat());
418  auto derived_class_ptr = static_cast<CoreDriverType<ONWHAT> *>(this);
419  derived_class_ptr->set_num_tols(num_tols);
420  }
421 
422 
423 #ifdef HAVE_TANGRAM
424 
436  void set_interface_reconstructor_options(bool all_convex,
437  const std::vector<Tangram::IterativeMethodTolerances_t> &tols =
438  std::vector<Tangram::IterativeMethodTolerances_t>()) {
439  assert(onwhat() == CELL);
440  auto derived_class_ptr = static_cast<CoreDriverType<CELL> *>(this);
441  derived_class_ptr->set_interface_reconstructor_options(all_convex, tols);
442  }
443 
444 #endif
445 
446 };
447 
448 
449 
450 
484 template <int D,
485  Entity_kind ONWHAT,
486  class SourceMesh, class SourceState,
487  class TargetMesh = SourceMesh, class TargetState = SourceState,
488  template <class, int, class, class> class InterfaceReconstructorType = DummyInterfaceReconstructor,
489  class Matpoly_Splitter = void,
490  class Matpoly_Clipper = void,
491  class CoordSys = Wonton::DefaultCoordSys
492  >
493 class CoreDriver : public CoreDriverBase<D,
494  SourceMesh, SourceState,
495  TargetMesh, TargetState,
496  InterfaceReconstructorType,
497  Matpoly_Splitter,
498  Matpoly_Clipper,
499  CoordSys> {
500 
501  // useful alias
502  using Gradient = Limited_Gradient<D, ONWHAT, SourceMesh, SourceState,
503  InterfaceReconstructorType,
504  Matpoly_Splitter, Matpoly_Clipper, CoordSys>;
505 
506  public:
521  CoreDriver(SourceMesh const& source_mesh,
522  SourceState const& source_state,
523  TargetMesh const& target_mesh,
524  TargetState& target_state,
525  Wonton::Executor_type const *executor = nullptr)
526  : source_mesh_(source_mesh),
527  target_mesh_(target_mesh),
528  source_state_(source_state),
529  target_state_(target_state),
530  executor_(executor)
531  {
532 #ifdef PORTAGE_ENABLE_MPI
533  mycomm_ = MPI_COMM_NULL;
534  auto mpiexecutor = dynamic_cast<Wonton::MPIExecutor_type const *>(executor);
535  if (mpiexecutor && mpiexecutor->mpicomm != MPI_COMM_NULL) {
536  mycomm_ = mpiexecutor->mpicomm;
537  MPI_Comm_rank(mycomm_, &comm_rank_);
538  MPI_Comm_size(mycomm_, &nprocs_);
539  }
540 #endif
541  }
542 
544  CoreDriver(const CoreDriver &) = delete;
545 
547  CoreDriver & operator = (const CoreDriver &) = delete;
548 
550  ~CoreDriver() = default;
551 
553  Entity_kind onwhat() {return ONWHAT;}
554 
565  template<template<int, Entity_kind, class, class> class Search>
567  search() {
568  // Get an instance of the desired search algorithm type
569  const Search<D, ONWHAT, SourceMesh, TargetMesh>
570  search_functor(source_mesh_, target_mesh_);
571 
572  int ntarget_ents = target_mesh_.num_entities(ONWHAT, PARALLEL_OWNED);
573 
574  // initialize search candidate vector
575  Portage::vector<std::vector<int>> candidates(ntarget_ents);
576 
577  Portage::transform(target_mesh_.begin(ONWHAT, PARALLEL_OWNED),
578  target_mesh_.end(ONWHAT, PARALLEL_OWNED),
579  candidates.begin(), search_functor);
580 
581  return candidates;
582  }
583 
584 
595  template<template <Entity_kind, class, class, class,
596  template <class, int, class, class> class,
597  class, class> class Intersect>
598  Portage::vector<std::vector<Portage::Weights_t>>
599  intersect_meshes(Portage::vector<std::vector<int>> const& candidates) {
600 
601 #ifdef HAVE_TANGRAM
602  // If user did NOT set tolerances for Tangram, use Portage tolerances
603  if (reconstructor_tols_.empty()) {
604  reconstructor_tols_ = { {1000, num_tols_.min_absolute_distance,
605  num_tols_.min_absolute_volume},
606  {100, num_tols_.min_absolute_distance,
607  num_tols_.min_absolute_distance} };
608  }
609  // If user set tolerances for Tangram, but not for Portage,
610  // use Tangram tolerances
611  else if (!num_tols_.user_tolerances) {
612  num_tols_.min_absolute_distance = reconstructor_tols_[0].arg_eps;
613  num_tols_.min_absolute_volume = reconstructor_tols_[0].fun_eps;
614  }
615 #endif
616 
617  int nents = target_mesh_.num_entities(ONWHAT, PARALLEL_OWNED);
618  Portage::vector<std::vector<Portage::Weights_t>> sources_and_weights(nents);
619 
620  Intersect<ONWHAT, SourceMesh, SourceState, TargetMesh,
621  InterfaceReconstructorType, Matpoly_Splitter, Matpoly_Clipper>
622  intersector(source_mesh_, source_state_, target_mesh_, num_tols_);
623 
624  Portage::transform(target_mesh_.begin(ONWHAT, PARALLEL_OWNED),
625  target_mesh_.end(ONWHAT, PARALLEL_OWNED),
626  candidates.begin(),
627  sources_and_weights.begin(),
628  intersector);
629 
630  return sources_and_weights;
631  }
632 
633 
635  void set_num_tols(const double min_absolute_distance,
636  const double min_absolute_volume) {
637  num_tols_.min_absolute_distance = min_absolute_distance;
638  num_tols_.min_absolute_volume = min_absolute_volume;
639  num_tols_.user_tolerances = true;
640  }
641 
643  void set_num_tols(const NumericTolerances_t& num_tols) {
644  num_tols_ = num_tols;
645  }
646 
647 #ifdef HAVE_TANGRAM
648 
660  void set_interface_reconstructor_options(bool all_convex,
661  const std::vector<Tangram::IterativeMethodTolerances_t> &tols =
662  std::vector<Tangram::IterativeMethodTolerances_t>()) {
663  reconstructor_tols_ = tols;
664  reconstructor_all_convex_ = all_convex;
665  }
666 
667 #endif
668 
669 
685  template<
686  template <Entity_kind, class, class, class,
687  template <class, int, class, class> class,
688  class, class> class Intersect
689  >
690  std::vector<Portage::vector<std::vector<Weights_t>>>
691  intersect_materials(Portage::vector<std::vector<int>> const& candidates) {
692 
693 #ifdef HAVE_TANGRAM
694 
695  int nmats = source_state_.num_materials();
696  // Make sure we have a valid interface reconstruction method instantiated
697 
698  assert(typeid(InterfaceReconstructorType<SourceMesh, D,
699  Matpoly_Splitter, Matpoly_Clipper >) !=
700  typeid(DummyInterfaceReconstructor<SourceMesh, D,
701  Matpoly_Splitter, Matpoly_Clipper>));
702 
703  // Intel 18.0.1 does not recognize std::make_unique even with -std=c++14 flag *ugh*
704  // interface_reconstructor_ =
705  // std::make_unique<Tangram::Driver<InterfaceReconstructorType, D,
706  // SourceMesh,
707  // Matpoly_Splitter,
708  // Matpoly_Clipper>
709  // >(source_mesh_, tols, true);
710  interface_reconstructor_ =
711  std::unique_ptr<Tangram::Driver<InterfaceReconstructorType, D,
712  SourceMesh,
713  Matpoly_Splitter,
714  Matpoly_Clipper>
715  >(new Tangram::Driver<InterfaceReconstructorType, D,
716  SourceMesh,
717  Matpoly_Splitter,
718  Matpoly_Clipper>(source_mesh_, reconstructor_tols_,
719  reconstructor_all_convex_));
720 
721  int ntargetcells = target_mesh_.num_entities(CELL, PARALLEL_OWNED);
722 
723 
724  std::vector<int> cell_num_mats, cell_mat_ids;
725  std::vector<double> cell_mat_volfracs;
726  std::vector<Wonton::Point<D>> cell_mat_centroids;
727 
728  // Extract volume fraction and centroid data for cells in compact
729  // cell-centric form (ccc)
730 
731  ccc_vfcen_data(cell_num_mats, cell_mat_ids, cell_mat_volfracs,
732  cell_mat_centroids);
733 
734  interface_reconstructor_->set_volume_fractions(cell_num_mats,
735  cell_mat_ids,
736  cell_mat_volfracs,
737  cell_mat_centroids);
738  interface_reconstructor_->reconstruct(executor_);
739 
740  // Make an intersector which knows about the source state (to be
741  // able to query the number of materials, etc) and also knows
742  // about the interface reconstructor so that it can retrieve pure
743  // material polygons
744 
745  Intersect<CELL, SourceMesh, SourceState, TargetMesh,
746  InterfaceReconstructorType, Matpoly_Splitter, Matpoly_Clipper>
747  intersector(source_mesh_, source_state_, target_mesh_, num_tols_,
748  interface_reconstructor_);
749 
750  // Assume (with no harm for sizing purposes) that all materials
751  // in source made it into target
752 
753  std::vector<Portage::vector<std::vector<Weights_t>>>
754  source_weights_by_mat(nmats);
755 
756  for (int m = 0; m < nmats; m++) {
757  std::vector<int> matcellstgt;
758 
759  intersector.set_material(m);
760 
761  // For each cell in the target mesh get a list of
762  // candidate-weight pairings (in a traditional mesh, not
763  // particle mesh, the weights are moments). Note that this
764  // candidate list is different from the search candidate list in
765  // that it may not include some of the search candidates. Also,
766  // note that for 2nd order and higher remaps, we get multiple
767  // moments (0th, 1st, etc) for each target-source cell
768  // intersection
769  //
770  // NOTE: IDEALLY WE WOULD REUSE THE MESH-MESH INTERSECTIONS
771  // WHEN THE SOURCE CELL CONTAINS ONLY ONE MATERIAL
772  //
773  // UNFORTUNATELY, THE REQUIREMENT OF THE INTERSECT FUNCTOR IS
774  // THAT IT CANNOT MODIFY STATE, THIS MEANS WE CANNOT STORE THE
775  // MESH-MESH INTERSECTION VALUES AND REUSE THEM AS NECESSARY
776  // FOR MESH-MATERIAL INTERSECTION COMPUTATIONS. WE COULD DO
777  // SOME OTHER THINGS LIKE PROCESS ONLY TARGET CELLS THAT
778  // POSSIBLY INTERSECT MULTI-MATERIAL SOURCE CELLS; TARGET
779  // CELLS THAT ONLY INTERSECT SINGLE MATERIAL CELLS CAN REUSE
780  // MESH-MESH INTERSECTIONS (still have to determine the
781  // materials coming into the target cell though - a target
782  // cell intersecting pure cells of different materials will
783  // become mixed).
784 
785 
786  std::vector<std::vector<Weights_t>> this_mat_sources_and_wts(ntargetcells);
787  Portage::transform(target_mesh_.begin(CELL, PARALLEL_OWNED),
788  target_mesh_.end(CELL, PARALLEL_OWNED),
789  candidates.begin(),
790  this_mat_sources_and_wts.begin(),
791  intersector);
792 
793  // LOOK AT INTERSECTION WEIGHTS TO DETERMINE WHICH TARGET CELLS
794  // WILL GET NEW MATERIALS
795 
796  ntargetcells = target_mesh_.num_entities(CELL, PARALLEL_OWNED);
797 
798  for (int c = 0; c < ntargetcells; c++) {
799  std::vector<Weights_t> const& cell_mat_sources_and_weights =
800  this_mat_sources_and_wts[c];
801  int nwts = cell_mat_sources_and_weights.size();
802  for (int s = 0; s < nwts; s++) {
803  std::vector<double> const& wts = cell_mat_sources_and_weights[s].weights;
804  // Check that the volume of material we are adding to c is not miniscule
805  if (wts[0] > num_tols_.min_absolute_volume) {
806  matcellstgt.push_back(c);
807  break;
808  }
809  }
810  }
811 
812  // If any processor is adding this material to the target state,
813  // add it on all the processors
814 
815  int nmatcells = matcellstgt.size();
816  int nmatcells_global = nmatcells;
817 #ifdef PORTAGE_ENABLE_MPI
818  if (mycomm_!= MPI_COMM_NULL)
819  MPI_Allreduce(&nmatcells, &nmatcells_global, 1, MPI_INT, MPI_SUM,
820  mycomm_);
821 #endif
822 
823  if (nmatcells_global) {
824  int nmatstrg = target_state_.num_materials();
825  bool found = false;
826  int m2 = -1;
827  for (int i = 0; i < nmatstrg; i++)
828  if (target_state_.material_name(i) == source_state_.material_name(m)) {
829  found = true;
830  m2 = i;
831  break;
832  }
833  if (found) { // material already present - just update its cell list
834  target_state_.mat_add_cells(m2, matcellstgt);
835  } else {
836  // add material along with the cell list
837 
838  // NOTE: NOT ONLY DOES THIS ROUTINE ADD A MATERIAL AND ITS
839  // CELLS TO THE STATEMANAGER, IT ALSO MAKES SPACE FOR
840  // FIELD VALUES FOR THIS MATERIAL IN EVERY MULTI-MATERIAL
841  // VECTOR IN THE STATE MANAGER. THIS ENSURES THAT WHEN WE
842  // CALL mat_get_celldata FOR A MATERIAL IN MULTI-MATERIAL
843  // STATE VECTOR IT WILL ALREADY HAVE SPACE ALLOCATED FOR
844  // FIELD VALUES OF THAT MATERIAL. SOME STATE WRAPPERS
845  // COULD CHOOSE TO MAKE THIS A SIMPLER ROUTINE THAT ONLY
846  // STORES THE NAME AND THE CELLS IN THE MATERIAL AND
847  // ACTUALLY ALLOCATE SPACE FOR FIELD VALUES OF A MATERIAL
848  // IN A MULTI-MATERIAL FIELD WHEN mat_get_celldata IS
849  // INVOKED.
850 
851  target_state_.add_material(source_state_.material_name(m),
852  matcellstgt);
853  }
854  }
855  else
856  continue; // maybe the target mesh does not overlap this material
857 
858  // Add volume fractions and centroids of materials to target mesh
859  //
860  // Also make list of sources/weights only for target cells that are
861  // getting this material - Can we avoid the copy?
862 
863  std::vector<double> mat_volfracs(nmatcells);
864  std::vector<Point<D>> mat_centroids(nmatcells);
865 
866  source_weights_by_mat[m].resize(nmatcells);
867 
868  for (int ic = 0; ic < nmatcells; ic++) {
869  int c = matcellstgt[ic];
870  double matvol = 0.0;
871  Point<D> matcen;
872  std::vector<Weights_t> const &
873  cell_mat_sources_and_weights = this_mat_sources_and_wts[c];
874  int nwts = cell_mat_sources_and_weights.size();
875  for (int s = 0; s < nwts; s++) {
876  std::vector<double> const& wts = cell_mat_sources_and_weights[s].weights;
877  matvol += wts[0];
878  for (int d = 0; d < D; d++)
879  matcen[d] += wts[d+1];
880  }
881  matcen /= matvol;
882  mat_volfracs[ic] = matvol/target_mesh_.cell_volume(c);
883  mat_centroids[ic] = matcen;
884 
885  source_weights_by_mat[m][ic] = cell_mat_sources_and_weights;
886  }
887 
888  target_state_.mat_add_celldata("mat_volfracs", m, &(mat_volfracs[0]));
889  target_state_.mat_add_celldata("mat_centroids", m, &(mat_centroids[0]));
890 
891  } // for each material m
892 
893  return source_weights_by_mat;
894 #else
895  return std::vector<Portage::vector<std::vector<Weights_t>>>();
896 #endif
897 
898  }
899 
900 
910  std::string const field_name,
911  Limiter_type limiter_type = NOLIMITER,
912  Boundary_Limiter_type boundary_limiter_type = BND_NOLIMITER,
913  int material_id = 0,
914  const Part<SourceMesh, SourceState>* source_part = nullptr) const {
915 
916  int nallent = 0;
917 #ifdef HAVE_TANGRAM
918  // enable part-by-part only for cell-based remap
919  auto const field_type = source_state_.field_type(ONWHAT, field_name);
920 
921  // multi-material remap makes only sense on cell-centered fields.
922  bool const multimat =
923  ONWHAT == Entity_kind::CELL and
924  field_type == Field_type::MULTIMATERIAL_FIELD;
925 
926  std::vector<int> mat_cells;
927 
928  if (multimat) {
929  if (interface_reconstructor_) {
930  std::vector<int> mat_cells_all;
931  source_state_.mat_get_cells(material_id, &mat_cells_all);
932  nallent = mat_cells_all.size();
933 
934  // Filter out GHOST cells
935  // SHOULD BE IN HANDLED IN THE STATE MANAGER (See ticket LNK-1589)
936  mat_cells.reserve(nallent);
937  for (auto const& c : mat_cells_all)
938  if (source_mesh_.cell_get_type(c) == PARALLEL_OWNED)
939  mat_cells.push_back(c);
940  }
941  else
942  throw std::runtime_error("interface reconstructor not set");
943  } else /* single material */ {
944 #endif
945  nallent = source_mesh_.num_entities(ONWHAT, ALL);
946 #ifdef HAVE_TANGRAM
947  }
948 #endif
949 
950  // instantiate the right kernel according to entity kind (cell/node),
951  // as well as source and target meshes and states types.
952 #ifdef HAVE_TANGRAM
953  Gradient kernel(source_mesh_, source_state_, field_name,
954  limiter_type, boundary_limiter_type,
955  interface_reconstructor_, source_part);
956 #else
957  Gradient kernel(source_mesh_, source_state_, field_name,
958  limiter_type, boundary_limiter_type, source_part);
959 #endif
960 
961  // create the field (material cell indices have owned and ghost
962  // cells mixed together; so we have to have a vector of size
963  // owned+ghost and fill in the right entries; the ghost entries
964  // are zeroed out)
965  Vector<D> zerovec;
966  Portage::vector<Vector<D>> gradient_field(nallent, zerovec);
967 
968  // populate it by invoking the kernel on each source entity.
969 #ifdef HAVE_TANGRAM
970  if (multimat) {
971  // no need for this to be Portage::vector as it will be copied out
972  std::vector<Vector<D>> owned_gradient_field(mat_cells.size());
973 
974  kernel.set_material(material_id);
975  Portage::transform(mat_cells.begin(),
976  mat_cells.end(),
977  owned_gradient_field.begin(), kernel);
978  int i = 0;
979  for (auto const& c : mat_cells) {
980  int cm = source_state_.cell_index_in_material(c, material_id);
981  gradient_field[cm] = owned_gradient_field[i++];
982  }
983  } else {
984 #endif
985  Portage::transform(source_mesh_.begin(ONWHAT, PARALLEL_OWNED),
986  source_mesh_.end(ONWHAT, PARALLEL_OWNED),
987  gradient_field.begin(), kernel);
988 #ifdef HAVE_TANGRAM
989  }
990 #endif
991  return gradient_field;
992  }
993 
1002  template<typename T = double,
1003  template<int, Entity_kind, class, class, class, class, class,
1004  template<class, int, class, class> class,
1005  class, class, class> class Interpolate
1006  >
1007  void interpolate_mesh_var(std::string srcvarname, std::string trgvarname,
1008  Portage::vector<std::vector<Weights_t>> const& sources_and_weights,
1009  Portage::vector<Vector<D>>* gradients = nullptr) {
1010 
1011  if (source_state_.get_entity(srcvarname) != ONWHAT) {
1012  std::cerr << "Variable " << srcvarname << " not defined on Entity_kind "
1013  << ONWHAT << ". Skipping!" << std::endl;
1014  return;
1015  }
1016 
1017 
1018  using Interpolator = Interpolate<D, ONWHAT,
1019  SourceMesh, TargetMesh,
1020  SourceState, TargetState,
1021  T,
1022  InterfaceReconstructorType,
1023  Matpoly_Splitter, Matpoly_Clipper, CoordSys>;
1024 
1025  Interpolator interpolator(source_mesh_, target_mesh_, source_state_,
1026  num_tols_);
1027  interpolator.set_interpolation_variable(srcvarname, gradients);
1028 
1029  // get a handle to a memory location where the target state
1030  // would like us to write this material variable into.
1031  T* target_mesh_field = nullptr;
1032  target_state_.mesh_get_data(ONWHAT, trgvarname, &target_mesh_field);
1033 
1034  Portage::pointer<T> target_field(target_mesh_field);
1035  Portage::transform(target_mesh_.begin(ONWHAT, PARALLEL_OWNED),
1036  target_mesh_.end(ONWHAT, PARALLEL_OWNED),
1037  sources_and_weights.begin(),
1038  target_field, interpolator);
1039  }
1040 
1041 
1068  template<typename T = double,
1069  template<int, Entity_kind, class, class, class, class, class,
1070  template<class, int, class, class> class,
1071  class, class, class> class Interpolate,
1072  Entity_kind ONWHAT1 = ONWHAT,
1073  typename = typename std::enable_if<ONWHAT1 == CELL>::type>
1074  void
1075  interpolate_mesh_var(std::string srcvarname, std::string trgvarname,
1076  Portage::vector<std::vector<Weights_t>> const& sources_and_weights,
1077  const PartPair<D, SourceMesh, SourceState,
1078  TargetMesh, TargetState>* partition,
1079  Portage::vector<Vector<D>>* gradients = nullptr) {
1080 
1081  if (source_state_.get_entity(srcvarname) != ONWHAT) {
1082  std::cerr << "Variable " << srcvarname << " not defined on Entity_kind "
1083  << ONWHAT << ". Skipping!" << std::endl;
1084  return;
1085  }
1086 
1087 
1088  using Interpolator = Interpolate<D, ONWHAT,
1089  SourceMesh, TargetMesh,
1090  SourceState, TargetState,
1091  T,
1092  InterfaceReconstructorType,
1093  Matpoly_Splitter, Matpoly_Clipper, CoordSys>;
1094 
1095  Interpolator interpolator(source_mesh_, target_mesh_, source_state_, num_tols_, partition);
1096  interpolator.set_interpolation_variable(srcvarname, gradients);
1097 
1098  // get a handle to a memory location where the target state
1099  // would like us to write this material variable into.
1100  T* target_mesh_field = nullptr;
1101  target_state_.mesh_get_data(ONWHAT, trgvarname, &target_mesh_field);
1102 
1103  // perform part-by-part interpolation
1104  assert(ONWHAT == Entity_kind::CELL && partition != nullptr);
1105 
1106  // 1. Do some basic checks on supplied source and target parts
1107  // to prevent bugs when interpolating values:
1108  // check that each entity id is within the
1109  // mesh entity index space.
1110  auto const& source_part = partition->source();
1111  auto const& target_part = partition->target();
1112 
1113 #ifdef DEBUG
1114  int const& max_source_id = source_mesh_.num_entities(ONWHAT, ALL);
1115  int const& max_target_id = target_mesh_.num_entities(ONWHAT, ALL);
1116 
1117  Portage::for_each(source_part.cells().begin(),
1118  source_part.cells().end(),
1119  [&](int current){ assert(current <= max_source_id); });
1120 
1121  Portage::for_each(target_part.cells().begin(),
1122  target_part.cells().end(),
1123  [&](int current){ assert(current <= max_target_id); });
1124 #endif
1125 
1126  int const target_part_size = target_part.size();
1127 
1128  // 2. Filter intersection weights list.
1129  // To restrict interpolation only to source-target parts, we need
1130  // to filter the intersection weights list to keep only that of the
1131  // entities of the source part. Notice that this step can be avoided
1132  // when the part-by-part intersection is implemented.
1133 
1134  auto filter_weights = [&](int entity) {
1135  // For a given target entity, we aim to filter its source weights
1136  // list to keep only those which are in the source part list.
1137  // that way, we ensure that only the contribution of source part entities
1138  // weights are taken into account when doing the interpolation.
1139  // For that, we just iterate on the related weight list, and add the
1140  // current couple of entity/weights if it belongs to the source part.
1141  // nb: 'auto' may imply unexpected behavior with thrust enabled.
1142  entity_weights_t const& entity_weights = sources_and_weights[entity];
1143  entity_weights_t heap;
1144  heap.reserve(10); // size of a local vicinity
1145  for (auto&& weight : entity_weights) {
1146  // constant-time lookup in average case.
1147  if(source_part.contains(weight.entityID)) {
1148  heap.emplace_back(weight);
1149  }
1150  }
1151  heap.shrink_to_fit();
1152  return heap;
1153  };
1154 
1155  Portage::vector<entity_weights_t> parts_weights(target_part_size);
1156  Portage::transform(target_part.cells().begin(),
1157  target_part.cells().end(),
1158  parts_weights.begin(), filter_weights);
1159 
1160  // 3. Process interpolation.
1161  // Now that intersection weights is filtered, perform the interpolation.
1162  // Notice that we need to store the interpolated values in a temporary
1163  // array since they are indexed with respect to the target part
1164  // and not to the target mesh. Hence we need to copy them back in the
1165  // target state at their correct (absolute index) memory locations.
1166  T temporary_storage[target_part_size];
1167  Portage::pointer<T> target_part_field(temporary_storage);
1168 
1169  Portage::transform(target_part.cells().begin(),
1170  target_part.cells().end(),
1171  parts_weights.begin(), target_part_field, interpolator);
1172 
1173  for (int i=0; i < target_part_size; ++i) {
1174  auto const& j = target_part.cells()[i];
1175  target_mesh_field[j] = target_part_field[i];
1176  }
1177  }
1178 
1179 
1180 #ifdef HAVE_TANGRAM
1181 
1211  template<typename T = double,
1212  template<int, Entity_kind, class, class, class, class, class,
1213  template<class, int, class, class> class,
1214  class, class, class> class Interpolate,
1215  Entity_kind ONWHAT1 = ONWHAT,
1216  typename = typename std::enable_if<ONWHAT1 == CELL>::type>
1217  void
1218  interpolate_mat_var(std::string srcvarname, std::string trgvarname,
1219  std::vector<Portage::vector<std::vector<Weights_t>>> const& sources_and_weights_by_mat,
1220  std::vector<Portage::vector<Vector<D>>>* gradients = nullptr) {
1221 
1222  using Interpolator = Interpolate<D, ONWHAT,
1223  SourceMesh, TargetMesh,
1224  SourceState, TargetState,
1225  T,
1226  InterfaceReconstructorType,
1227  Matpoly_Splitter, Matpoly_Clipper, CoordSys>;
1228 
1229  Interpolator interpolator(source_mesh_, target_mesh_,
1230  source_state_, num_tols_,
1231  interface_reconstructor_);
1232 
1233  int const nmats = source_state_.num_materials();
1234 
1235  for (int m = 0; m < nmats; m++) {
1236 
1237  interpolator.set_material(m); // We have to do this so we know
1238  // // which material values we have
1239  // // to grab from the source state
1240 
1241  auto mat_grad = (gradients != nullptr ? &((*gradients)[m]) : nullptr);
1242  // FEATURE ;-) Have to set interpolation variable AFTER setting
1243  // the material for multimaterial variables
1244  interpolator.set_interpolation_variable(srcvarname, mat_grad);
1245 
1246  // if the material has no cells on this partition, then don't bother
1247  // interpolating MM variables
1248  if (target_state_.mat_get_num_cells(m) == 0) continue;
1249 
1250  std::vector<int> matcellstgt;
1251  target_state_.mat_get_cells(m, &matcellstgt);
1252 
1253  // Get a handle to a memory location where the target state
1254  // would like us to write this material variable into. If it is
1255  // NULL, we allocate it ourself
1256 
1257  T *target_field_raw;
1258  target_state_.mat_get_celldata(trgvarname, m, &target_field_raw);
1259  assert (target_field_raw != nullptr);
1260 
1261  Portage::pointer<T> target_field(target_field_raw);
1262 
1263  Portage::transform(matcellstgt.begin(), matcellstgt.end(),
1264  sources_and_weights_by_mat[m].begin(),
1265  target_field, interpolator);
1266 
1267  // If the state wrapper knows that the target data is already
1268  // laid out in this way and it gave us a pointer to the array
1269  // where the values reside, it has to do nothing in this
1270  // call. If the storage format is different, however, it may
1271  // have to copy the values into their proper locations
1272 
1273  target_state_.mat_add_celldata(trgvarname, m, target_field_raw);
1274  } // over all mats
1275 
1276  } // CoreDriver::interpolate_mat_var
1277 
1278 #endif // HAVE_TANGRAM
1279 
1280 
1289  bool
1290  check_mismatch(Portage::vector<std::vector<Weights_t>> const& source_weights) {
1291 
1292  // Instantiate mismatch fixer for later use
1293  if (not mismatch_fixer_) {
1294  // Intel 18.0.1 does not recognize std::make_unique even with -std=c++14 flag *ugh*
1295  // mismatch_fixer_ = std::make_unique<MismatchFixer<D, ONWHAT,
1296  // SourceMesh, SourceState,
1297  // TargetMesh, TargetState>
1298  // >
1299  // (source_mesh_, source_state_, target_mesh_, target_state_,
1300  // source_weights, executor_);
1301 
1302  mismatch_fixer_ = std::unique_ptr<MismatchFixer<D, ONWHAT,
1303  SourceMesh, SourceState,
1304  TargetMesh, TargetState>
1305  >(new MismatchFixer<D, ONWHAT,
1306  SourceMesh, SourceState,
1307  TargetMesh, TargetState>
1308  (source_mesh_, source_state_, target_mesh_, target_state_,
1309  executor_));
1310  }
1311 
1312  return mismatch_fixer_->check_mismatch(source_weights);
1313  }
1314 
1315 
1321  bool
1323  assert(mismatch_fixer_ && "check_mismatch must be called first!");
1324  return mismatch_fixer_->has_mismatch();
1325  }
1326 
1356  bool fix_mismatch(std::string const & src_var_name,
1357  std::string const & trg_var_name,
1358  double global_lower_bound = -std::numeric_limits<double>::max(),
1359  double global_upper_bound = std::numeric_limits<double>::max(),
1360  double conservation_tol = 1e2*std::numeric_limits<double>::epsilon(),
1361  int maxiter = 5,
1362  Partial_fixup_type partial_fixup_type =
1364  Empty_fixup_type empty_fixup_type =
1366 
1367  assert(mismatch_fixer_ && "check_mismatch must be called first!");
1368 
1369  if (source_state_.field_type(ONWHAT, src_var_name) ==
1370  Field_type::MESH_FIELD)
1371  return mismatch_fixer_->fix_mismatch(src_var_name, trg_var_name,
1372  global_lower_bound, global_upper_bound,
1373  conservation_tol, maxiter,
1374  partial_fixup_type, empty_fixup_type);
1375  return false;
1376  }
1377 
1378  private:
1379  SourceMesh const & source_mesh_;
1380  TargetMesh const & target_mesh_;
1381  SourceState const & source_state_;
1382  TargetState & target_state_;
1383 
1384  NumericTolerances_t num_tols_ = DEFAULT_NUMERIC_TOLERANCES<D>;
1385 
1386  int comm_rank_ = 0;
1387  int nprocs_ = 1;
1388 
1389  Wonton::Executor_type const *executor_;
1390 
1391 #ifdef PORTAGE_ENABLE_MPI
1392  MPI_Comm mycomm_ = MPI_COMM_NULL;
1393 #endif
1394 
1395 #ifdef HAVE_TANGRAM
1396 
1397  // The following tolerances as well as the all-convex flag are
1398  // required for the interface reconstructor driver. The size of the
1399  // tols vector is currently set to two since MOF requires two
1400  // different set of tolerances to match the 0th-order and 1st-order
1401  // moments. VOF on the other does not require the second tolerance.
1402  // If a new IR method which requires tolerances for higher moment is
1403  // added to Tangram, then this vector size should be
1404  // generalized. The boolean all_convex flag is to specify if a mesh
1405  // contains only convex cells and set to true in that case.
1406  //
1407  // There is an associated method called
1408  // set_interface_reconstructor_options that should be invoked to set
1409  // user-specific values. Otherwise, the remapper will use the
1410  // default values.
1411 
1412  std::vector<Tangram::IterativeMethodTolerances_t> reconstructor_tols_;
1413  bool reconstructor_all_convex_ = true;
1414 
1415  // Pointer to the interface reconstructor object (required by the
1416  // interface to be shared)
1417  std::shared_ptr<Tangram::Driver<InterfaceReconstructorType, D,
1418  SourceMesh,
1419  Matpoly_Splitter, Matpoly_Clipper>
1420  > interface_reconstructor_;
1421 
1422 
1423  // Convert volume fraction and centroid data from compact
1424  // material-centric to compact cell-centric (ccc) form as needed
1425  // by Tangram
1426  void ccc_vfcen_data(std::vector<int>& cell_num_mats,
1427  std::vector<int>& cell_mat_ids,
1428  std::vector<double>& cell_mat_volfracs,
1429  std::vector<Wonton::Point<D>>& cell_mat_centroids) {
1430 
1431  int nsourcecells = source_mesh_.num_entities(CELL,
1432  ALL);
1433 
1434  int nmats = source_state_.num_materials();
1435  cell_num_mats.assign(nsourcecells, 0);
1436 
1437  // First build full arrays (as if every cell had every material)
1438 
1439  std::vector<int> cell_mat_ids_full(nsourcecells*nmats, -1);
1440  std::vector<double> cell_mat_volfracs_full(nsourcecells*nmats, 0.0);
1441  std::vector<Wonton::Point<D>> cell_mat_centroids_full(nsourcecells*nmats);
1442 
1443  bool have_centroids = true;
1444  int nvals = 0;
1445  for (int m = 0; m < nmats; m++) {
1446  std::vector<int> cellids;
1447  source_state_.mat_get_cells(m, &cellids);
1448  for (int c : cellids) {
1449  int nmatc = cell_num_mats[c];
1450  cell_mat_ids_full[c*nmats+nmatc] = m;
1451  cell_num_mats[c]++;
1452  }
1453  nvals += cellids.size();
1454 
1455  double const * matfracptr;
1456  source_state_.mat_get_celldata("mat_volfracs", m, &matfracptr);
1457  int const num_cell_ids = cellids.size();
1458  for (int ic = 0; ic < num_cell_ids; ic++)
1459  cell_mat_volfracs_full[cellids[ic]*nmats+m] = matfracptr[ic];
1460 
1461  Wonton::Point<D> const *matcenvec;
1462 
1463  // handle the case where we don't have centroids in the state manager at all
1464  if (source_state_.get_entity("mat_centroids")==Entity_kind::UNKNOWN_KIND) {
1465  have_centroids = false;
1466  continue;
1467  }
1468 
1469  source_state_.mat_get_celldata("mat_centroids", m, &matcenvec);
1470  if (cellids.size() && !matcenvec) {
1471  have_centroids = false; // VOF
1472  } else {
1473  for (int ic = 0; ic < num_cell_ids; ic++)
1474  cell_mat_centroids_full[cellids[ic]*nmats+m] = matcenvec[ic];
1475  }
1476  }
1477 
1478  // At this point nvals contains the number of non-zero volume
1479  // fraction entries in the full array. Use this and knowledge of
1480  // number of materials in each cell to compress the data into
1481  // linear arrays
1482 
1483  cell_mat_ids.resize(nvals);
1484  cell_mat_volfracs.resize(nvals);
1485  cell_mat_centroids.resize(nvals); // dummy vals for VOF
1486 
1487  int idx = 0;
1488  for (int c = 0; c < nsourcecells; c++) {
1489  for (int m = 0; m < cell_num_mats[c]; m++) {
1490  int matid = cell_mat_ids_full[c*nmats+m];
1491  cell_mat_ids[idx] = matid;
1492  cell_mat_volfracs[idx] = cell_mat_volfracs_full[c*nmats+matid];
1493  if (have_centroids)
1494  cell_mat_centroids[idx] = cell_mat_centroids_full[c*nmats+matid];
1495  idx++;
1496  }
1497  }
1498  }
1499 
1500 #endif
1501 
1502  std::unique_ptr<MismatchFixer<D, ONWHAT,
1503  SourceMesh, SourceState,
1504  TargetMesh, TargetState>> mismatch_fixer_;
1505 
1506 }; // CoreDriver
1507 
1508 
1509 // Core Driver Factory
1510 
1511 template <int D,
1512  class SourceMesh, class SourceState,
1513  class TargetMesh, class TargetState,
1514  template <class, int, class, class> class InterfaceReconstructorType,
1515  class Matpoly_Splitter,
1516  class Matpoly_Clipper,
1517  class CoordSys>
1518 std::unique_ptr<CoreDriverBase<D, SourceMesh, SourceState,
1519  TargetMesh, TargetState,
1520  InterfaceReconstructorType,
1521  Matpoly_Splitter, Matpoly_Clipper,
1522  CoordSys>
1523  >
1525  SourceMesh const & source_mesh,
1526  SourceState const & source_state,
1527  TargetMesh const & target_mesh,
1528  TargetState & target_state,
1529  Wonton::Executor_type const *executor) {
1530  switch (onwhat) {
1531  case CELL:
1532  // Intel 18.0.1 does not recognize std::make_unique even with -std=c++14 flag *ugh*
1533  // return std::make_unique<CoreDriver<D, CELL,
1534  // SourceMesh, SourceState,
1535  // TargetMesh, TargetState,
1536  // InterfaceReconstructorType,
1537  // Matpoly_Splitter, Matpoly_Clipper,
1538  // CoordSys>>
1539  // (source_mesh, source_state, target_mesh, target_state, executor);
1540 
1541  return std::unique_ptr<CoreDriver<D, CELL,
1542  SourceMesh, SourceState,
1543  TargetMesh, TargetState,
1544  InterfaceReconstructorType,
1545  Matpoly_Splitter, Matpoly_Clipper,
1546  CoordSys>>(
1547  new CoreDriver<D, CELL,
1548  SourceMesh, SourceState,
1549  TargetMesh, TargetState,
1550  InterfaceReconstructorType,
1551  Matpoly_Splitter, Matpoly_Clipper,
1552  CoordSys>
1553  (source_mesh, source_state,
1554  target_mesh, target_state,
1555  executor)
1556  );
1557  case NODE:
1558  // Intel 18.0.1 does not recognize std::make_unique even with -std=c++14 flag *ugh*
1559  // return std::make_unique<CoreDriver<D, NODE,
1560  // SourceMesh, SourceState,
1561  // TargetMesh, TargetState,
1562  // InterfaceReconstructorType,
1563  // Matpoly_Splitter, Matpoly_Clipper,
1564  // CoordSys>>
1565  // (source_mesh, source_state, target_mesh, target_state, executor);
1566  return std::unique_ptr<CoreDriver<D, CELL,
1567  SourceMesh, SourceState,
1568  TargetMesh, TargetState,
1569  InterfaceReconstructorType,
1570  Matpoly_Splitter, Matpoly_Clipper,
1571  CoordSys>>(
1572  new CoreDriver<D, CELL,
1573  SourceMesh, SourceState,
1574  TargetMesh, TargetState,
1575  InterfaceReconstructorType,
1576  Matpoly_Splitter, Matpoly_Clipper,
1577  CoordSys>
1578  (source_mesh, source_state,
1579  target_mesh, target_state,
1580  executor)
1581  );
1582  default:
1583  throw std::runtime_error("Remapping on "+Wonton::to_string(onwhat)+" not implemented");
1584  }
1585 } // make_core_driver
1586 
1587 
1588 } // namespace Portage
1589 
1590 #endif // PORTAGE_CORE_DRIVER_H_
Boundary_Limiter_type
Boundary limiter type.
Definition: portage.h:91
Definition: dummy_interface_reconstructor.h:30
void set_num_tols(const double min_absolute_distance, const double min_absolute_volume)
Set core numerical tolerances.
Definition: coredriver.h:635
Definition: fix_mismatch.h:122
std::vector< T > vector
Definition: portage.h:238
OutputIterator transform(InputIterator first, InputIterator last, OutputIterator result, UnaryFunction op)
Definition: portage.h:250
void interpolate_mat_var(std::string srcvarname, std::string trgvarname, std::vector< Portage::vector< std::vector< Weights_t >>> const &sources_and_weights_by_mat, std::vector< Portage::vector< Vector< D >>> *gradients=nullptr)
Definition: coredriver.h:307
bool check_mismatch(Portage::vector< std::vector< Weights_t >> const &source_weights)
Definition: coredriver.h:1290
Intersection and other tolerances to handle tiny values.
Definition: portage.h:152
T * pointer
Definition: portage.h:241
void set_num_tols(const double min_absolute_distance, const double min_absolute_volume)
Set numerical tolerances for small distances and volumes.
Definition: coredriver.h:399
void set_num_tols(const NumericTolerances_t &num_tols)
Set numerical tolerances for small volumes, distances, etc.
Definition: coredriver.h:416
void for_each(InputIterator first, InputIterator last, UnaryFunction f)
Definition: portage.h:264
bool fix_mismatch(std::string const &src_var_name, std::string const &trg_var_name, double global_lower_bound=-std::numeric_limits< double >::max(), double global_upper_bound=std::numeric_limits< double >::max(), double conservation_tol=1e2 *std::numeric_limits< double >::epsilon(), int maxiter=5, Partial_fixup_type partial_fixup_type=Partial_fixup_type::SHIFTED_CONSERVATIVE, Empty_fixup_type empty_fixup_type=Empty_fixup_type::EXTRAPOLATE)
Return if meshes are mismatched (check_mismatch must already have been called)
Definition: coredriver.h:364
Partial_fixup_type
Fixup options for partially filled cells.
Definition: portage.h:114
Compute limited gradient of a field or components of a field.
Definition: gradient.h:52
bool has_mismatch()
Definition: coredriver.h:1322
bool check_mismatch(Portage::vector< std::vector< Weights_t >> const &source_weights)
Check if meshes are mismatched (don&#39;t cover identical portions of space)
Definition: coredriver.h:332
Manages source and target sub-meshes for part-by-part remap.
double const epsilon
Numerical tolerance.
Definition: weight.h:34
Definition: portage.h:85
virtual Entity_kind onwhat()=0
Portage::vector< std::vector< int > > search()
search for candidate source entities whose control volumes (cells, dual cells) overlap the control vo...
Definition: coredriver.h:134
virtual ~CoreDriverBase()=default
Manages source and target sub-meshes for part-by-part remap. It detects boundaries mismatch and provi...
Definition: parts.h:234
void interpolate_mesh_var(std::string srcvarname, std::string trgvarname, Portage::vector< std::vector< Weights_t >> const &sources_and_weights, const PartPair< D, SourceMesh, SourceState, TargetMesh, TargetState > *partition, Portage::vector< Vector< D >> *gradients=nullptr)
Interpolate mesh variable from source part to target part.
Definition: coredriver.h:1075
Limiter_type
Limiter type.
Definition: portage.h:85
bool has_mismatch()
Return if meshes are mismatched (check_mismatch must already have been called)
Definition: coredriver.h:348
void interpolate_mesh_var(std::string srcvarname, std::string trgvarname, Portage::vector< std::vector< Weights_t >> const &sources_and_weights, Portage::vector< Vector< D >> *gradients=nullptr)
Definition: coredriver.h:239
CoreDriver(SourceMesh const &source_mesh, SourceState const &source_state, TargetMesh const &target_mesh, TargetState &target_state, Wonton::Executor_type const *executor=nullptr)
Constructor for the CORE remap driver.
Definition: coredriver.h:521
std::vector< Wonton::Weights_t > entity_weights_t
Definition: parts.h:36
Definition: portage.h:134
Portage::vector< std::vector< int > > search()
Definition: coredriver.h:567
CoreDriverBase - Base class for core driver that is agnostic to the Entity_kind.
Definition: coredriver.h:105
bool fix_mismatch(std::string const &src_var_name, std::string const &trg_var_name, double global_lower_bound=-std::numeric_limits< double >::max(), double global_upper_bound=std::numeric_limits< double >::max(), double conservation_tol=1e2 *std::numeric_limits< double >::epsilon(), int maxiter=5, Partial_fixup_type partial_fixup_type=Partial_fixup_type::SHIFTED_CONSERVATIVE, Empty_fixup_type empty_fixup_type=Empty_fixup_type::EXTRAPOLATE)
Repair the remapped field to account for boundary mismatch.
Definition: coredriver.h:1356
Definition: portage.h:114
Entity_kind onwhat()
What entity kind is this defined on?
Definition: coredriver.h:553
Definition: coredriver.h:42
void set_num_tols(const NumericTolerances_t &num_tols)
Set all numerical tolerances.
Definition: coredriver.h:643
double kernel(const Kernel kern, double x)
General kernel function.
Definition: weight.h:313
std::unique_ptr< CoreDriverBase< D, SourceMesh, SourceState, TargetMesh, TargetState, InterfaceReconstructorType, Matpoly_Splitter, Matpoly_Clipper, CoordSys > > make_core_driver(Entity_kind onwhat, SourceMesh const &source_mesh, SourceState const &source_state, TargetMesh const &target_mesh, TargetState &target_state, Wonton::Executor_type const *executor)
Definition: coredriver.h:1524
std::vector< Portage::vector< std::vector< Portage::Weights_t > > > intersect_materials(Portage::vector< std::vector< int >> const &intersection_candidates)
Definition: coredriver.h:185
Definition: portage.h:91
Portage::vector< std::vector< Portage::Weights_t > > intersect_meshes(Portage::vector< std::vector< int >> const &intersection_candidates)
intersect target entities with candidate source entities
Definition: coredriver.h:159
Portage::vector< Vector< D > > compute_source_gradient(std::string const field_name, Limiter_type limiter_type=NOLIMITER, Boundary_Limiter_type boundary_limiter_type=BND_NOLIMITER, int material_id=0, const Part< SourceMesh, SourceState > *source_part=nullptr) const
Compute the gradient field of the given variable on source mesh.
Definition: coredriver.h:909
void Intersect(const IsotheticBBox< D > &box, const KDTree< D > *kdtree, std::vector< int > &pfound)
Definition: kdtree.h:439
CoreDriver - Core driver that remaps fields on a particular Entity_kind (ONWHAT) like CELL or NODE...
Definition: coredriver.h:64
std::string to_string(Limiter_type limiter_type)
Definition: portage.h:96
Portage::vector< Vector< D > > compute_source_gradient(std::string const field_name, Limiter_type limiter_type=NOLIMITER, Boundary_Limiter_type boundary_limiter_type=BND_NOLIMITER, int material_id=0, const Part< SourceMesh, SourceState > *source_part=nullptr)
Compute the gradient field of the given variable on source mesh.
Definition: coredriver.h:201
Empty_fixup_type
Fixup options for empty cells.
Definition: portage.h:134