LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
modelproblem_circle_main.cc
1
8#include <lf/io/io.h>
9
10#include <cstdlib>
11#include <filesystem>
12#include <iostream>
13#include <stdexcept>
14#include <string>
15#include <vector>
16
17#include "strangsplitting.h"
18
20
21int main(int /*argc*/, char ** /*argv*/) {
22 /* Obtain mesh */
23 auto mesh_factory = std::make_unique<lf::mesh::hybrid2d::MeshFactory>(2);
24 std::filesystem::path here = __FILE__;
25
26 /* In case of one circle: Mesh 1. */
27 auto mesh_file = (here.parent_path() / "/meshes/circle.msh").string();
28 const lf::io::GmshReader reader(std::move(mesh_factory), mesh_file);
29 std::shared_ptr<const lf::mesh::Mesh> mesh_p = reader.mesh();
30 /* Finite Element Space */
31 std::shared_ptr<lf::uscalfe::UniformScalarFESpace<double>> fe_space =
32 std::make_shared<lf::uscalfe::FeSpaceLagrangeO1<double>>(mesh_p);
33 /* Dofhandler */
34 const lf::assemble::DofHandler &dofh{fe_space->LocGlobMap()};
35 const lf::uscalfe::size_type N_dofs(dofh.NumDofs());
36
37 std::cout << "N_dofs :" << N_dofs << std::endl;
38
39 /* Initial Population density */
40 Eigen::VectorXd u0(N_dofs);
41 u0.setZero();
42
43 /* In case of the circle: Mesh 1. For one source only: */
44 u0(0) = 0.001;
45 /* For two sources on the circle: */
46 /* u0(0) = 0.0005;
47 * u0(53) = 0.0005;
48 */
49
50 std::cout << "norm u0 " << u0.norm() << std::endl;
51
52 /* Diffusion Coefficient */
53 auto c = [](const Eigen::Vector2d & /*x*/) -> double {
54 /* In case of the circle: Mesh 1. */
55 return 0.007;
56 };
57
58 /* Growth Factor */
59 /* In case of the circle: Mesh 1. */
60 double lambda = 0.008;
61
62 /* Boundary Conditions. */
63
64 /* In case of the circle: Mesh 1. */
65 auto h = [](const Eigen::Vector2d & /*x*/) -> double { return 0.0; };
66 Eigen::MatrixXd L(N_dofs, N_dofs);
67 L.setZero();
68
69 /* Strang Splitting Method
70 * SDIRK-2 evolution of linear parabolic term
71 * Exact Evolution for nonlinear reaction term
72 */
73
74 /* Total number of timesteps */
75 unsigned int m = 100;
76 double T = 1.; // the timestepsize tau will equal T/m = 0.01
77
78 /* First we assemble the carrying capacity maps */
79
80 Eigen::VectorXd cap(N_dofs);
81 cap.setZero();
82 cap = 0.8 * Eigen::VectorXd::Ones(N_dofs);
83
84 /* Now we may compute the solution */
85 StrangSplit StrangSplitter(fe_space, T, m, lambda, c, h, L);
86
87 Eigen::MatrixXd sol(N_dofs, 20);
88
89 sol.col(0) = StrangSplitter.Evolution(cap, u0);
90 std::cout << "sol1" << std::endl;
91 sol.col(1) = StrangSplitter.Evolution(cap, sol.col(0));
92 std::cout << "sol2" << std::endl;
93 sol.col(2) = StrangSplitter.Evolution(cap, sol.col(1));
94 std::cout << "sol3" << std::endl;
95 sol.col(3) = StrangSplitter.Evolution(cap, sol.col(2));
96 std::cout << "sol4" << std::endl;
97 sol.col(4) = StrangSplitter.Evolution(cap, sol.col(3));
98 std::cout << "sol5" << std::endl;
99
100 /* Use VTK-Writer for Visualization of solution */
101
102 for (int k = 1; k < 6; k++) {
103 std::stringstream filename;
104 filename << "sol" << k << ".vtk";
105
106 lf::io::VtkWriter vtk_writer(mesh_p, filename.str());
107 auto nodal_data = lf::mesh::utils::make_CodimMeshDataSet<double>(mesh_p, 2);
108 for (int global_idx = 0; global_idx < N_dofs; global_idx++) {
109 nodal_data->operator()(dofh.Entity(global_idx)) =
110 sol.col(k - 1)[global_idx];
111 }
112
113 vtk_writer.WritePointData("sol", *nodal_data);
114 }
115
116 return 0;
117}
A general (interface) class for DOF handling, see Lecture Document Paragraph 2.7.4....
Definition: dofhandler.h:109
Reads a Gmsh *.msh file into a mesh::MeshFactory and provides a link between mesh::Entity objects and...
Definition: gmsh_reader.h:70
Write a mesh along with mesh data into a vtk file.
Definition: vtk_writer.h:272
lf::assemble::size_type size_type
Definition: lagr_fe.h:30