20 #ifndef OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_UPWIND_GRADIENT_HPP 21 #define OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_UPWIND_GRADIENT_HPP 27 #include "Grid/grid_dist_id.hpp" 28 #include "FD_simple.hpp" 29 #include "Eno_Weno.hpp" 38 template <
typename field_type>
39 static field_type
upwinding(field_type dplus, field_type dminus,
int sign)
41 field_type grad_upwind = 0.0;
43 && (dminus + dplus) * sign < 0) grad_upwind = dplus;
45 else if (dminus * sign > 0
46 && (dminus + dplus) * sign > 0) grad_upwind = dminus;
48 else if (dminus * sign < 0
49 && dplus * sign > 0) grad_upwind = 0;
69 template <
size_t Field,
size_t Sign,
typename gr
idtype,
typename keytype>
74 typedef typename std::decay_t<decltype(
grid.template get<Field>(key))> field_type;
75 field_type dplus = 0.0, dminus = 0.0;
76 int sign_phi0 =
grid.template get<Sign> (key);
81 dplus = FD_forward<Field>(
grid, key, d);
82 dminus = FD_backward<Field>(
grid, key, d);
85 dplus = ENO_3_Plus<Field>(
grid, key, d);
86 dminus = ENO_3_Minus<Field>(
grid, key, d);
89 dplus = WENO_5_Plus<Field>(
grid, key, d);
90 dminus = WENO_5_Minus<Field>(
grid, key, d);
93 auto &v_cl = create_vcluster();
94 if (v_cl.rank() == 0) std::cout <<
"Order of accuracy chosen not valid. Using default order 1." <<
96 dplus = FD_forward<Field>(
grid, key, d);
97 dminus = FD_backward<Field>(
grid, key, d);
101 return upwinding(dplus, dminus, sign_phi0);
122 template <
size_t Field,
size_t Sign,
size_t Gradient,
typename gr
idtype>
125 grid.template ghost_get<Field>(KEEP_PROPERTIES);
126 grid.template ghost_get<Sign>(KEEP_PROPERTIES);
128 auto dom =
grid.getDomainIterator();
134 auto key = dom.get();
135 auto key_g =
grid.getGKey(key);
137 for(
size_t d = 0; d < gridtype::dims; d++ )
140 if (key_g.get(d) > 2 && key_g.get(d) <
grid.size(d) - 3)
143 grid.template get<Gradient> (key) [d] = FD_upwind<Field, Sign>(
grid, key, d, order);
147 else if (key_g.get(d) > 0 && key_g.get(d) <
grid.size(d) - 1)
149 grid.template get<Gradient> (key) [d] = FD_upwind<Field, Sign>(
grid, key, d, 1);
152 else if (key_g.get(d) == 0)
154 grid.template get<Gradient> (key) [d] = FD_forward<Field>(
grid, key, d);
157 else if (key_g.get(d) >=
grid.size(d) - 1)
159 grid.template get<Gradient> (key) [d] = FD_backward<Field>(
grid, key, d);
170 auto key = dom.get();
171 for(
size_t d = 0; d < gridtype::dims; d++)
173 grid.template get<Gradient> (key) [d] = FD_upwind<Field, Sign>(
grid, key, d, order);
187 template <
typename gr
idtype>
190 auto ghost =
grid.getDecomposition().getGhost();
191 int np_ghost[gridtype::dims];
193 for (
int d = 0 ; d < gridtype::dims ; d++)
195 np_ghost[d] = ghost.getHigh(d) /
grid.getSpacing()[d];
198 int min_width = np_ghost[0];
199 for (
int d = 0 ; d < gridtype::dims ; d++)
201 if(np_ghost[d] < min_width) min_width = np_ghost[d];
204 return (min_width >= required_width);
216 template <
size_t Field_in,
size_t Sign,
size_t Gradient_out,
typename gr
idtype>
219 grid.template ghost_get<Field_in>();
220 grid.template ghost_get<Sign>();
224 auto &v_cl = create_vcluster();
225 if (v_cl.rank() == 0)
228 size_t stencil_width;
229 (order > 1) ? stencil_width = 3 : stencil_width = 1;
232 std::cout <<
"Error: Ghost layer not big enough. Either run with one_sided_BC=true or create a ghost " 233 "layer that has a width of least " << stencil_width <<
" grid node(s)" << std::endl;
244 upwind_gradient<Field_in, Sign, Gradient_out>(
grid, one_sided_BC, order);
247 auto &v_cl = create_vcluster();
248 if (v_cl.rank() == 0) std::cout <<
"Order of accuracy chosen not valid. Using default order 1." <<
250 upwind_gradient<Field_in, Sign, Gradient_out>(
grid, one_sided_BC, 1);
258 #endif //OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_UPWIND_GRADIENT_HPP void upwind_gradient(gridtype &grid, const bool one_sided_BC, size_t order)
Computes upwind gradient with order of accuracy 1, 3 or 5.
static field_type upwinding(field_type dplus, field_type dminus, int sign)
Upwinding: For a specific dimension, from the forward and backward gradient find the upwind side.
static bool ghost_width_is_sufficient(gridtype &grid, size_t required_width)
Checks if ghost layer is thick enough for a given stencil-width.
void get_upwind_gradient(gridtype &grid, const size_t order=5, const bool one_sided_BC=true)
Calls upwind_gradient. Computes upwind gradient of desired order {1, 3, 5} for the whole n-dim grid.
auto FD_upwind(gridtype &grid, keytype &key, size_t d, size_t order)
Get the upwind finite difference of a scalar property on the current grid node.