Gyselalib++
 
Loading...
Searching...
No Matches
crank_nicolson.hpp
1// SPDX-License-Identifier: MIT
2#pragma once
3
4#include "ddc_alias_inline_functions.hpp"
5#include "ddc_aliases.hpp"
6#include "ddc_helper.hpp"
7#include "itimestepper.hpp"
8#include "l_norm_tools.hpp"
9#include "multipatch_math_tools.hpp"
10#include "vector_field_common.hpp"
11
12
33template <
34 class FieldMem,
35 class DerivFieldMem = FieldMem,
36 class ExecSpace = Kokkos::DefaultExecutionSpace>
37class CrankNicolson : public ITimeStepper<FieldMem, DerivFieldMem, ExecSpace>
38{
40
41public:
42 using typename base_type::IdxRange;
43
44 using typename base_type::ValConstField;
45 using typename base_type::ValField;
46
47 using typename base_type::DerivConstField;
48 using typename base_type::DerivField;
49
50private:
51 IdxRange const m_idx_range;
52 int const m_max_counter;
53 double const m_epsilon;
54
55public:
57
58public:
69 explicit CrankNicolson(
70 IdxRange idx_range,
71 int const counter = int(20),
72 double const epsilon = 1e-12)
73 : m_idx_range(idx_range)
74 , m_max_counter(counter)
75 , m_epsilon(epsilon)
76 {
77 }
78
94 void update(
95 ExecSpace const& exec_space,
96 ValField y,
97 double dt,
98 std::function<void(DerivField, ValConstField)> dy_calculator,
99 std::function<void(ValField, DerivConstField, double)> y_update) const final
100 {
101 static_assert(
102 Kokkos::SpaceAccessibility<ExecSpace, typename FieldMem::memory_space>::accessible,
103 "MemorySpace has to be accessible for ExecutionSpace.");
104 static_assert(
105 Kokkos::SpaceAccessibility<ExecSpace, typename DerivFieldMem::memory_space>::
106 accessible,
107 "MemorySpace has to be accessible for ExecutionSpace.");
108 using element_type = typename DerivField::element_type;
109
110 FieldMem y_init_alloc(m_idx_range);
111 FieldMem y_old_alloc(m_idx_range);
112 DerivFieldMem k1_alloc(m_idx_range);
113 DerivFieldMem k_new_alloc(m_idx_range);
114 DerivFieldMem k_total_alloc(m_idx_range);
115 ValField y_init = get_field(y_init_alloc);
116 ValField y_old = get_field(y_old_alloc);
117 DerivField k1 = get_field(k1_alloc);
118 DerivField k_new = get_field(k_new_alloc);
119 DerivField k_total = get_field(k_total_alloc);
120
121
122 base_type::copy(y_init, get_const_field(y));
123
124 // --------- Calculate k1 ------------
125 // Calculate k1 = f(y_n)
126 dy_calculator(k1, get_const_field(y));
127
128 // -------- Calculate k_new ----------
129 bool not_converged = true;
130 int counter = 0;
131 do {
132 counter++;
133
134 // Calculate k_new = f(y_new)
135 dy_calculator(k_new, get_const_field(y));
136
137 // Calculation of step
138 // k_total = k1 + k_new
140 exec_space,
141 k_total,
142 KOKKOS_LAMBDA(std::array<element_type, 2> k) { return k[0] + k[1]; },
143 k1,
144 k_new);
145
146 // Save the old characteristic feet
147 base_type::copy(y_old, get_const_field(y));
148
149 // Re-initialiase the characteristic feet
150 base_type::copy(y, get_const_field(y_init));
151
152 // Calculate y_new := y_n + h/2*(k_1 + k_new)
153 y_update(y, get_const_field(k_total), 0.5 * dt);
154
155
156 // Check convergence
157 not_converged
158 = not have_converged(exec_space, get_const_field(y_old), get_const_field(y));
159
160
161 } while (not_converged and (counter < m_max_counter));
162 }
163
164
181 bool have_converged(ExecSpace const& exec_space, ValConstField y_old, ValConstField y_new) const
182 {
183 double norm_old = norm_inf(exec_space, y_old);
184
185 double max_diff = error_norm_inf(exec_space, y_old, y_new);
186
187 return (max_diff / norm_old) < m_epsilon;
188 }
189};
A class which provides an implementation of a Crank-Nicolson method.
Definition crank_nicolson.hpp:38
bool have_converged(ExecSpace const &exec_space, ValConstField y_old, ValConstField y_new) const
Check if the relative difference of the function between two time steps is below epsilon.
Definition crank_nicolson.hpp:181
typename DerivFieldMem::view_type DerivConstField
The constant type of the derivatives values of the function being evolved.
Definition itimestepper.hpp:59
typename FieldMem::span_type ValField
The type of the values of the function being evolved.
Definition itimestepper.hpp:50
void update(ExecSpace const &exec_space, ValField y, double dt, std::function< void(DerivField, ValConstField)> dy_calculator, std::function< void(ValField, DerivConstField, double)> y_update) const final
Carry out one step of the Crank-Nicolson scheme.
Definition crank_nicolson.hpp:94
CrankNicolson(IdxRange idx_range, int const counter=int(20), double const epsilon=1e-12)
Create a CrankNicolson object.
Definition crank_nicolson.hpp:69
typename FieldMem::view_type ValConstField
The constant type of the values of the function being evolved.
Definition itimestepper.hpp:53
See DerivFieldMemImplementation.
Definition derivative_field.hpp:10
See DerivFieldImplementation.
Definition derivative_field.hpp:20
The superclass from which all timestepping methods inherit.
Definition itimestepper.hpp:23
typename FieldMem::discrete_domain_type IdxRange
The type of the index range on which the values of the function are defined.
Definition itimestepper.hpp:46
typename DerivFieldMem::span_type DerivField
The type of the derivatives of the function being evolved.
Definition itimestepper.hpp:56
void assemble_k_total(ExecSpace const &exec_space, DerivField k_total, FuncType func, T... k) const
A method to assemble multiple derivative fields into one.
Definition itimestepper.hpp:182
typename DerivFieldMem::view_type DerivConstField
The constant type of the derivatives values of the function being evolved.
Definition itimestepper.hpp:59
typename FieldMem::span_type ValField
The type of the values of the function being evolved.
Definition itimestepper.hpp:50
void update(ValField y, double dt, std::function< void(DerivField, ValConstField)> dy_calculator) const
Carry out one step of the timestepping scheme.
Definition itimestepper.hpp:78
void copy(ValField copy_to, ValConstField copy_from) const
Make a copy of the values of the function being evolved.
Definition itimestepper.hpp:147
typename FieldMem::view_type ValConstField
The constant type of the values of the function being evolved.
Definition itimestepper.hpp:53
File Describing useful mathematical functions to compute Lnorms.
KOKKOS_FUNCTION double norm_inf(ddc::Coordinate< Tags... > coord)
Compute the infinity norm.
Definition l_norm_tools.hpp:25
double error_norm_inf(ExecSpace exec_space, ConstField< ElementType, IdxRange, typename ExecSpace::memory_space > function, ConstField< ElementType, IdxRange, typename ExecSpace::memory_space > exact_function)
Compute the infinity norm of the error between 2 Fields.
Definition l_norm_tools.hpp:127