8 #ifndef _EXAMPLES__ADVEC_DIFF__ADVECTION_DIFFUSION_SWEEPER_HPP_
9 #define _EXAMPLES__ADVEC_DIFF__ADVECTION_DIFFUSION_SWEEPER_HPP_
30 #define PI 3.1415926535897932385
60 namespace advection_diffusion
66 typedef map<tuple<size_t, size_t>,
double>
error_map;
70 typedef error_map::value_type
vtype;
71 typedef error_map::key_type
ktype;
77 template<
typename time = pfasst::time_precision>
84 pfasst::config::options::add_option<size_t>(
"Adv/Diff Sweeper",
"spatial_dofs",
"Number of spatial degrees of freedom");
95 vector<complex<double>> ddx,
lap;
114 this->ddx.resize(nvars);
115 this->lap.resize(nvars);
116 for (
size_t i = 0; i < nvars; i++) {
117 double kx = 2 *
PI * ((i <= nvars / 2) ?
int(i) : int(i) - int(nvars));
118 this->ddx[i] = complex<double>(0.0, 1.0) * kx;
119 this->lap[i] = (kx * kx < 1e-13) ? 0.0 : -kx * kx;
127 ML_CLOG(INFO,
"Advec",
"number of f1 evals: " << this->nf1evals);
134 this->exact(as_vector<double, time>(q), t);
140 double a = 1.0 / sqrt(4 *
PI * nu * (t + t0));
142 for (
size_t i = 0; i < n; i++) {
146 for (
int ii = -2; ii < 3; ii++) {
147 for (
size_t i = 0; i < n; i++) {
148 double x = double(i) / n - 0.5 + ii - t * v;
149 q[i] += a * exp(-x * x / (4 * nu * (t + t0)));
156 auto& qend = as_vector<double, time>(this->get_end_state());
162 for (
size_t i = 0; i < qend.size(); i++) {
163 double d = abs(qend[i] - qex[i]);
164 if (d > max) { max = d; }
167 auto n = this->get_controller()->get_step();
168 auto k = this->get_controller()->get_iteration();
175 vector<shared_ptr<Encapsulation<time>>> residuals;
177 for (
size_t m = 0; m < this->get_nodes().size(); m++) {
180 this->residual(this->get_controller()->get_step_size(), residuals);
183 for (
auto r: residuals) {
184 rnorms.push_back(r->norm0());
186 auto rmax = *std::max_element(rnorms.begin(), rnorms.end());
188 auto n = this->get_controller()->get_step();
189 auto k = this->get_controller()->get_iteration();
191 auto err = this->errors[
ktype(n, k)];
193 ML_CLOG(INFO,
"Advec", (boost::format(this->FORMAT_STR) % (n+1) % k % this->get_nodes().size() % as_vector<double, time>(this->state[0]).size() % rmax % err));
195 this->residuals[
ktype(n, k)] = rmax;
205 return this->residuals;
215 time
t = this->get_controller()->get_time();
216 time
dt = this->get_controller()->get_step_size();
217 this->echo_error(t + dt);
218 this->echo_residual();
226 time
t = this->get_controller()->get_time();
227 time
dt = this->get_controller()->get_step_size();
228 this->echo_error(t + dt);
229 this->echo_residual();
242 auto& u = as_vector<double, time>(u_encap);
243 auto& f_expl = as_vector<double, time>(f_expl_encap);
245 double c = -v / double(u.size());
247 auto* z = this->fft.
forward(u);
248 for (
size_t i = 0; i < u.size(); i++) {
249 z[i] *= c * this->ddx[i];
264 auto& u = as_vector<double, time>(u_encap);
265 auto& f_impl = as_vector<double, time>(f_impl_encap);
267 double c = nu / double(u.size());
269 auto* z = this->fft.
forward(u);
270 for (
size_t i = 0; i < u.size(); i++) {
271 z[i] *= c * this->lap[i];
285 auto& u = as_vector<double, time>(u_encap);
286 auto& f_impl = as_vector<double, time>(f_impl_encap);
287 auto& rhs = as_vector<double, time>(rhs_encap);
289 double c = nu * double(dt);
291 auto* z = this->fft.
forward(rhs);
292 for (
size_t i = 0; i < u.size(); i++) {
293 z[i] /= (1.0 - c * this->lap[i]) *
double(u.size());
297 for (
size_t i = 0; i < u.size(); i++) {
298 f_impl[i] = (u[i] - rhs[i]) /
double(dt);
307 #endif // _EXAMPLES__ADVEC_DIFF__ADVECTION_DIFFUSION_SWEEPER_HPP_
Semi-implicit IMEX sweeper.
void post_sweep() override
Perform one SDC sweep/iteration.
void post_predict() override
Compute low-order provisional solution.
AdvectionDiffusionSweeper(size_t nvars)
map< size_t, error_map > residual_map
map< tuple< size_t, size_t >, double > error_map
void impl_solve(shared_ptr< Encapsulation< time >> f_impl_encap, shared_ptr< Encapsulation< time >> u_encap, time t, time dt, shared_ptr< Encapsulation< time >> rhs_encap) override
Solve \( U - \Delta t F_{\rm impl}(U) = RHS \) for \( U \).
#define ML_CLOG(level, logger_id, x)
same as CLOG(level, logger, x) from easylogging++
static void add_custom_logger(const string &id)
Provides convenient way of adding additional named loggers.
virtual ~AdvectionDiffusionSweeper()
complex< double > * forward(const DVectorT &x)
void f_impl_eval(shared_ptr< Encapsulation< time >> f_impl_encap, shared_ptr< Encapsulation< time >> u_encap, time t) override
Evaluate the implicit part of the ODE.
void f_expl_eval(shared_ptr< Encapsulation< time >> f_expl_encap, shared_ptr< Encapsulation< time >> u_encap, time t) override
Evaluate the explicit part of the ODE.
void exact(shared_ptr< Encapsulation< time >> q, time t)
static precision max(const vector< precision > &data)
error_map::value_type vtype
Data/solution encapsulation.
void exact(DVectorT &q, time t)
#define UNUSED(expr)
Denoting unused function parameters for omitting compiler warnings.
void backward(DVectorT &x)
vector< complex< double > > lap
advection-diffusion sweeper with semi-implicit time-integration.
error_map::key_type ktype
error_map get_residuals()
VectorEncapsulation< scalar, time > & as_vector(shared_ptr< Encapsulation< time >> x)