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"
39template <
typename field_type>
40static field_type
upwinding(field_type dplus, field_type dminus,
int sign)
42 field_type grad_upwind = 0.0;
44 && (dminus + dplus) * sign < 0) grad_upwind = dplus;
46 else if (dminus * sign > 0
47 && (dminus + dplus) * sign > 0) grad_upwind = dminus;
49 else if (dminus * sign < 0
50 && dplus * sign > 0) grad_upwind = 0;
61template <
typename velocity_type>
74template <
typename velocity_type>
94template <
size_t Field,
size_t Velocity,
typename gr
idtype,
typename keytype>
99 typedef typename std::decay_t<
decltype(
grid.template get<Field>(key))> field_type;
100 field_type dplus = 0.0, dminus = 0.0;
108 dplus = FD_forward<Field>(
grid, key, d);
109 dminus = FD_backward<Field>(
grid, key, d);
112 dplus = ENO_3_Plus<Field>(
grid, key, d);
113 dminus = ENO_3_Minus<Field>(
grid, key, d);
116 dplus = WENO_5_Plus<Field>(
grid, key, d);
117 dminus = WENO_5_Minus<Field>(
grid, key, d);
120 auto &v_cl = create_vcluster();
121 if (v_cl.rank() == 0) std::cout <<
"Order of accuracy chosen not valid. Using default order 1." <<
123 dplus = FD_forward<Field>(
grid, key, d);
124 dminus = FD_backward<Field>(
grid, key, d);
128 return upwinding(dplus, dminus, sign_velocity);
148template <
size_t Field,
size_t Velocity,
size_t Gradient,
typename gr
idtype>
151 grid.template ghost_get<Field>(KEEP_PROPERTIES);
152 grid.template ghost_get<Velocity>(KEEP_PROPERTIES);
154 auto dom =
grid.getDomainIterator();
160 auto key = dom.get();
161 auto key_g =
grid.getGKey(key);
163 for(
size_t d = 0; d < gridtype::dims; d++ )
166 if (key_g.get(d) > 2 && key_g.get(d) <
grid.size(d) - 3)
169 grid.template get<Gradient> (key) [d] = FD_upwind<Field, Velocity>(
grid, key, d, order);
173 else if (key_g.get(d) > 0 && key_g.get(d) <
grid.size(d) - 1)
175 grid.template get<Gradient> (key) [d] = FD_upwind<Field, Velocity>(
grid, key, d, 1);
178 else if (key_g.get(d) == 0)
180 grid.template get<Gradient> (key) [d] = FD_forward<Field>(
grid, key, d);
183 else if (key_g.get(d) >=
grid.size(d) - 1)
185 grid.template get<Gradient> (key) [d] = FD_backward<Field>(
grid, key, d);
196 auto key = dom.get();
197 for(
size_t d = 0; d < gridtype::dims; d++)
199 grid.template get<Gradient> (key) [d] = FD_upwind<Field, Velocity>(
grid, key, d, order);
213template <
typename gr
idtype>
216 auto ghost =
grid.getDecomposition().getGhost();
217 int np_ghost[gridtype::dims];
219 for (
int d = 0 ; d < gridtype::dims ; d++)
221 np_ghost[d] = ghost.getHigh(d) /
grid.getSpacing()[d];
224 int min_width = np_ghost[0];
225 for (
int d = 0 ; d < gridtype::dims ; d++)
227 if(np_ghost[d] < min_width) min_width = np_ghost[d];
230 return (min_width >= required_width);
241template <
size_t Field_in,
size_t Velocity,
size_t Gradient_out,
typename gr
idtype>
244 grid.template ghost_get<Field_in>();
245 grid.template ghost_get<Velocity>();
249 auto &v_cl = create_vcluster();
250 if (v_cl.rank() == 0)
253 size_t stencil_width;
254 (order > 1) ? stencil_width = 3 : stencil_width = 1;
257 std::cout <<
"Error: Ghost layer not big enough. Either run with one_sided_BC=true or create a ghost "
258 "layer that has a width of least " << stencil_width <<
" grid node(s)" << std::endl;
269 upwind_gradient<Field_in, Velocity, Gradient_out>(
grid, one_sided_BC, order);
272 auto &v_cl = create_vcluster();
273 if (v_cl.rank() == 0) std::cout <<
"Order of accuracy chosen not valid. Using default order 1." <<
275 upwind_gradient<Field_in, Velocity, Gradient_out>(
grid, one_sided_BC, 1);
Header file containing small mathematical help-functions that are needed e.g. for the Sussman redista...
int sgn(T val)
Gets the sign of a variable.
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.
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.
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.
int get_sign_velocity(velocity_type v, size_t d)
Returns the sign of a scalar velocity field.
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 upwind_gradient(gridtype &grid, const bool one_sided_BC, size_t order)
Computes upwind gradient with order of accuracy 1, 3 or 5.