LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
convergence_study1.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 4
9
10int main() {
11 std::cout << "Convergence study 1: Primal DPG method, smooth solution \n";
12 std::cout << "Exact solution: u(x,y) = sin(pi*x)sin(pi*y), homogenous "
13 "dirichlet b.c. \n";
14 std::cout << "BVP 1: epsilon_1=1.0, beta_1=[0.0,0.0] \n";
15 std::cout << "BVP 2: epsilon_2=1.0, beta_2=[2.0,1.0] \n ";
16 std::cout << "p = {1,2}, enrichement delta_p = {1,2} \n";
17
18 // specify the boundary value problems:
19 // exact solution:
20 const double PI = lf::base::kPi;
21 auto u_exact = [PI](const Eigen::Vector2d& x) -> double {
22 return std::sin(PI * x[0]) * std::sin(PI * x[1]);
23 };
24 auto u_grad = [PI](const Eigen::Vector2d& x) -> Eigen::Vector2d {
25 return (Eigen::VectorXd(2)
26 << PI * std::cos(PI * x[0]) * std::sin(PI * x[1]),
27 PI * std::sin(PI * x[0]) * std::cos(PI * x[1]))
28 .finished();
29 };
30
31 // BVP1:
32 auto epsilon_1 = [](const Eigen::Vector2d & /*x*/) -> double { return 1.0; };
33 auto beta_1 = [](const Eigen::Vector2d & /*x*/) -> Eigen::Vector2d {
34 return (Eigen::VectorXd(2) << 0.0, 0.0).finished();
35 };
36 auto f_1 = [PI](const Eigen::Vector2d& x) -> double {
37 return 2.0 * PI * PI * std::sin(PI * x[0]) * std::sin(PI * x[1]);
38 };
39 auto g_1 = [](const Eigen::Vector2d & /*x*/) -> double { return 0.0; };
40
41 // BVP 2:
42 auto epsilon_2 = [](const Eigen::Vector2d & /*x*/) -> double { return 1.0; };
43 auto beta_2 = [PI](const Eigen::Vector2d & /*x*/) -> Eigen::Vector2d {
44 return (Eigen::VectorXd(2) << 2.0, 1.0).finished();
45 };
46 auto f_2 = [PI](const Eigen::Vector2d& x) -> double {
47 return 2.0 * PI * PI * std::sin(PI * x[0]) * std::sin(PI * x[1]) +
48 PI * (2.0 * std::cos(PI * x[0]) * std::sin(PI * x[1]) +
49 std::sin(PI * x[0]) * std::cos(PI * x[1]));
50 };
51 auto g_2 = [](const Eigen::Vector2d & /*x*/) -> double { return 0.0; };
52
53 //-----------------------------------------
54 // Convergence tests on a triangluar mesh -
55 //-----------------------------------------
56 // run the convergence tests choosing different approxiamtion orders and
57 // enrichement degrees:
58 std::cout << "Running convergence tests for BVP 1 on a triangular mesh.\n";
59 for (int deg_p = 1; deg_p <= 2; deg_p++) {
60 for (int delta_p = 1; delta_p <= 3 - deg_p; delta_p++) {
61 auto errors = projects::dpg::test::
63 reflev, u_exact, u_grad, epsilon_1, beta_1, f_1, g_1, deg_p,
64 delta_p, lf::base::RefEl::kTria());
65
66 // output to a corresponding file
67 std::string file_name = "cs1/triangular/bvp1_" + std::to_string(deg_p) +
68 "_" + std::to_string(delta_p);
69 std::ofstream file(file_name);
70 for (auto [dofs, h1error, estimator] : errors) {
71 file << dofs << ", " << h1error << ", " << estimator << std::endl;
72 }
73 file.close();
74 }
75 }
76
77 std::cout << "Running convergence tests for BVP 2 on a triangular mesh\n";
78 for (int deg_p = 1; deg_p <= 2; deg_p++) {
79 for (int delta_p = 1; delta_p <= 3 - deg_p; delta_p++) {
80 auto errors = projects::dpg::test::
82 reflev, u_exact, u_grad, epsilon_2, beta_2, f_2, g_2, deg_p,
83 delta_p, lf::base::RefEl::kTria());
84 std::string file_name = "cs1/triangular/bvp2_" + std::to_string(deg_p) +
85 "_" + std::to_string(delta_p);
86 std::ofstream file(file_name);
87 for (auto [dofs, h1error, estimator] : errors) {
88 file << dofs << ", " << h1error << ", " << estimator << std::endl;
89 }
90 file.close();
91 }
92 }
93
94 //--------------------------------------------
95 // Convergence tests on a quadrilateral mesh -
96 //--------------------------------------------
97 std::cout << "Running convergence tests for BVP 1 on a quadrilateral mesh\n";
98 for (int deg_p = 1; deg_p <= 2; deg_p++) {
99 for (int delta_p = 1; delta_p <= 3 - deg_p; delta_p++) {
100 auto errors = projects::dpg::test::
102 reflev, u_exact, u_grad, epsilon_1, beta_1, f_1, g_1, deg_p,
103 delta_p, lf::base::RefEl::kQuad());
104
105 // output to a corresponding file
106 std::string file_name = "cs1/quadrilateral/bvp1_" +
107 std::to_string(deg_p) + "_" +
108 std::to_string(delta_p);
109 std::ofstream file(file_name);
110 for (auto [dofs, h1error, estimator] : errors) {
111 file << dofs << ", " << h1error << ", " << estimator << std::endl;
112 }
113 file.close();
114 }
115 }
116
117 std::cout << "Running convergence tests for BVP 2 on a quadrilateral mesh \n";
118 for (int deg_p = 1; deg_p <= 2; deg_p++) {
119 for (int delta_p = 1; delta_p <= 3 - deg_p; delta_p++) {
120 auto errors = projects::dpg::test::
122 reflev, u_exact, u_grad, epsilon_2, beta_2, f_2, g_2, deg_p,
123 delta_p, lf::base::RefEl::kQuad());
124 std::string file_name = "cs1/quadrilateral/bvp2_" +
125 std::to_string(deg_p) + "_" +
126 std::to_string(delta_p);
127 std::ofstream file(file_name);
128 for (auto [dofs, h1error, estimator] : errors) {
129 file << dofs << ", " << h1error << ", " << estimator << std::endl;
130 }
131 file.close();
132 }
133 }
134
135 return 0;
136}
static constexpr RefEl kTria()
Returns the reference triangle.
Definition: ref_el.h:158
static constexpr RefEl kQuad()
Returns the reference quadrilateral.
Definition: ref_el.h:166
constexpr double kPi
Definition: base.h:43
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