LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
convergence_study5.cc
1#include <cmath>
2#include <fstream>
3#include <iomanip>
4
5#include "primal_dpg_adapted_norm.h"
6#include "ultraweak_dpg.h"
7
8#define reflev 7
9
10int main() {
11 std::cout << "Convergence study 5: Primal DPG method, solution with a "
12 "boundary layer \n";
13 std::cout << "Solution develops a boundary layer at top and right edge. \n";
14 std::cout << "Formulation using an adapted test space innner product. \n";
15
16 std::vector<double> epsilon_values = {1, 0.5, 0.1, 0.05, 0.02, 0.01};
17 const double b1 = 2.0;
18 const double b2 = 1.0;
19
20 for (const double eps : epsilon_values) {
21 //------------------------
22 // Specification of the BVP
23 //------------------------
24 // exact solution:
25 auto u1_exact = [eps, b1](double x) -> double {
26 return x + (std::exp(x * b1 / eps) - 1) / (1 - std::exp(b1 / eps));
27 };
28 auto u1_exact_grad = [eps, b1](double x) -> double {
29 return 1 + b1 / eps * std::exp(x * b1 / eps) / (1 - std::exp(b1 / eps));
30 };
31 auto u1_exact_d2 = [eps, b1](double x) -> double {
32 return b1 * b1 / (eps * eps) * std::exp(x * b1 / eps) /
33 (1 - std::exp(b1 / eps));
34 };
35
36 auto u2_exact = [eps, b2](double y) -> double {
37 return y + (std::exp(y * b2 / eps) - 1) / (1 - std::exp(b2 / eps));
38 };
39 auto u2_exact_grad = [eps, b2](double y) -> double {
40 return 1 + b2 / eps * std::exp(y * b2 / eps) / (1 - std::exp(b2 / eps));
41 };
42 auto u2_exact_d2 = [eps, b2](double y) -> double {
43 return b2 * b2 / (eps * eps) * std::exp(y * b2 / eps) /
44 (1 - std::exp(b2 / eps));
45 };
46
47 auto u_exact = [&u1_exact, &u2_exact](const Eigen::Vector2d& x) -> double {
48 return u1_exact(x[0]) * u2_exact(x[1]);
49 };
50 auto u_grad = [eps, &u1_exact, &u2_exact, &u1_exact_grad, &u2_exact_grad](
51 const Eigen::Vector2d& x) -> Eigen::Vector2d {
52 return (Eigen::VectorXd(2) << u1_exact_grad(x[0]) * u2_exact(x[1]),
53 u1_exact(x[0]) * u2_exact_grad(x[1]))
54 .finished();
55 };
56
57 auto epsilon = [eps](const Eigen::Vector2d & /*x*/) -> double {
58 return eps;
59 };
60 auto beta = [b1, b2](const Eigen::Vector2d & /*x*/) -> Eigen::Vector2d {
61 return (Eigen::VectorXd(2) << b1, b2).finished();
62 };
63
64 auto f = [eps, b1, b2, &u1_exact, &u1_exact_grad, &u1_exact_d2, &u2_exact,
65 &u2_exact_grad,
66 &u2_exact_d2](const Eigen::Vector2d& x) -> double {
67 return -eps * (u1_exact_d2(x[0]) * u2_exact(x[1]) +
68 u1_exact(x[0]) * u2_exact_d2(x[1])) +
69 b1 * u1_exact_grad(x[0]) * u2_exact(x[1]) +
70 b2 * u1_exact(x[0]) * u2_exact_grad(x[1]);
71 };
72 auto g = [](const Eigen::Vector2d & /*x*/) -> double { return 0.0; };
73
74 // specification of degree and enrichement for the method
75 int deg_p = 2;
76 int delta_p = 1;
77
78 //------------------------
79 // run the convergence test
80 //------------------------
81 std::cout << "Running convergence tests on a triangular mesh (eps= " << eps
82 << ")\n";
83 auto errors = projects::dpg::test::
85 reflev, u_exact, u_grad, epsilon, beta, f, g, deg_p, delta_p,
87
88 // output to a corresponding file
89 std::string file_name = "cs5/" + std::to_string(eps);
90 std::ofstream file(file_name);
91 for (auto [dofs, h1error, errorestimator] : errors) {
92 file << dofs << ", " << h1error << ", " << errorestimator << std::endl;
93 }
94 file.close();
95 }
96
97 return 0;
98}
static constexpr RefEl kTria()
Returns the reference triangle.
Definition: ref_el.h:158
energy_vector TestConververgencePrimalDPGAdaptedNormConvectionDiffusionDirichletBVP(size_type reflevels, SOLFUNC solution, SOLGRAD sol_grad, ALPHAFUNC alpha, BETAFUNC beta, FFUNC f, GFUNC g, int degree_p, int enrichement, lf::base::RefEl ref_el)
Examines the convergence behaviour of the primal DPG method for a pure Dirichlet convection-diffusion...