OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
 
Loading...
Searching...
No Matches
RedistancingSussman.hpp
Go to the documentation of this file.
1//
2// Created by jstark on 2020-04-06.
3//
31#ifndef REDISTANCING_SUSSMAN_REDISTANCINGSUSSMAN_HPP
32#define REDISTANCING_SUSSMAN_REDISTANCINGSUSSMAN_HPP
33
34// Include standard library header files
35#include <iostream>
36#include <string>
37#include <fstream>
38// Include OpenFPM header files
39#include "Vector/vector_dist.hpp"
40#include "Grid/grid_dist_id.hpp"
41#include "data_type/aggregate.hpp"
42#include "Decomposition/CartDecomposition.hpp"
43
44// Include other header files
45#include "HelpFunctions.hpp"
47//#include "ComputeGradient.hpp"
49
58template <typename phi_type=double>
60{
61 bool check = true;
65 phi_type value = 1e-15;
67};
68
74template <typename phi_type=double>
76{
77 bool check = true;
80 phi_type value = 1e-3;
83};
84
116template <typename phi_type=double>
118{
119 size_t min_iter = 1e3;
120 size_t max_iter = 1e6;
121
122 Conv_tol_change<phi_type> convTolChange;
123 Conv_tol_residual<phi_type> convTolResidual;
124
125 size_t interval_check_convergence = 100;
126 size_t width_NB_in_grid_points = 2;
127 bool print_current_iterChangeResidual = false;
128 bool print_steadyState_iter = true;
129 bool save_temp_grid = false;
130};
131
138template <typename phi_type=double>
140{
141 phi_type change;
147 phi_type residual;
151 int count;
152};
153
154
160template <typename grid_in_type, typename phi_type=double>
162{
163public:
173 r_grid_in(grid_in),
174 g_temp(grid_in.getDecomposition(),
175 grid_in.getGridInfoVoid().getSize(),
176 Ghost<grid_in_type::dims, long int>(3))
177 {
178 // Get timestep fulfilling CFL condition for velocity=1.0 and courant number=0.1
179 time_step = get_time_step_CFL(grid_in, 1.0, 0.1);
180 order_upwind_gradient = 1;
181#ifdef SE_CLASS1
182 assure_minimal_thickness_of_NB();
183#endif // SE_CLASS1
184 }
185
207
214 template <size_t Phi_0_in, size_t Phi_SDF_out>
216 {
217 init_temp_grid<Phi_0_in>();
218 init_sign_prop<Phi_n_temp, Phi_0_sign_temp>(g_temp); // Initialize Phi_0_sign_temp with the sign of the
219 // initial (pre-redistancing) Phi_0
220 // Get initial gradients
221 get_upwind_gradient<Phi_n_temp, Phi_0_sign_temp, Phi_grad_temp>(g_temp, order_upwind_gradient, true);
222 iterative_redistancing(g_temp); // Do the redistancing on the temporary grid
223 copy_gridTogrid<Phi_n_temp, Phi_SDF_out>(g_temp, r_grid_in); // Copy resulting SDF function to input grid
224 }
234 template<typename T>
236 {
237 time_step = dt;
238 }
243 {
245 return time_step;
246 }
247
248 int get_finalIteration()
249 {
250 return final_iter;
251 }
252
253 auto get_finalChange()
254 {
255 return distFromSol.change;
256 }
257
258 auto get_finalResidual()
259 {
260 return distFromSol.residual;
261 }
262
263 int get_finalNumberNbPoints()
264 {
265 return distFromSol.count;
266 }
267
268private:
269 // Some indices for better readability
270 static constexpr size_t Phi_n_temp = 0;
271 static constexpr size_t Phi_grad_temp = 1;
272 static constexpr size_t Phi_0_sign_temp = 2;
273
274 // Member variables
276 grid_in_type &r_grid_in;
277
279 // point in NB.
280 int final_iter = 0;
281
283 phi_type kappa = ceil(redistOptions.width_NB_in_grid_points / 2.0) * get_biggest_spacing(g_temp);
287 typename grid_in_type::stype time_step;
288 int order_upwind_gradient;
289 // Member functions
290#ifdef SE_CLASS1
296 void assure_minimal_thickness_of_NB()
297 {
298 if (redistOptions.width_NB_in_grid_points < 8)
299 {
300 std::cout << "The narrow band thickness that you chose for the convergence check is very small. Consider "
301 "setting redist_options.width_NB_in_grid_points to at least 8" << std::endl;
302 } // check narrow band width of convergence check if defined SE_CLASS1
303 }
304#endif // SE_CLASS1
308 template<size_t Phi_0_in>
310 {
311 phi_type min_value = get_min_val<Phi_0_in>(r_grid_in); // get minimum Phi_0 value on the input grid
312 init_grid_and_ghost<Phi_n_temp>(g_temp, min_value); // init. Phi_n_temp (incl. ghost) with min. Phi_0
313 copy_gridTogrid<Phi_0_in, Phi_n_temp>(r_grid_in, g_temp); // Copy Phi_0 from the input grid to Phi_n_temp
314 }
315
326 phi_type get_phi_nplus1(phi_type phi_n, phi_type phi_n_magnOfGrad, typename grid_in_type::stype dt, phi_type
327 sgn_phi_n)
328 {
329 return phi_n + dt * sgn_phi_n * (1 - phi_n_magnOfGrad);
330 }
331
337 {
338 get_upwind_gradient<Phi_n_temp, Phi_0_sign_temp, Phi_grad_temp>(grid, order_upwind_gradient, true);
339 grid.template ghost_get<Phi_n_temp, Phi_grad_temp>();
340 auto dom = grid.getDomainIterator();
341 while (dom.isNext())
342 {
343 auto key = dom.get();
344 const phi_type phi_n = grid.template get<Phi_n_temp>(key);
345 const phi_type phi_n_magnOfGrad = get_vector_magnitude<Phi_grad_temp>(grid, key);
346 phi_type epsilon = phi_n_magnOfGrad * grid.getSpacing()[0];
347 grid.template get<Phi_n_temp>(key) = get_phi_nplus1(phi_n, phi_n_magnOfGrad, time_step,
348 smooth_S(phi_n, epsilon));
349 ++dom;
350 }
351 }
352
359 bool lays_inside_NB(phi_type Phi)
360 {
361 return (abs(Phi) <= kappa);
362 }
363
370 {
371 phi_type max_residual = 0;
372 phi_type max_change = 0;
373 int count = 0;
374 auto dom = grid.getDomainIterator();
375 while (dom.isNext())
376 {
377 auto key = dom.get();
378 if (lays_inside_NB(grid.template get<Phi_n_temp>(key)))
379 {
380 count++;
381 phi_type phi_n_magnOfGrad = get_vector_magnitude<Phi_grad_temp>(grid, key);
382 phi_type epsilon = phi_n_magnOfGrad * grid.getSpacing()[0];
383 phi_type phi_nplus1 = get_phi_nplus1(grid.template get<Phi_n_temp>(key), phi_n_magnOfGrad, time_step,
384 smooth_S(grid.template get<Phi_n_temp>(key), epsilon));
385
386 if (abs(phi_nplus1 - grid.template get<Phi_n_temp>(key)) > max_change)
387 {
388 max_change = abs(phi_nplus1 - grid.template get<Phi_n_temp>(key));
389 }
390
391 if (abs(phi_n_magnOfGrad - 1) > max_residual) { max_residual = abs(phi_n_magnOfGrad - 1); }
392 }
393 ++dom;
394 }
395 auto &v_cl = create_vcluster();
396 v_cl.max(max_change);
397 v_cl.max(max_residual);
398 v_cl.sum(count);
399 v_cl.execute();
400
401 // Update member variable distFromSol
402 distFromSol.change = max_change;
403 distFromSol.residual = max_residual;
404 distFromSol.count = count;
405 }
406
414 {
416 auto &v_cl = create_vcluster();
417 if (v_cl.rank() == 0)
418 {
419 if (iter == 0)
420 {
421 std::cout << "Iteration,MaxChange,MaxResidual,NumberOfNarrowBandPoints" << std::endl;
422 }
423 std::cout << iter
424 << "," << to_string_with_precision(distFromSol.change, 15)
425 << "," << to_string_with_precision(distFromSol.residual, 15)
426 << "," << distFromSol.count << std::endl;
427 }
428 }
429
441 {
442 bool steady_state = false;
444 if (redistOptions.convTolChange.check && redistOptions.convTolResidual.check)
445 {
446 steady_state = (
447 distFromSol.change <= redistOptions.convTolChange.value &&
448 distFromSol.residual <= redistOptions.convTolResidual.value &&
449 distFromSol.count > 0
450 );
451 }
452 else
453 {
454 if (redistOptions.convTolChange.check)
455 {
456 steady_state = (distFromSol.change <= redistOptions.convTolChange.value && distFromSol.count > 0);
457 } // Use the normalized total change between two iterations in the narrow bands steady-state criterion
458 if (redistOptions.convTolResidual.check)
459 {
460 steady_state = (distFromSol.residual <= redistOptions.convTolResidual.value && distFromSol.count > 0);
461 } // Use the normalized total residual of phi compared to SDF in the narrow bands steady-state criterion
462 }
463 return steady_state;
464 }
465
476 {
477 int i = 0;
478 while (i < redistOptions.max_iter)
479 {
480 for (int j = 0; j < redistOptions.interval_check_convergence; j++)
481 {
483 ++i;
484 }
485 if (redistOptions.print_current_iterChangeResidual)
486 {
488 }
489 if (redistOptions.save_temp_grid)
490 {
491 get_upwind_gradient<Phi_n_temp, Phi_0_sign_temp, Phi_grad_temp>(g_temp, order_upwind_gradient, true);
492 g_temp.setPropNames({"Phi_Sussman_Out", "Phi_upwind_gradient", "Phi_0_sign_temp"});
493 g_temp.save("g_temp_redistancing_iteration_" + std::to_string(i) + ".hdf5"); // HDF5 file
494 // g_temp.write_frame("g_temp_redistancing_iteration", i, FORMAT_BINARY); // VTK file
495 }
496 if (i >= redistOptions.min_iter)
497 {
499 {
500 if (redistOptions.print_steadyState_iter)
501 {
502 auto &v_cl = create_vcluster();
503 if (v_cl.rank() == 0)
504 {
505 std::cout << "Steady state criterion reached at iteration: " << i << std::endl;
506 std::cout << "FinalIteration,MaxChange,MaxResidual" << std::endl;
507 }
509 }
510 break;
511 }
512 }
513 }
515 final_iter = i;
516 // If save_temp_grid set true, save the temporary grid as hdf5 that can be reloaded onto a grid
517 if (redistOptions.save_temp_grid)
518 {
519 get_upwind_gradient<Phi_n_temp, Phi_0_sign_temp, Phi_grad_temp>(g_temp, order_upwind_gradient, true);
520 g_temp.setPropNames({"Phi_Sussman_Out", "Phi_upwind_gradient", "Phi_0_sign_temp"});
521 g_temp.save("g_temp_redistancing_final.hdf5"); // HDF5 file
522 // g_temp.write("g_temp_redistancing_final", FORMAT_BINARY); // VTK file
523 }
524 }
525};
526
527#endif //REDISTANCING_SUSSMAN_REDISTANCINGSUSSMAN_HPP
Header file containing help-functions that perform on OpenFPM-grids.
grid_type::stype get_time_step_CFL(grid_type &grid, typename grid_type::stype u[grid_type::dims], typename grid_type::stype C)
Computes the time step size fulfilling CFL condition according to https://www.cfd-online ....
grid_type::stype get_biggest_spacing(grid_type &grid)
Determines the biggest spacing of a grid which is potentially anisotropic when comparing x,...
Header file containing small mathematical help-functions that are needed e.g. for the Sussman redista...
T smooth_S(T val, T epsilon)
Gets the smoothed sign of a variable.
std::string to_string_with_precision(const T myValue, const size_t n=6)
Converts value into string maintaining a desired precision.
Approximating upwind gradients on a grid with the following options for the order of accuracy: 1,...
Class for reinitializing a level-set function into a signed distance function using Sussman redistanc...
grid_in_type & r_grid_in
Define reference to input grid.
g_temp_type g_temp
Create temporary grid, which is only used inside the class for the redistancing.
int final_iter
Will be set to the final iteration when redistancing ends.
static constexpr size_t Phi_n_temp
Property index of Phi_0 on the temporary grid.
bool steady_state_NB(g_temp_type &grid)
Checks steady-state is reached in the narrow band.
bool lays_inside_NB(phi_type Phi)
Checks if a node lays within the narrow band around the interface.
void init_temp_grid()
Copies values from input grid to internal temporary grid and initializes ghost layer with minimum val...
void run_redistancing()
Runs the Sussman-redistancing.
void update_distFromSol(g_temp_type &grid)
Re-computes the member variables distFromSol.change, distFromSol.residual, distFromSol....
static constexpr size_t Phi_0_sign_temp
Property index of sign of initial (input) Phi_0 (temp. grid).
phi_type kappa
Transform the half-bandwidth in no_of_grid_points into physical half-bandwidth kappa.
DistFromSol< phi_type > distFromSol
Instantiate distance from solution in terms of change, residual, numb.
phi_type get_phi_nplus1(phi_type phi_n, phi_type phi_n_magnOfGrad, typename grid_in_type::stype dt, phi_type sgn_phi_n)
Run one timestep of re-distancing and compute Phi_n+1.
auto get_time_step()
Access the artificial timestep (private member) which will be used for the iterative redistancing.
grid_in_type::stype time_step
Artificial timestep for the redistancing iterations.
static constexpr size_t Phi_grad_temp
Property index of gradient of Phi_n on the temporary grid.
grid_dist_id< grid_in_type::dims, typename grid_in_type::stype, props_temp > g_temp_type
Type definition for the temporary grid.
void iterative_redistancing(g_temp_type &grid)
Runs Sussman re-distancing on the internal temporary grid.
RedistancingSussman(grid_in_type &grid_in, Redist_options< phi_type > &redistOptions)
Constructor initializing the redistancing options, the temporary internal grid and reference variable...
void print_out_iteration_change_residual(g_temp_type &grid, size_t iter)
Prints out the iteration number, max. change, max. residual and number of points in the narrow band o...
Redist_options< phi_type > redistOptions
Instantiate redistancing options.
void go_one_redistancing_step_whole_grid(g_temp_type &grid)
Go one re-distancing time-step on the whole grid.
void set_user_time_step(T dt)
Overwrite the time_step found via CFL condition with an individual time_step.
aggregate< phi_type, phi_type[grid_in_type::dims], int > props_temp
Aggregated properties for the temporary grid.
This is a distributed grid.
void save(const std::string &filename) const
Save the grid state on HDF5.
void setPropNames(const openfpm::vector< std::string > &names)
Set the properties names.
Optional convergence criterium checking the total change.
phi_type value
redistancing process is considered as steady-state. (see also DistFromSol::change)
Optional convergence criterium checking the residual.
Bundles total residual and total change over all the grid points.
int count
Integer variable that contains the number of points that could be assigned to the narrow band.
Structure to bundle options for redistancing.
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...