LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
convergence_study4.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 5
9
10int main() {
11 std::cout << "Convergence study 4: Ultraweak 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 sigma = [eps, &u1_exact, &u2_exact, &u1_exact_grad,
50 &u2_exact_grad](const Eigen::Vector2d& x) -> Eigen::Vector2d {
51 return (Eigen::VectorXd(2) << eps * u1_exact_grad(x[0]) * u2_exact(x[1]),
52 eps * 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 = 1;
75 int delta_p = 2;
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::
83 TestConververgenceUltraWeakDPGConvectionDiffusionDirichletBVP(
84 reflev, u_exact, sigma, epsilon, beta, f, g, deg_p, delta_p,
86
87 // output to a corresponding file
88 std::string file_name = "cs4/" + std::to_string(eps);
89 std::ofstream file(file_name);
90 for (auto [dofs, error_u, error_s, errorestimator] : errors) {
91 file << dofs << ", " << error_u << ", " << error_s << ", "
92 << 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