LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
Loading...
Searching...
No Matches
torus_mesh_builder.cc
1
9#include "torus_mesh_builder.h"
10
11#include <lf/geometry/geometry.h>
12#include <spdlog/spdlog.h>
13
14#include <cmath>
15#include <iostream>
16
17#include "lf/mesh/mesh_interface.h"
18
19namespace lf::mesh::utils {
20
21std::shared_ptr<spdlog::logger>& TorusMeshBuilder::Logger() {
22 static auto logger =
23 base::InitLogger("lf::mesh::utils::TorusMeshBuilder::Logger");
24 return logger;
25}
26
27std::shared_ptr<mesh::Mesh> TorusMeshBuilder::Build() {
28 using coord_t = Eigen::Vector3d;
29
30 const size_type nx = num_of_x_cells_;
31 const size_type ny = num_of_y_cells_;
32
33 // opposite edges and vertices are identical and only counted once
34 const unsigned no_of_cells = nx * ny;
35 const unsigned no_of_edges = 2 * nx * ny;
36 const unsigned no_of_vertices = nx * ny;
37
38 if (no_of_cells == 0) {
39 return nullptr;
40 }
41
42 const double x_size = top_right_corner_[0] - bottom_left_corner_[0];
43 const double y_size = top_right_corner_[1] - bottom_left_corner_[1];
44
45 if ((x_size <= 0.0) || (y_size <= 0.0)) {
46 return nullptr;
47 }
48
49 // calculate mesh width of uniform grid on rectangle
50 const double hx = x_size / nx;
51 const double hy = y_size / ny;
52
53 // parametrize torus: https://en.wikipedia.org/wiki/Torus#Geometry
54 const double r = x_size / (2. * lf::base::kPi);
55 const double R = y_size / (2. * lf::base::kPi);
56 auto theta = [r, hx](double i) -> double { return (i * hx) / r; };
57 auto phi = [R, hy](double j) -> double { return (j * hy) / R; };
58
59 SPDLOG_LOGGER_DEBUG(
60 Logger(),
61 "TorusMesh: {} cells, {} edges, {} vertices, mesh widths hx/hy = {}/{}",
62 no_of_cells, no_of_edges, no_of_vertices, hx, hy);
63
64 // compute vertices of mesh on torus with lexicographic numbering
65 std::vector<size_type> v_idx(no_of_vertices);
66 int node_cnt = 0;
67
68 for (size_type j = 0; j < ny; ++j) {
69 for (size_type i = 0; i < nx; ++i, ++node_cnt) {
70 // compute vertex coordinates
71 coord_t node_coord;
72 node_coord << (R + r * std::cos(theta(i))) * std::cos(phi(j)),
73 (R + r * std::cos(theta(i))) * std::sin(phi(j)),
74 r * std::sin(theta(i));
75
76 SPDLOG_LOGGER_TRACE(Logger(), "Adding vertex {}: {}", node_cnt,
77 node_coord.transpose());
78 // register vertex
79 v_idx[node_cnt] = mesh_factory_->AddPoint(node_coord);
80 }
81 }
82
83 // compute cells of mesh on torus
84 std::vector<size_type> t_idx(no_of_cells);
85 size_type quad_cnt = 0;
86
87 for (size_type i = 0; i < nx; ++i) {
88 for (size_type j = 0; j < ny; ++j, quad_cnt++) {
89 // gather vertex indices of given cell wrapping around edges of rectangle
90 std::vector<size_type> vertex_index_list{
91 v_idx[VertexIndex(i, j)], v_idx[VertexIndex((i + 1) % nx, j)],
92 v_idx[VertexIndex((i + 1) % nx, (j + 1) % ny)],
93 v_idx[VertexIndex(i, (j + 1) % ny)]};
94
95 Eigen::Matrix<double, 3, 4> quad_geo;
96 quad_geo << (R + r * std::cos(theta(i))) * std::cos(phi(j)),
97 (R + r * std::cos(theta(i + 1))) * std::cos(phi(j)),
98 (R + r * std::cos(theta(i + 1))) * std::cos(phi(j + 1)),
99 (R + r * std::cos(theta(i))) * std::cos(phi(j + 1)),
100 (R + r * std::cos(theta(i))) * std::sin(phi(j)),
101 (R + r * std::cos(theta(i + 1))) * std::sin(phi(j)),
102 (R + r * std::cos(theta(i + 1))) * std::sin(phi(j + 1)),
103 (R + r * std::cos(theta(i))) * std::sin(phi(j + 1)),
104 r * std::sin(theta(i)), r * std::sin(theta(i + 1)),
105 r * std::sin(theta(i + 1)), r * std::sin(theta(i));
106
107 SPDLOG_LOGGER_TRACE(Logger(), "Adding quad {}:\n{}", quad_cnt, quad_geo);
108
109 // request cell production from MeshFactory (straight edges will be
110 // created as needed)
111 t_idx[quad_cnt] = mesh_factory_->AddEntity(
112 lf::base::RefEl::kQuad(), vertex_index_list,
113 std::make_unique<geometry::QuadO1>(quad_geo));
114 }
115 }
116
117 return mesh_factory_->Build();
118} // TorusMeshBuilder::Build()
119
120} // namespace lf::mesh::utils
static constexpr RefEl kQuad()
Returns the reference quadrilateral.
Definition ref_el.h:169
std::unique_ptr< mesh::MeshFactory > mesh_factory_
size_type VertexIndex(size_type i, size_type j) const
vertex index from grid position
std::shared_ptr< mesh::Mesh > Build() override
actual construction of the mesh
static std::shared_ptr< spdlog::logger > & Logger()
logger that is used by Build() to provide additional debug info.
std::shared_ptr< spdlog::logger > InitLogger(const std::string &name)
Create a spdlog logger, register it in the spdlog registry and initialize it with LehrFEM++ specific ...
constexpr double kPi
Definition types.h:39
Contains helper functions and classes that all operate on the interface classes defined in lf::mesh.