6#define _USE_MATH_DEFINES
7#include <build_system_matrix.h>
8#include <lf/assemble/dofhandler.h>
10#include <lf/io/gmsh_reader.h>
11#include <lf/io/vtk_writer.h>
12#include <lf/mesh/entity.h>
13#include <lf/mesh/hybrid2d/mesh_factory.h>
14#include <lf/mesh/utils/tp_triag_mesh_builder.h>
15#include <lf/mesh/utils/utils.h>
16#include <lf/quad/quad.h>
17#include <lf/refinement/refinement.h>
18#include <mesh_function_velocity.h>
20#include <piecewise_const_element_matrix_provider.h>
21#include <piecewise_const_element_vector_provider.h>
22#include <solution_to_mesh_data_set.h>
37Eigen::Vector2d computeU(
int n, Eigen::Vector2d x) {
38 const double r = x.norm();
39 const double u0 = 1 - std::cos(2 * M_PI * n * r);
42 return u0 * u.normalized();
51Eigen::Matrix2d computeUGrad(
int n, Eigen::Vector2d x) {
52 const double r = x.norm();
53 const double r2 = r * r;
54 const double r3 = r2 * r;
55 const double phi = 2 * M_PI * n * r;
56 const double cphi = std::cos(phi);
57 const double sphi = std::sin(phi);
59 grad << x[0] * x[1] / r3 * (1 - cphi) -
60 2 * M_PI * n * x[0] * x[1] / r2 * sphi,
61 (1. / r - x[0] * x[0] / r3) * (1 - cphi) +
62 2 * M_PI * n * x[0] * x[0] / r2 * sphi,
63 (x[0] * x[1] / r3 - 1. / r) * (1 - cphi) +
64 2 * M_PI * n * x[1] * x[1] / r2 * sphi,
65 -x[0] * x[1] / r3 * (1 - cphi) + 2 * M_PI * n * x[0] * x[1] / r2 * sphi;
75Eigen::Vector2d computeF(
int n, Eigen::Vector2d x) {
76 const double r = x.norm();
77 const double f0 = r == 0 ? -6 * n * n * M_PI * M_PI
79 (1 + 4 * n * n * M_PI * M_PI * r * r) *
80 std::cos(2 * M_PI * n * r) -
81 2 * M_PI * n * r * std::sin(2 * M_PI * n * r)) /
85 return f0 * f.normalized();
94template <
typename... Args>
95static std::string concat(Args&&... args) {
96 std::ostringstream ss;
105 std::shared_ptr<const lf::mesh::Mesh>
mesh;
106 std::shared_ptr<const lf::assemble::DofHandler>
dofh;
107 Eigen::SparseMatrix<double>
A;
123 const unsigned mesh_count = 6;
125 const unsigned quadrule_degree = 10;
128 std::vector<ProblemSolution> solutions(mesh_count);
130 std::filesystem::path meshpath = __FILE__;
131 meshpath = meshpath.parent_path() / concat(
"disk", lvl,
".msh");
132 std::unique_ptr<lf::mesh::MeshFactory> factory =
133 std::make_unique<lf::mesh::hybrid2d::MeshFactory>(2);
135 auto mesh = reader.mesh();
136 auto& sol = solutions[lvl];
138 sol.dofh = std::shared_ptr<const lf::assemble::DofHandler>(
143 auto f = [n](
const Eigen::Vector2d& x) -> Eigen::Vector2d {
144 return computeF(n, x);
148 ) -> Eigen::Vector2d {
149 return Eigen::Vector2d::Zero();
151 const auto [A, rhs] =
153 sol.mesh, *(sol.dofh), f, dirichlet_funct, 1,
156 sol.A = A.makeSparse();
158 Eigen::SparseLU<Eigen::SparseMatrix<double>> solver;
159 solver.compute(sol.A);
160 sol.solution = solver.solve(rhs);
161 const auto [A_modified, rhs_modified] =
163 sol.mesh, *(sol.dofh), f, dirichlet_funct, 1,
166 sol.A_modified = A_modified.makeSparse();
167 Eigen::SparseLU<Eigen::SparseMatrix<double>> solver_modified(
169 sol.solution_modified = solver_modified.solve(rhs_modified);
174 [&](
const Eigen::Vector2d& x) -> Eigen::Vector2d {
175 return computeU(n, x);
178 [&](
const Eigen::Vector2d& x) -> Eigen::Vector2d {
179 return computeF(n, x);
182 const auto fe_space =
183 std::make_shared<lf::uscalfe::FeSpaceLagrangeO1<double>>(
184 solutions[lvl].mesh);
186 [n](
const Eigen::Vector2d& x) {
return computeU(n, x); });
188 [n](
const Eigen::Vector2d& x) -> Eigen::Matrix2d {
189 return computeUGrad(n, x);
192 velocity(fe_space, solutions[lvl].solution);
194 velocity_modified(fe_space, solutions[lvl].solution_modified);
196 concat(
"result", lvl,
".vtk"));
197 writer.WriteCellData(
"analyticU", analyticU);
198 writer.WriteCellData(
"analyticF", analyticF);
199 writer.WriteCellData(
"U", velocity);
200 writer.WriteCellData(
"U_modified", velocity_modified);
202 const auto diff_v = velocity - velocity_exact;
203 const auto diff_v_modified = velocity_modified - velocity_exact;
205 const auto diff_grad = -grad_exact;
206 const auto diff_grad_modified = -grad_exact;
211 const double factor =
213 *(solutions[lvl].mesh),
214 lf::mesh::utils::transpose(velocity) * velocity_exact,
217 lf::mesh::utils::squaredNorm(velocity),
219 const double factor_modified =
221 *(solutions[lvl].mesh),
222 lf::mesh::utils::transpose(velocity_modified) * velocity_exact,
225 *(solutions[lvl].mesh),
226 lf::mesh::utils::squaredNorm(velocity_modified), qr_provider);
227 std::cout << factor << std::endl;
229 const auto velocity_scaled =
231 const auto velocity_scaled_modified =
234 const auto diff_v_fac = velocity_scaled - velocity_exact;
235 const auto diff_v_fac_modified = velocity_scaled_modified - velocity_exact;
237 const auto& diff_g_fac = diff_grad;
238 const auto& diff_g_fac_modified = diff_grad_modified;
240 solutions[lvl].mesh, diff_v, qr_provider);
242 solutions[lvl].mesh, diff_v, diff_grad, qr_provider);
244 solutions[lvl].mesh, diff_v_fac, qr_provider);
246 solutions[lvl].mesh, diff_v_fac, diff_g_fac, qr_provider);
248 solutions[lvl].mesh, diff_v_modified, qr_provider);
250 solutions[lvl].mesh, diff_v_modified, diff_grad_modified, qr_provider);
252 solutions[lvl].mesh, diff_v_fac_modified, qr_provider);
254 solutions[lvl].mesh, diff_v_fac_modified, diff_g_fac_modified,
256 std::cout << lvl <<
' ' << solutions[lvl].mesh->NumEntities(2) <<
' ' << L2
257 <<
' ' << DG <<
' ' << L2f <<
' ' << DGf <<
' ' << L2_modified
258 <<
' ' << DG_modified <<
' ' << L2f_modified <<
' '
259 << DGf_modified << std::endl;
static constexpr RefEl kSegment()
Returns the (1-dimensional) reference segment.
static constexpr RefEl kPoint()
Returns the (0-dimensional) reference point.
static constexpr RefEl kTria()
Returns the reference triangle.
Reads a Gmsh *.msh file into a mesh::MeshFactory and provides a link between mesh::Entity objects and...
Write a mesh along with mesh data into a vtk file.
Interface class representing a topological entity in a cellular complex
A MeshFunction which takes the same constant value on the whole mesh.
MeshFunction wrapper for a simple function of physical coordinates.
A MeshFunction returning the velocity computed from the basis function coefficients of a vector poten...
unsigned int size_type
general type for variables related to size of arrays
auto IntegrateMeshFunction(const lf::mesh::Mesh &mesh, const MF &mf, const QR_SELECTOR &qr_selector, const ENTITY_PREDICATE &ep=base::PredicateTrue{}, int codim=0) -> mesh::utils::MeshFunctionReturnType< MF >
Integrate a MeshFunction over a mesh (with quadrature rules)
QuadRule make_QuadRule(base::RefEl ref_el, unsigned degree)
Returns a QuadRule object for the given Reference Element and Degree.
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.
double DGnorm(const std::shared_ptr< const lf::mesh::Mesh > &mesh, const MF_F &f, const MF_GRAD &f_grad, const QR_SELECTOR &qr_selector)
Compute the DG-norm of a vector valued function over a mesh.
double L2norm(const std::shared_ptr< const lf::mesh::Mesh > &mesh, const MF &f, const QR_SELECTOR &qr_selector)
Compute the -norm of a vector valued function over a mesh.
stores information to recover convergence properties
Eigen::SparseMatrix< double > A_modified
Eigen::VectorXd solution_modified
Eigen::SparseMatrix< double > A
std::shared_ptr< const lf::mesh::Mesh > mesh
std::shared_ptr< const lf::assemble::DofHandler > dofh