gradient.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_GRADIENT_H_
8 #define PORTAGE_INTERPOLATE_GRADIENT_H_
9 
10 #include <algorithm>
11 #include <stdexcept>
12 #include <string>
13 #include <vector>
14 #include <iostream>
15 
19 #include "portage/driver/parts.h"
20 
21 #include "wonton/support/lsfits.h"
22 #include "wonton/support/Point.h"
23 #include "wonton/support/Vector.h"
24 
25 #ifdef HAVE_TANGRAM
26  #include "tangram/driver/driver.h"
27  #include "tangram/driver/CellMatPoly.h"
28  #include "tangram/support/MatPoly.h"
29 #endif
30 
31 namespace Portage {
32 
33  using Wonton::Point;
34  using Wonton::Vector;
35 
43  template<
44  int D, Entity_kind on_what,
45  typename Mesh, typename State,
46  template<class, int, class, class>
47  class InterfaceReconstructorType = DummyInterfaceReconstructor,
48  class Matpoly_Splitter = void,
49  class Matpoly_Clipper = void,
50  class CoordSys = Wonton::DefaultCoordSys
51  >
53 
54  // useful aliases
55 #ifdef HAVE_TANGRAM
56  using InterfaceReconstructor =
57  Tangram::Driver<
58  InterfaceReconstructorType, D, Mesh,
59  Matpoly_Splitter, Matpoly_Clipper
60  >;
61 #endif
62 
63  public:
76  Limited_Gradient(Mesh const& mesh, State const& state,
77  std::string const var_name,
78  Limiter_type limiter_type,
79  Boundary_Limiter_type boundary_limiter_type,
80  const Part<Mesh, State>* part = nullptr)
81  : mesh_(mesh),
82  state_(state),
83  values_(nullptr),
84  variable_name_(var_name),
85  limiter_type_(limiter_type),
86  boundary_limiter_type_(boundary_limiter_type) {}
87 
88 #ifdef HAVE_TANGRAM
89  Limited_Gradient(Mesh const &mesh, State const &state,
90  std::string const var_name,
91  Limiter_type limiter_type,
92  Boundary_Limiter_type boundary_limiter_type,
93  std::shared_ptr<InterfaceReconstructor> ir,
94  const Part<Mesh, State>* part = nullptr)
95  : mesh_(mesh),
96  state_(state),
97  values_(nullptr),
98  variable_name_(var_name),
99  limiter_type_(limiter_type),
100  boundary_limiter_type_(boundary_limiter_type) {}
101 #endif
102 
103  // Assignment operator (disabled)
105 
106  // Destructor
107  ~Limited_Gradient() = default;
108 
109  // Functor - not implemented for all types - see specialization for
110  // cells, nodes
111  Vector<D> operator()(int entity_id) {
112  std::cerr << "Limited gradient not implemented for this entity kind";
113  std::cerr << std::endl;
114  }
115 
116  private:
117  Mesh const& mesh_;
118  State const& state_;
119  double const* values_;
120  std::string variable_name_ = "";
121  Limiter_type limiter_type_ = DEFAULT_LIMITER;
122  Boundary_Limiter_type boundary_limiter_type_ = DEFAULT_BND_LIMITER;
123  Field_type field_type_ = Field_type::UNKNOWN_TYPE_FIELD;
124  int material_id_ = 0;
125  };
126 
128 
136  template<
137  int D,
138  typename Mesh,
139  typename State,
140  template<class, int, class, class>
141  class InterfaceReconstructorType,
142  class Matpoly_Splitter, class Matpoly_Clipper, class CoordSys
143  >
145  D, Entity_kind::CELL,
146  Mesh, State,
147  InterfaceReconstructorType,
148  Matpoly_Splitter, Matpoly_Clipper, CoordSys
149  > {
150 
151  // useful aliases
152 #ifdef HAVE_TANGRAM
153  using InterfaceReconstructor =
154  Tangram::Driver<
155  InterfaceReconstructorType, D, Mesh,
156  Matpoly_Splitter, Matpoly_Clipper
157  >;
158 #endif
159 
160  public:
161  //Constructor for single material remap
162  Limited_Gradient(Mesh const& mesh,
163  State const& state,
164  std::string var_name,
165  Limiter_type limiter_type,
166  Boundary_Limiter_type boundary_limiter_type,
167  const Part<Mesh, State>* part = nullptr)
168  : mesh_(mesh),
169  state_(state),
170  values_(nullptr),
171  variable_name_(var_name),
172  limiter_type_(limiter_type),
173  boundary_limiter_type_(boundary_limiter_type),
174  part_(part) {
175 
176  // Collect and keep the list of neighbors for each OWNED CELL as
177  // it is common to gradient computation of any field variable.
178  // We don't collect neighbors of GHOST CELLs because the outer
179  // ghost layer (even if it is a single layer) will not have
180  // neighbors on the outer side and therefore, will not yield the
181  // right gradient anyway
182 
183  int const nb_cells = mesh_.num_entities(Entity_kind::CELL,
184  Entity_type::PARALLEL_OWNED);
185  cell_neighbors_.resize(nb_cells);
186 
187  if (part_ == nullptr) /* entire mesh */ {
188  auto collect_neighbors = [this](int c) {
189  mesh_.cell_get_node_adj_cells(c, Entity_type::ALL,
190  &(cell_neighbors_[c]));
191  };
192 
193  Portage::for_each(mesh_.begin(Entity_kind::CELL,
194  Entity_type::PARALLEL_OWNED),
195  mesh_.end(Entity_kind::CELL,
196  Entity_type::PARALLEL_OWNED),
197  collect_neighbors);
198  } else /* only on source part */ {
199  auto filter_neighbors = [this](int c) {
200  cell_neighbors_[c] = part_->get_neighbors(c);
201  };
202 
203  auto const& part_cells = part_->cells();
204  Portage::for_each(part_cells.begin(), part_cells.end(), filter_neighbors);
205  }
206 
207  set_interpolation_variable(var_name, limiter_type, boundary_limiter_type);
208  }
209 
210 #ifdef HAVE_TANGRAM
211  // Constructor with interface reconstructor for multimaterial remaps.
212  Limited_Gradient(Mesh const& mesh,
213  State const& state,
214  std::string const& var_name,
215  Limiter_type limiter_type,
216  Boundary_Limiter_type boundary_limiter_type,
217  std::shared_ptr<InterfaceReconstructor> ir,
218  const Part<Mesh, State>* part = nullptr)
219  : mesh_(mesh),
220  state_(state),
221  values_(nullptr),
222  variable_name_(var_name),
223  limiter_type_(limiter_type),
224  boundary_limiter_type_(boundary_limiter_type),
225  interface_reconstructor_(ir),
226  part_(part) {
227 
228  // Collect and keep the list of neighbors for each OWNED CELL as
229  // it is common to gradient computation of any field variable.
230  // We don't collect neighbors of GHOST CELLs because the outer
231  // ghost layer (even if it is a single layer) will not have
232  // neighbors on the outer side and therefore, will not yield the
233  // right gradient anyway
234 
235  int const nb_cells = mesh_.num_entities(Entity_kind::CELL,
236  Entity_type::PARALLEL_OWNED);
237  cell_neighbors_.resize(nb_cells);
238 
239  if (part_ == nullptr) /* entire mesh */ {
240  auto collect_neighbors = [this](int c) {
241  mesh_.cell_get_node_adj_cells(c, Entity_type::ALL, &(cell_neighbors_[c]));
242  };
243 
244  Portage::for_each(mesh_.begin(Entity_kind::CELL,
245  Entity_type::PARALLEL_OWNED),
246  mesh_.end(Entity_kind::CELL,
247  Entity_type::PARALLEL_OWNED),
248  collect_neighbors);
249 
250  } else /* only on source part */ {
251  auto filter_neighbors = [this](int c) {
252  cell_neighbors_[c] = part_->get_neighbors(c);
253  };
254 
255  auto const& part_cells = part_->cells();
256  Portage::for_each(part_cells.begin(), part_cells.end(), filter_neighbors);
257  }
258 
259  //If the field type is a MESH_FIELD, then the corresponding data will
260  //be stored. If the field_type is a MULTIMATERIAL_FIELD, then the constructor
261  //only stores the variable name. The user code must make a call to the method
262  //set_material to store the material-wise data.
263  set_interpolation_variable(var_name, limiter_type, boundary_limiter_type);
264  }
265 #endif
266 
267  //This method should be called by the user if the field type is MULTIMATERIAL_FIELD.
268  //As the constructor with interface reconstructor only sets the variable name
269  //for such fields, this method is needed to properly set the multimaterial data local
270  //to the routine.
271  void set_material(int matid) {
272  material_id_ = matid;
273  // Extract the field data from the state manager
274  if (field_type_ != Field_type::MESH_FIELD) {
275  state_.mat_get_celldata(variable_name_, material_id_, &values_);
276  }
277  }
278 
279  void set_interpolation_variable(std::string variable_name,
280  Limiter_type limiter_type,
281  Boundary_Limiter_type boundary_limiter_type) {
282 
283  variable_name_ = variable_name;
284  limiter_type_ = limiter_type;
285  boundary_limiter_type_ = boundary_limiter_type;
286 
287  // Extract the field data from the state manager
288  field_type_ = state_.field_type(Entity_kind::CELL, variable_name_);
289  if (field_type_ == Field_type::MESH_FIELD) {
290  state_.mesh_get_data(Entity_kind::CELL, variable_name_, &values_);
291  }
292  }
293 
294  // @brief Implementation of Limited_Gradient functor for CELLs
295  Vector<D> operator()(int cellid) {
296 
297  assert(values_);
298  assert(mesh_.cell_get_type(cellid) == Entity_type::PARALLEL_OWNED);
299 
300  double phi = 1.0;
301  Vector<D> grad;
302 
303  // check that cell is within the part if part-by-part requested
304  if (part_ != nullptr && !part_->contains(cellid)) {
305  grad.zero();
306  return grad;
307  }
308 
309  // useful predicates
310  bool is_boundary_cell = mesh_.on_exterior_boundary(Entity_kind::CELL, cellid);
311  bool apply_limiter = limiter_type_ == BARTH_JESPERSEN &&
312  (!is_boundary_cell || boundary_limiter_type_ == BND_BARTH_JESPERSEN);
313 
314  // Limit the boundary gradient to enforce monotonicity preservation
315  if (is_boundary_cell && boundary_limiter_type_ == BND_ZERO_GRADIENT) {
316  grad.zero();
317  return grad;
318  }
319 
320  // Include cell where grad is needed as first element
321  std::vector<int> neighbors{cellid};
322 
323  if (!cell_neighbors_.empty()) {
324  neighbors.insert(std::end(neighbors),
325  std::begin(cell_neighbors_[cellid]),
326  std::end(cell_neighbors_[cellid]));
327  }
328 
329  std::vector<Point<D>> list_coords;
330  std::vector<double> list_values;
331 
332  // Loop over cell where grad is needed and its neighboring cells
333  for (auto&& neigh_global : neighbors) {
334 #ifdef HAVE_TANGRAM
335  // Field values for each cells in each material are stored according to
336  // the material's cell list. So, get the local index of each neighbor cell
337  // in the material cell list to access the correct field value
338  int const neigh_local = (field_type_ == Field_type::MESH_FIELD)
339  ? neigh_global
340  : state_.cell_index_in_material(neigh_global, material_id_);
341 
342  // In case of material-data, we need to check that neighbors contain
343  // material of interest (i.e. have valid local id);
344  // in the case of mesh data, this is always true, since local cellid
345  // (neigh_local) is equal to global cellid (neigh_global).
346  // nota bene: cell_index_in_material can return -1.
347  if (neigh_local >= 0) {
348  std::vector<int> cell_mats;
349  state_.cell_get_mats(neigh_global, &cell_mats);
350  int const nb_mats = cell_mats.size();
351 
352  if (nb_mats > 1 && interface_reconstructor_) /* multi-material cell */ {
353  // Get cell's cellmatpoly
354  auto cell_matpoly = interface_reconstructor_->cell_matpoly_data(neigh_global);
355 
356  // Collect all the matpolys in this cell for the material of interest
357  auto matpolys = cell_matpoly.get_matpolys(material_id_);
358 
359  // If there are multiple matpolys in this cell for the material of interest,
360  // aggregate moments to compute new centroid
361  double mvol = 0.0;
362  Point<D> centroid;
363  for (auto&& poly : matpolys) {
364  auto moments = poly.moments();
365  mvol += moments[0];
366  for (int k = 0; k < D; k++)
367  centroid[k] += moments[k + 1];
368  }
369 
370  // There are cases where r3d returns a single zero volume poly which
371  // ultimately produces a nan, so here we are explicitly filtering this
372  // case.
373  if (mvol==0.) continue;
374 
375  for (int k = 0; k < D; k++)
376  centroid[k] /= mvol;
377 
378  list_coords.push_back(centroid);
379 
380  // Populate least squares vectors with centroid for material
381  // of interest and field value in the current cell for that material
382  list_values.push_back(values_[neigh_local]);
383  } else if (nb_mats == 1) /* single-material cell */ {
384 
385  // Ensure that the single material is the material of interest
386  if (cell_mats[0] == material_id_) {
387  // Get the cell-centered value for this material
388  Point<D> centroid;
389  mesh_.cell_centroid(neigh_global, &centroid);
390  list_coords.push_back(centroid);
391  list_values.push_back(values_[neigh_local]);
392  }
393  }
394  }
395 #endif
396  // If we get here, we must have mesh data which is cell-centered
397  // and not dependent on material, so just get the centroid and value
398  if (field_type_ == Field_type::MESH_FIELD) {
399  Point<D> centroid;
400  mesh_.cell_centroid(neigh_global, &centroid);
401  list_coords.push_back(centroid);
402  list_values.push_back(values_[neigh_global]);
403  }
404  }
405 
406  grad = Wonton::ls_gradient<D, CoordSys>(list_coords, list_values);
407 
408  // Limit the gradient to enforce monotonicity preservation
409  if (apply_limiter) {
410 
411  phi = 1.0;
412 
413  // Min and max vals of function (cell centered vals) among neighbors
414  // and the cell itself
416  double minval = list_values[0];
417  double maxval = list_values[0];
418  double cellcenval = list_values[0];
419 
420  // Find min and max values among all neighbors (exlude the first element
421  // in nbrids because it corresponds to the cell itself, not a neighbor)
422  int const nb_values = list_values.size();
423  for (int i = 1; i < nb_values; ++i) {
424  minval = std::min(list_values[i], minval);
425  maxval = std::max(list_values[i], maxval);
426  }
427 
428  /* Per page 278 of [Kucharik, M. and Shaskov, M, "Conservative
429  Multi-material Remap for Staggered Multi-material Arbitrary
430  Lagrangian-Eulerian Methods," Journal of Computational Physics,
431  v 258, pp. 268-304, 2014], if a cell is a multimaterial cell and the
432  field is a material field, then the min value (for density, at
433  least) should be set to 0 and the max value to infinity (or a large
434  number), so that we don't end up limiting the gradient to 0 and drop
435  down to 1st order. But we don't know if a variable is density (don't
436  want to do silly things like string comparison) or pressure or
437  something else? What if we limit pressure to 0 and it should
438  actually be allowed to go -ve? In the end, along with the limiter
439  type, the application should be able to tell Portage the global
440  bounds that a variable has to satisfy. Then we can impose the global
441  limits at multi-material cells and boundary cells without limiting
442  the gradient to 0. */
443 
444  // Find the min and max of the reconstructed function in the cell
445  // Since the reconstruction is linear, this will occur at one of
446  // the nodes of the cell. So find the values of the reconstructed
447  // function at the nodes of the cell
448  std::vector<Point<D>> cellcoords;
449  mesh_.cell_get_coordinates(cellid, &cellcoords);
450 
451  for (auto&& coord : cellcoords) {
452  auto vec = coord - list_coords[0];
453  double diff = dot(grad, vec);
454  double extremeval = (diff > 0.) ? maxval : minval;
455  double phi_new = (diff == 0. ? 1. : (extremeval - cellcenval) / diff);
456  phi = std::min(phi_new, phi);
457  }
458  }
459 
460  // Limited gradient is phi*grad
461  return phi * grad;
462  }
463 
464  private:
465  Mesh const& mesh_;
466  State const& state_;
467  double const* values_;
468  std::string variable_name_ = "";
469  Limiter_type limiter_type_ = DEFAULT_LIMITER;
470  Boundary_Limiter_type boundary_limiter_type_ = DEFAULT_BND_LIMITER;
471  Field_type field_type_ = Field_type::UNKNOWN_TYPE_FIELD;
472 
473  int material_id_ = 0;
474  std::vector<int> cell_ids_;
475  std::vector<std::vector<int>> cell_neighbors_;
476 #ifdef HAVE_TANGRAM
477  std::shared_ptr<InterfaceReconstructor> interface_reconstructor_;
478 #endif
479  Part<Mesh, State> const* part_;
480  };
481 
483 
490  template<
491  int D,
492  typename Mesh,
493  typename State,
494  template<class, int, class, class>
495  class InterfaceReconstructorType,
496  class Matpoly_Splitter, class Matpoly_Clipper, class CoordSys
497  >
499  D, Entity_kind::NODE,
500  Mesh, State,
501  InterfaceReconstructorType,
502  Matpoly_Splitter, Matpoly_Clipper, CoordSys
503  > {
504 
505 #ifdef HAVE_TANGRAM
506  using InterfaceReconstructor =
507  Tangram::Driver<
508  InterfaceReconstructorType, D, Mesh,
509  Matpoly_Splitter, Matpoly_Clipper
510  >;
511 #endif
512 
513  public:
523  Limited_Gradient(Mesh const& mesh,
524  State const& state,
525  std::string var_name,
526  Limiter_type limiter_type,
527  Boundary_Limiter_type boundary_limiter_type,
528  const Part<Mesh, State>* part = nullptr)
529  : mesh_(mesh),
530  state_(state),
531  values_(nullptr),
532  variable_name_(var_name),
533  limiter_type_(limiter_type),
534  boundary_limiter_type_(boundary_limiter_type) {
535 
536  auto collect_node_neighbors = [this](int n) {
537  this->mesh_.dual_cell_get_node_adj_cells(
538  n, Entity_type::ALL, &(node_neighbors_[n])
539  );
540  };
541 
542  // Collect and keep the list of neighbors for each OWNED or
543  // GHOST as it is common to gradient computation of any field
544  // variable.
545  // NOTE:*******************************************************
546  // The iteration for node (or dual cell) gradients is
547  // purposefully different from that of cells. For cells, we
548  // collect neighbors of only OWNED source cells because we will
549  // compute gradients only over OWNED source cells because our
550  // parallel scheme mandates that any target cell overlap only
551  // OWNED source cells (even if we have to duplicate those source
552  // cells on multiple partitions as we do when we
553  // redistribute). With nodes, we have to compute the gradient
554  // over ALL (OWNED+GHOST) nodes. This is because, even with the
555  // above requirement on overlap of OWNED target and source
556  // cells, the dual cells of a target node can overlap the dual
557  // cell of GHOST source node on a partition boundary and we want
558  // the gradient at that ghost node.
559  //
560  // Anyway, this is a bit moot, because we cannot guarantee
561  // second-order accuracy for remap of node-centered variables in
562  // anything other than uniform regular meshes since the linear
563  // reconstruction is supposed to be over the centroid while our
564  // field variables are at nodes which may not be coincident with
565  // the centroid. [PERHAPS THIS WILL GET FIXED IF WE ARE ABLE TO
566  // DO A CONSERVATIVE RECONSTRUCTION AROUND ANY POINT NOT JUST
567  // THE CENTROID]
568  //
569  // Also, the only node centered variables in the codes we are
570  // dealing with are likely to be velocity and one never remaps
571  // velocity directly anyway - we remap momentum in a
572  // conservative and consistent way by transferring momentum to
573  // cell centers, remapping cell centered momentum and
574  // transferring it back to nodes and backing out velocity.
575  //
576  // Iterating over ALL nodes (or dual control volumes) just keeps
577  // us from making a grosser error at partition boundaries
578 
579  int const nnodes = mesh_.num_entities(Entity_kind::NODE,
580  Entity_type::ALL);
581  node_neighbors_.resize(nnodes);
582  Portage::for_each(mesh_.begin(Entity_kind::NODE,
583  Entity_type::ALL),
584  mesh_.end(Entity_kind::NODE,
585  Entity_type::ALL),
586  collect_node_neighbors);
587 
588  set_interpolation_variable(var_name, limiter_type, boundary_limiter_type);
589  }
590 
591 #ifdef HAVE_TANGRAM
592 
602  Limited_Gradient(Mesh const& mesh,
603  State const& state,
604  std::string const& var_name,
605  Limiter_type limiter_type,
606  Boundary_Limiter_type boundary_limiter_type,
607  std::shared_ptr<InterfaceReconstructor> ir,
608  const Part<Mesh, State>* part = nullptr)
609  : Limited_Gradient(mesh, state, var_name, limiter_type, boundary_limiter_type) {
610 
611  if (part != nullptr) {
612  std::cerr << "Sorry, part-by-part remap is only defined ";
613  std::cerr << "for cell-centered field, will be ignored." << std::endl;
614  }
615  }
616 #endif
617 
618  void set_material(int material_id) { material_id_ = material_id; }
619 
620  void set_interpolation_variable(std::string const& variable_name,
621  Limiter_type limiter_type,
622  Boundary_Limiter_type boundary_limiter_type) {
623 
624  variable_name_ = variable_name;
625  limiter_type_ = limiter_type;
626  boundary_limiter_type_ = boundary_limiter_type;
627  state_.mesh_get_data(Entity_kind::NODE, variable_name_, &values_);
628  }
629 
630  // @brief Limited gradient functor implementation for NODE
631  Vector<D> operator()(int nodeid) {
632 
633  assert(values_);
634 
635  double phi = 1.0;
636  Vector<D> grad;
637 
638  bool is_boundary_node = mesh_.on_exterior_boundary(Entity_kind::NODE, nodeid);
639  bool apply_limiter = limiter_type_ == BARTH_JESPERSEN &&
640  (!is_boundary_node
641  || boundary_limiter_type_ == BND_BARTH_JESPERSEN);
642 
643  if (is_boundary_node && boundary_limiter_type_ == BND_ZERO_GRADIENT) {
644  grad.zero();
645  return grad;
646  }
647 
648  auto const& neighbors = node_neighbors_[nodeid];
649  std::vector<Point<D>> node_coords(neighbors.size() + 1);
650  std::vector<double> node_values(neighbors.size() + 1);
651  mesh_.node_get_coordinates(nodeid, &(node_coords[0]));
652  node_values[0] = values_[nodeid];
653 
654  int i = 1;
655  for (auto&& current : neighbors) {
656  mesh_.node_get_coordinates(current, &node_coords[i]);
657  node_values[i] = values_[current];
658  i++;
659  }
660 
661  grad = Wonton::ls_gradient<D, CoordSys>(node_coords, node_values);
662 
663  if (apply_limiter) {
664  // Min and max vals of function (cell centered vals) among neighbors
665  double minval = values_[nodeid];
666  double maxval = values_[nodeid];
667 
668  for (auto const& val : node_values) {
669  minval = std::min(val, minval);
670  maxval = std::max(val, maxval);
671  }
672 
673  // Find the min and max of the reconstructed function in the cell
674  // Since the reconstruction is linear, this will occur at one of
675  // the nodes of the cell. So find the values of the reconstructed
676  // function at the nodes of the cell
677  double nodeval = values_[nodeid];
678 
679  std::vector<Point<D>> dual_cell_coords;
680  mesh_.dual_cell_get_coordinates(nodeid, &dual_cell_coords);
681 
682  for (auto&& coord : dual_cell_coords) {
683  auto vec = coord - node_coords[0];
684  double diff = dot(grad, vec);
685  double extremeval = (diff > 0.0) ? maxval : minval;
686  double phi_new = (diff == 0.0) ? 1 : (extremeval - nodeval) / diff;
687  phi = std::min(phi_new, phi);
688  }
689  }
690 
691  // Limited gradient is phi*grad
692  return phi * grad;
693  }
694 
695  private:
696  Mesh const& mesh_;
697  State const& state_;
698  double const* values_;
699  std::string variable_name_ = "";
700  Limiter_type limiter_type_ = DEFAULT_LIMITER;
701  Boundary_Limiter_type boundary_limiter_type_ = DEFAULT_BND_LIMITER;
702  Field_type field_type_ = Field_type::UNKNOWN_TYPE_FIELD;
703 
704  int material_id_ = 0;
705  std::vector<int> cell_ids_;
706  std::vector<std::vector<int>> node_neighbors_;
707  };
708 } // namespace Portage
709 
710 #endif // PORTAGE_INTERPOLATE_GRADIENT_H_
void set_interpolation_variable(std::string const &variable_name, Limiter_type limiter_type, Boundary_Limiter_type boundary_limiter_type)
Definition: gradient.h:620
Definition: portage.h:91
Boundary_Limiter_type
Boundary limiter type.
Definition: portage.h:91
constexpr Boundary_Limiter_type DEFAULT_BND_LIMITER
Definition: portage.h:94
Wonton::Point< OP::dim > centroid(const typename OP::points_t &apts)
Definition: operator.h:616
Definition: portage.h:91
void for_each(InputIterator first, InputIterator last, UnaryFunction f)
Definition: portage.h:264
Compute limited gradient of a field or components of a field.
Definition: gradient.h:52
Manages source and target sub-meshes for part-by-part remap.
Limited_Gradient & operator=(const Limited_Gradient &)=delete
Limited_Gradient(Mesh const &mesh, State const &state, std::string var_name, Limiter_type limiter_type, Boundary_Limiter_type boundary_limiter_type, const Part< Mesh, State > *part=nullptr)
Constructor.
Definition: gradient.h:523
Limiter_type
Limiter type.
Definition: portage.h:85
Limited_Gradient(Mesh const &mesh, State const &state, std::string const var_name, Limiter_type limiter_type, Boundary_Limiter_type boundary_limiter_type, const Part< Mesh, State > *part=nullptr)
Constructor.
Definition: gradient.h:76
Limited_Gradient(Mesh const &mesh, State const &state, std::string var_name, Limiter_type limiter_type, Boundary_Limiter_type boundary_limiter_type, const Part< Mesh, State > *part=nullptr)
Definition: gradient.h:162
Definition: coredriver.h:42
Definition: parts.h:39
Vector< D > operator()(int entity_id)
Definition: gradient.h:111
constexpr Limiter_type DEFAULT_LIMITER
Definition: portage.h:88
Definition: portage.h:85
void set_interpolation_variable(std::string variable_name, Limiter_type limiter_type, Boundary_Limiter_type boundary_limiter_type)
Definition: gradient.h:279