LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
convergence_study3.cc
1#include <cmath>
2#include <fstream>
3#include <iomanip>
4
5#include "primal_dpg.h"
6#include "ultraweak_dpg.h"
7
8#define reflev 7
9
10int main() {
11 std::cout << "Convergence study 4: 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
15 std::vector<double> epsilon_values = {1, 0.5, 0.1, 0.05, 0.02, 0.01};
16 const double b1 = 2.0;
17 const double b2 = 1.0;
18
19 for (const double eps : epsilon_values) {
20 //------------------------
21 // Specification of the BVP
22 //------------------------
23 // exact solution:
24 auto u1_exact = [eps, b1](double x) -> double {
25 return x + (std::exp(x * b1 / eps) - 1) / (1 - std::exp(b1 / eps));
26 };
27 auto u1_exact_grad = [eps, b1](double x) -> double {
28 return 1 + b1 / eps * std::exp(x * b1 / eps) / (1 - std::exp(b1 / eps));
29 };
30 auto u1_exact_d2 = [eps, b1](double x) -> double {
31 return b1 * b1 / (eps * eps) * std::exp(x * b1 / eps) /
32 (1 - std::exp(b1 / eps));
33 };
34
35 auto u2_exact = [eps, b2](double y) -> double {
36 return y + (std::exp(y * b2 / eps) - 1) / (1 - std::exp(b2 / eps));
37 };
38 auto u2_exact_grad = [eps, b2](double y) -> double {
39 return 1 + b2 / eps * std::exp(y * b2 / eps) / (1 - std::exp(b2 / eps));
40 };
41 auto u2_exact_d2 = [eps, b2](double y) -> double {
42 return b2 * b2 / (eps * eps) * std::exp(y * b2 / eps) /
43 (1 - std::exp(b2 / eps));
44 };
45
46 auto u_exact = [&u1_exact, &u2_exact](const Eigen::Vector2d& x) -> double {
47 return u1_exact(x[0]) * u2_exact(x[1]);
48 };
49 auto u_grad = [eps, &u1_exact, &u2_exact, &u1_exact_grad, &u2_exact_grad](
50 const Eigen::Vector2d& x) -> Eigen::Vector2d {
51 return (Eigen::VectorXd(2) << u1_exact_grad(x[0]) * u2_exact(x[1]),
52 u1_exact(x[0]) * u2_exact_grad(x[1]))
53 .finished();
54 };
55
56 auto epsilon = [eps](const Eigen::Vector2d & /*x*/) -> double {
57 return eps;
58 };
59 auto beta = [b1, b2](const Eigen::Vector2d & /*x*/) -> Eigen::Vector2d {
60 return (Eigen::VectorXd(2) << b1, b2).finished();
61 };
62
63 auto f = [eps, b1, b2, &u1_exact, &u1_exact_grad, &u1_exact_d2, &u2_exact,
64 &u2_exact_grad,
65 &u2_exact_d2](const Eigen::Vector2d& x) -> double {
66 return -eps * (u1_exact_d2(x[0]) * u2_exact(x[1]) +
67 u1_exact(x[0]) * u2_exact_d2(x[1])) +
68 b1 * u1_exact_grad(x[0]) * u2_exact(x[1]) +
69 b2 * u1_exact(x[0]) * u2_exact_grad(x[1]);
70 };
71 auto g = [](const Eigen::Vector2d & /*x*/) -> double { return 0.0; };
72
73 // specification of degree and enrichement for the method
74 int deg_p = 2;
75 int delta_p = 1;
76
77 //------------------------
78 // run the convergence test
79 //------------------------
80 std::cout << "Running convergence tests on a triangular mesh (eps= " << eps
81 << ")\n";
82 auto errors = projects::dpg::test::
84 reflev, u_exact, u_grad, epsilon, beta, f, g, deg_p, delta_p,
86
87 // output to a corresponding file
88 std::string file_name = "cs3/" + std::to_string(eps);
89 std::ofstream file(file_name);
90 for (auto [dofs, h1error, errorestimator] : errors) {
91 file << dofs << ", " << h1error << ", " << errorestimator << std::endl;
92 }
93 file.close();
94 }
95
96 return 0;
97}
static constexpr RefEl kTria()
Returns the reference triangle.
Definition: ref_el.h:158
energy_vector TestConververgencePrimalDPGConvectionDiffusionDirichletBVP(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...
Definition: primal_dpg.h:58