quadfit.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_QUADFIT_H_
8 #define PORTAGE_INTERPOLATE_QUADFIT_H_
9 
10 #include <algorithm>
11 #include <stdexcept>
12 #include <string>
13 #include <vector>
14 
15 #include <iostream>
16 
17 // portage includes
19 
20 // wonton includes
21 #include "wonton/support/lsfits.h"
22 #include "wonton/support/Point.h"
23 #include "wonton/support/Vector.h"
24 
25 namespace Portage {
26 
27 using Wonton::Point;
28 using Wonton::Vector;
29 
31 
32 
42 template<int D, Entity_kind on_what, typename MeshType, typename StateType>
44  public:
56  Limited_Quadfit(MeshType const & mesh, StateType const & state,
57  std::string const var_name,
58  Limiter_type limiter_type,
60  : mesh_(mesh),
61  state_(state),
62  var_name_(var_name),
63  limtype_(limiter_type),
64  bnd_limtype_(Boundary_Limiter_type) {
65 
66  // Extract the field data from the statemanager
67 
68  state.mesh_get_data(on_what, var_name, &vals_);
69  }
70 
72  //
73  // //! Copy constructor (deleted)
74  //
75  // Limited_Quadfit(const Limited_Quadfit &) = delete;
76 
78 
79  Limited_Quadfit & operator = (const Limited_Quadfit &) = delete;
80 
82 
83  ~Limited_Quadfit() = default;
84 
87 
88  Vector<D*(D+3)/2> operator()(int entity_id) {
89  std::cerr << "Limited quadfit not implemented for this entity kind\n";
90  }
91 
92  private:
93  MeshType const & mesh_;
94  StateType const & state_;
95  std::string var_name_;
96  double const* vals_;
97  Limiter_type limtype_;
98  Boundary_Limiter_type bnd_limtype_;
99 };
100 
101 
103 
110 template<int D, typename MeshType, typename StateType>
111 class Limited_Quadfit<D, Entity_kind::CELL, MeshType, StateType> {
112  public:
123  Limited_Quadfit(MeshType const & mesh, StateType const & state,
124  std::string const var_name,
125  Limiter_type limiter_type,
127  : mesh_(mesh),
128  state_(state),
129  var_name_(var_name),
130  limtype_(limiter_type),
131  bnd_limtype_(Boundary_Limiter_type) {
132 
133  // Extract the field data from the statemanager
134  state.mesh_get_data(Entity_kind::CELL, var_name, &vals_);
135 
136  // Collect and keep the list of neighbors for each NODE as it may
137  // be expensive to go to the mesh layer and collect this data for
138  // each cell during the actual quadfit calculation
139 
140  int ncells = mesh_.num_entities(Entity_kind::CELL);
141  cell_neighbors_.resize(ncells);
142 
143  Portage::for_each(mesh_.begin(Entity_kind::CELL), mesh_.end(Entity_kind::CELL),
144  [this](int c) { mesh_.cell_get_node_adj_cells(
145  c, Entity_type::ALL, &(cell_neighbors_[c])); } );
146  }
147 
149  //
150  // //! Copy constructor (deleted)
151  //
152  // Limited_Quadfit(const Limited_Quadfit &) = delete;
153 
155 
156  Limited_Quadfit & operator = (const Limited_Quadfit &) = delete;
157 
159 
160  ~Limited_Quadfit() = default;
161 
163 
164  Vector<D*(D+3)/2> operator()(int cellid);
165 
166  private:
167  MeshType const & mesh_;
168  StateType const & state_;
169  std::string var_name_;
170  double const *vals_;
171  Limiter_type limtype_;
172  Boundary_Limiter_type bnd_limtype_;
173  std::vector<std::vector<int>> cell_neighbors_;
174 };
175 
184 template<int D, typename MeshType, typename StateType>
185  Vector<D*(D+3)/2>
187 
188  assert(D == mesh_.space_dimension());
189  assert(D == 2 || D == 3);
190  double phi = 1.0;
191  Vector<D*(D+3)/2> qfit;
192  Vector<D*(D+3)/2> dvec;
193 
194  bool boundary_cell = mesh_.on_exterior_boundary(Entity_kind::CELL, cellid);
195  // Limit the boundary gradient to enforce monotonicity preservation
196  if (bnd_limtype_ == BND_ZERO_GRADIENT && boundary_cell) {
197  qfit.zero();
198  return qfit;
199  }
200 
201  std::vector<int> const & nbrids = cell_neighbors_[cellid];
202 
203  std::vector<Point<D>> cellcenters(nbrids.size()+1);
204  std::vector<double> cellvalues(nbrids.size()+1);
205 
206  // get centroid and value for cellid at center of point cloud
207  mesh_.cell_centroid(cellid, &(cellcenters[0]));
208 
209  cellvalues[0] = vals_[cellid];
210 
211  int i = 1;
212  for (auto nbrcell : nbrids) {
213  mesh_.cell_centroid(nbrcell, &(cellcenters[i]));
214  cellvalues[i] = vals_[nbrcell];
215  i++;
216  }
217 
218  qfit = Wonton::ls_quadfit(cellcenters, cellvalues, boundary_cell);
219  // Limit the gradient to enforce monotonicity preservation
220 
221  if (limtype_ == BARTH_JESPERSEN &&
222  (!boundary_cell || bnd_limtype_ == BND_BARTH_JESPERSEN)) {
223 
224  // Min and max vals of function (cell centered vals) among neighbors
226 
227  double minval = vals_[cellid];
228  double maxval = vals_[cellid];
229 
230  int nnbr = nbrids.size();
231  for (int ic = 0; ic < nnbr; ++ic) {
232  minval = std::min(cellvalues[ic], minval);
233  maxval = std::max(cellvalues[ic], maxval);
234  }
235 
236  // Find the min and max of the reconstructed function in the cell
237  // Since the reconstruction is linear, this will occur at one of
238  // the nodes of the cell. So find the values of the reconstructed
239  // function at the nodes of the cell
240 
241  double cellcenval = vals_[cellid];
242  std::vector<Point<D>> cellcoords;
243  mesh_.cell_get_coordinates(cellid, &cellcoords);
244 
245  for (auto coord : cellcoords) {
246  Vector<D> vec = coord-cellcenters[0];
247  //Vector<D*(D+3)/2> dvec;
248  for (int j = 0; j < D; ++j) {
249  dvec[j] = vec[j];
250  // Add the quadratic terms
251  for (int k = 0; k < j; ++k) {
252  dvec[j+k+D-1] = dvec[k]*dvec[j];
253  }
254  }
255 
256  double diff = dot(qfit, dvec);
257  double extremeval = (diff > 0.0) ? maxval : minval;
258  double phi_new = (diff == 0.0) ? 1 : (extremeval-cellcenval)/diff;
259  phi = std::min(phi_new, phi);
260  }
261 
262  }
263 
264  // Limited quadfit is phi*fit
265  return phi*qfit;
266 }
267 
268 
270 
278 template<int D, typename MeshType, typename StateType>
279 class Limited_Quadfit<D, Entity_kind::NODE, MeshType, StateType> {
280  public:
281 
292  Limited_Quadfit(MeshType const & mesh, StateType const & state,
293  std::string const var_name,
294  Limiter_type limiter_type,
296  : mesh_(mesh),
297  state_(state),
298  var_name_(var_name),
299  limtype_(limiter_type),
300  bnd_limtype_(Boundary_Limiter_type) {
301 
302  // Extract the field data from the statemanager
303  state.mesh_get_data(Entity_kind::NODE, var_name, &vals_);
304 
305  // Collect and keep the list of neighbors for each NODE as it may
306  // be expensive to go to the mesh layer and collect this data for
307  // each cell during the actual quadfit calculation
308 
309  int nnodes = mesh_.num_entities(Entity_kind::NODE);
310  node_neighbors_.resize(nnodes);
311 
312  Portage::for_each(mesh_.begin(Entity_kind::NODE), mesh_.end(Entity_kind::NODE),
313  [this](int n) { mesh_.dual_cell_get_node_adj_cells(
314  n, Entity_type::ALL, &(node_neighbors_[n])); } );
315  }
316 
318  //
319  // //! Copy constructor (deleted)
320  //
321  // Limited_Quadfit(const Limited_Quadfit &) = delete;
322 
324 
325  Limited_Quadfit & operator = (const Limited_Quadfit &) = delete;
326 
328 
329  ~Limited_Quadfit() = default;
330 
332 
333  Vector<D*(D+3)/2> operator()(int nodeid);
334 
335  private:
336  MeshType const & mesh_;
337  StateType const & state_;
338  std::string var_name_;
339  double const *vals_;
340  Limiter_type limtype_;
341  Boundary_Limiter_type bnd_limtype_;
342  std::vector<std::vector<int>> node_neighbors_;
343 };
344 
354 template<int D, typename MeshType, typename StateType>
355  Vector<D*(D+3)/2>
357 
358  assert(D == mesh_.space_dimension());
359  assert(D == 2 || D == 3);
360  double phi = 1.0;
361  Vector<D*(D+3)/2> qfit;
362  Vector<D*(D+3)/2> dvec;
363 
364  bool boundary_node = mesh_.on_exterior_boundary(Entity_kind::NODE, nodeid);
365  if (bnd_limtype_ == BND_ZERO_GRADIENT && boundary_node) {
366  qfit.zero();
367  return qfit;
368  }
369 
370  std::vector<int> const & nbrids = node_neighbors_[nodeid];
371  std::vector<Point<D>> nodecoords(nbrids.size()+1);
372  std::vector<double> nodevalues(nbrids.size()+1);
373 
374  Point<D> point;
375 
376  mesh_.node_get_coordinates(nodeid, &(nodecoords[0]));
377  nodevalues[0] = vals_[nodeid];
378 
379  int i = 1;
380  for (auto const & nbrnode : nbrids) {
381  mesh_.node_get_coordinates(nbrnode, &nodecoords[i]);
382  nodevalues[i] = vals_[nbrnode];
383  i++;
384  }
385 
386  qfit = Wonton::ls_quadfit(nodecoords, nodevalues, boundary_node);
387 
388  if (limtype_ == BARTH_JESPERSEN &&
389  (!boundary_node || bnd_limtype_ == BND_BARTH_JESPERSEN)) {
390 
391  // Min and max vals of function (cell centered vals) among neighbors
392 
393  double minval = vals_[nodeid];
394  double maxval = vals_[nodeid];
395 
396  for (auto const & val : nodevalues) {
397  minval = std::min(val, minval);
398  maxval = std::max(val, maxval);
399  }
400 
401  // Find the min and max of the reconstructed function in the cell
402  // Since the reconstruction is linear, this will occur at one of
403  // the nodes of the cell. So find the values of the reconstructed
404  // function at the nodes of the cell
405 
406  double nodeval = vals_[nodeid];
407 
408  std::vector<Point<D>> dualcellcoords;
409  mesh_.dual_cell_get_coordinates(nodeid, &dualcellcoords);
410 
411  for (auto const & coord : dualcellcoords) {
412  Vector<D> vec = coord-nodecoords[0];
413  // Vector<D*(D+3)/2> dvec;
414  for (int j = 0; j < D; ++j) {
415  dvec[j] = vec[j];
416  // Add the quadratic terms
417  for (int k = 0; k < j; ++k) {
418  dvec[j+k+D-1] = dvec[k]*dvec[j];
419  }
420  }
421 
422  double diff = dot(qfit, dvec);
423  double extremeval = (diff > 0.0) ? maxval : minval;
424  double phi_new = (diff == 0.0) ? 1 : (extremeval-nodeval)/diff;
425  phi = std::min(phi_new, phi);
426  }
427  }
428 
429  // Limited gradient is phi*qfit
430 
431  return phi*qfit;
432 }
433 
434 } // namespace Portage
435 
436 #endif // PORTAGE_INTERPOLATE_QUADFIT_H_
Definition: portage.h:91
Boundary_Limiter_type
Boundary limiter type.
Definition: portage.h:91
Definition: portage.h:91
void for_each(InputIterator first, InputIterator last, UnaryFunction f)
Definition: portage.h:264
Limited_Quadfit & operator=(const Limited_Quadfit &)=delete
Assignment operator (disabled)
Limited_Quadfit(MeshType const &mesh, StateType const &state, std::string const var_name, Limiter_type limiter_type, Boundary_Limiter_type Boundary_Limiter_type)
Constructor.
Definition: quadfit.h:56
~Limited_Quadfit()=default
Destructor.
Limited_Quadfit(MeshType const &mesh, StateType const &state, std::string const var_name, Limiter_type limiter_type, Boundary_Limiter_type Boundary_Limiter_type)
Constructor.
Definition: quadfit.h:123
Limiter_type
Limiter type.
Definition: portage.h:85
Definition: coredriver.h:42
Limited_Quadfit(MeshType const &mesh, StateType const &state, std::string const var_name, Limiter_type limiter_type, Boundary_Limiter_type Boundary_Limiter_type)
Constructor.
Definition: quadfit.h:292
Compute limited quadfit of a field or components of a field.
Definition: quadfit.h:43
Definition: portage.h:85