LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
vortex.cc
1
6#include <build_system_matrix.h>
7#include <lf/assemble/dofhandler.h>
8#include <lf/io/gmsh_reader.h>
9#include <lf/io/vtk_writer.h>
10#include <lf/mesh/entity.h>
11#include <lf/mesh/hybrid2d/mesh_factory.h>
12#include <lf/mesh/utils/tp_triag_mesh_builder.h>
13#include <lf/quad/quad.h>
14#include <lf/refinement/refinement.h>
15#include <piecewise_const_element_matrix_provider.h>
16#include <piecewise_const_element_vector_provider.h>
17#include <solution_to_mesh_data_set.h>
18
19#include <Eigen/Dense>
20#include <Eigen/Sparse>
21#include <cassert>
22#include <filesystem>
23
32Eigen::VectorXd solveLidDrivenCavity(
33 const std::shared_ptr<const lf::mesh::Mesh> &mesh,
34 const lf::assemble::DofHandler &dofh, bool modified = false) {
35 // No volume forces are present in this experiment
36 auto f = [](const Eigen::Vector2d & /*unused*/) -> Eigen::Vector2d {
37 return Eigen::Vector2d::Zero();
38 };
39 // The top lid is driven with velocity 1
40 auto dirichlet_funct = [](const lf::mesh::Entity &edge) -> Eigen::Vector2d {
41 static constexpr double eps = 1e-10;
42 const auto *const geom = edge.Geometry();
43 const auto vertices = geom->Global(edge.RefEl().NodeCoords());
44 Eigen::Vector2d v;
45 v << 1. / 100, 0;
46 if (vertices(1, 0) <= 100 + eps && vertices(1, 0) >= 100 - eps &&
47 vertices(1, 1) <= 100 + eps && vertices(1, 1) >= 100 - eps) {
48 return v;
49 }
50 return Eigen::Vector2d::Zero();
51 };
52
53 // Solve the LSE using sparse cholesky
54 const auto [A, rhs] =
56 mesh, dofh, f, dirichlet_funct, 1,
58 Eigen::SparseMatrix<double> As = A.makeSparse();
59 Eigen::SparseLU<Eigen::SparseMatrix<double>> solver;
60 solver.compute(As);
61 return solver.solve(rhs);
62}
63
67int main() {
68 const double mu = 1;
69 const double sigma = 1;
70 const double rho = 1;
71
72 // Load the mesh
73 std::filesystem::path meshpath = __FILE__;
74 meshpath = meshpath.parent_path() / "mesh.msh";
75 std::unique_ptr<lf::mesh::MeshFactory> factory =
76 std::make_unique<lf::mesh::hybrid2d::MeshFactory>(2);
77 lf::io::GmshReader reader(std::move(factory), meshpath.string());
78 auto mesh = reader.mesh();
79
80 const auto boundary = lf::mesh::utils::flagEntitiesOnBoundary(mesh);
81
84 std::cout << "solving original" << std::endl;
85 const Eigen::VectorXd solution_original =
86 solveLidDrivenCavity(mesh, dofh, false);
87 std::cout << "extracting original" << std::endl;
88 const auto c_original =
90 mesh, dofh, solution_original);
91 const auto v_original =
93 mesh, dofh, solution_original);
94 std::cout << "solving modified" << std::endl;
95 const Eigen::VectorXd solution_modified =
96 solveLidDrivenCavity(mesh, dofh, true);
97 std::cout << "extracting modified" << std::endl;
98 const auto c_modified =
100 mesh, dofh, solution_modified);
101 const auto v_modified =
103 mesh, dofh, solution_modified);
104
105 std::cout << "writing" << std::endl;
106 lf::io::VtkWriter writer(mesh, "vortex.vtk");
107 writer.WritePointData("coefficients_original", c_original);
108 writer.WritePointData("coefficients_modified", c_modified);
109 writer.WriteCellData("velocity_original", v_original);
110 writer.WriteCellData("velocity_modified", v_modified);
111
112 return 0;
113}
A general (interface) class for DOF handling, see Lecture Document Paragraph 2.7.4....
Definition: dofhandler.h:109
Dofhandler for uniform finite element spaces.
Definition: dofhandler.h:257
static constexpr RefEl kSegment()
Returns the (1-dimensional) reference segment.
Definition: ref_el.h:150
static constexpr RefEl kPoint()
Returns the (0-dimensional) reference point.
Definition: ref_el.h:141
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
Interface class representing a topological entity in a cellular complex
Definition: entity.h:39
QuadRule make_TriaQR_MidpointRule()
midpoint quadrature rule for triangles
CodimMeshDataSet< bool > flagEntitiesOnBoundary(const std::shared_ptr< const Mesh > &mesh_p, lf::base::dim_t codim)
flag entities of a specific co-dimension located on the boundary
std::tuple< lf::assemble::COOMatrix< double >, Eigen::VectorXd > buildSystemMatrixNoFlow(const std::shared_ptr< const lf::mesh::Mesh > &mesh, const lf::assemble::DofHandler &dofh, const std::function< Eigen::Vector2d(const Eigen::Vector2d &)> &f, const std::function< Eigen::Vector2d(const lf::mesh::Entity &)> &dirichlet_data, double sigma, const lf::quad::QuadRule &quadrule, bool modified_penalty)
Build the system matrix for the stokes system with no flow boundary conditions.
lf::mesh::utils::CodimMeshDataSet< Eigen::Vector2d > extractVelocity(const std::shared_ptr< const lf::mesh::Mesh > &mesh, const lf::assemble::DofHandler &dofh, const Eigen::VectorXd &solution)
Extract the flow velocity on cells from the solution vector.
lf::mesh::utils::CodimMeshDataSet< double > extractBasisFunctionCoefficients(const std::shared_ptr< const lf::mesh::Mesh > &mesh, const lf::assemble::DofHandler &dofh, const Eigen::VectorXd &solution)
Extract the basis function coefficients from the solution vector.