17#include "strangsplitting.h"
22int main(
int ,
char** ) {
24 auto mesh_factory = std::make_unique<lf::mesh::hybrid2d::MeshFactory>(2);
25 std::filesystem::path here = __FILE__;
26 auto mesh_file = (here.parent_path() /
"/meshes/earth.msh").
string();
28 std::shared_ptr<const lf::mesh::Mesh> mesh_p = reader.mesh();
30 std::shared_ptr<lf::uscalfe::UniformScalarFESpace<double>> fe_space =
31 std::make_shared<lf::uscalfe::FeSpaceLagrangeO1<double>>(mesh_p);
37 Eigen::VectorXd u0(N_dofs);
41 std::cout <<
"N_dofs :" << N_dofs << std::endl;
51 Eigen::Vector2d Himalaya(-280, 29);
52 Eigen::Vector2d Alps(-350, 46);
53 Eigen::Vector2d Karakoram(-285, 36);
54 Eigen::Vector2d Hindukush(-288, 36);
55 Eigen::Vector2d RockyMountains(-109, 44);
56 Eigen::Vector2d Ural(-300, 60);
57 Eigen::Vector2d Andes(-66, -21);
59 auto c = [&Himalaya, &Alps, &Karakoram, &Hindukush, &RockyMountains, &Ural,
60 &Andes](
const Eigen::Vector2d& x) ->
double {
61 double diffCoeff = 86.0;
63 if ((x - Himalaya).norm() <= 3) {
65 std::cout <<
"Take Himalaya into account." << std::endl;
68 if ((x - Karakoram).norm() <= 3) {
70 std::cout <<
"Take Karakoram into account." << std::endl;
73 if ((x - Hindukush).norm() <= 2) {
75 std::cout <<
"Take Hindukush into account." << std::endl;
78 if ((x - Alps).norm() <= 3) {
80 std::cout <<
"Take Alps into account." << std::endl;
83 if ((x - Ural).norm() <= 2) {
85 std::cout <<
"Take Ural into account." << std::endl;
88 if ((x - RockyMountains).norm() <= 2) {
90 std::cout <<
"Take Himalaya into account." << std::endl;
93 if ((x - Andes).norm() <= 3) {
95 std::cout <<
"Take Himalaya into account." << std::endl;
102 double lambda = 1.94;
108 auto boundary_nodes = [&bd_flags, &dofh](
unsigned int idx) ->
bool {
109 return bd_flags(dofh.Entity(idx));
115 return bd_flags_edge(edge);
119 std::vector<Eigen::MatrixXd> locBoundary;
120 for (
int i = 0; i < N_dofs; ++i) {
122 if (boundary_nodes(i)) {
123 locBoundary.push_back(coords);
130 auto h = [fe_space, mesh_p, edge_pred](
const Eigen::Vector2d& x) ->
double {
133 auto g = [&x](
const Eigen::Vector2d& y) ->
double {
134 double tmp_res = 0.0;
135 if (5 <= (x - y).norm() && (x - y).norm() <= 30) {
150 std::cout <<
"res" << res << std::endl;
155 Eigen::MatrixXd L(N_dofs, N_dofs);
156 for (
int j = 0; j < N_dofs; j++) {
157 if (boundary_nodes(j)) {
158 auto L_j = [fe_space, &dofh, N_dofs, edge_pred,
159 j](
const Eigen::Vector2d& x) ->
double {
160 auto g_j = [&x](
const Eigen::Vector2d& y) ->
double {
161 double tmp_res = 0.0;
162 if (5 <= (x - y).norm() && (x - y).norm() <= 30) {
168 Eigen::VectorXd L1(N_dofs);
174 edgeVec_y(fe_space, mf_g, edge_pred);
180 Eigen::VectorXd L2(N_dofs);
186 edgeVec_x(fe_space, mf_L, edge_pred);
193 L.col(j) = Eigen::VectorXd::Zero(N_dofs);
203 unsigned int m = 121;
207 Eigen::MatrixXd car_cap(N_dofs, 22);
209 Eigen::VectorXd K(N_dofs);
211 K = 0.2 * Eigen::VectorXd::Ones(N_dofs);
212 auto c_cap = [](
const Eigen::Vector2d & ) ->
double {
return 80.0; };
213 auto h_cap = [](
const Eigen::Vector2d & ) ->
double {
return 1.0; };
214 Eigen::MatrixXd L_cap(N_dofs, N_dofs);
215 L_cap = Eigen::MatrixXd::Zero(N_dofs, N_dofs);
217 StrangSplit DiffusionCapacity(fe_space, T, m, 0.0, c_cap, h_cap, L_cap);
219 Eigen::VectorXd k0(N_dofs);
224 car_cap.col(0) = DiffusionCapacity.Evolution(K, k0);
225 car_cap.col(1) = DiffusionCapacity.Evolution(K, car_cap.col(0));
226 car_cap.col(2) = DiffusionCapacity.Evolution(K, car_cap.col(1));
227 car_cap.col(2) *= 10;
229 std::cout <<
"Carrying Capacity 200kya - 150kya!" << std::endl;
232 std::cout <<
"Carrying Capacity 150kya - 130kya!" << std::endl;
237 car_cap.col(3) = DiffusionCapacity.Evolution(K, k0);
238 car_cap.col(4) = DiffusionCapacity.Evolution(K, car_cap.col(3));
239 car_cap.col(5) = DiffusionCapacity.Evolution(K, car_cap.col(4));
240 car_cap.col(5) *= 10;
242 std::cout <<
"Carrying Capacity 130kya - 100kya!" << std::endl;
245 std::cout <<
"Carrying Capacity 100kya - 70kya!" << std::endl;
250 car_cap.col(6) = DiffusionCapacity.Evolution(K, k0);
251 car_cap.col(7) = DiffusionCapacity.Evolution(K, car_cap.col(6));
252 car_cap.col(7) *= 15;
254 std::cout <<
"Carrying Capacity 70kya - 65kya!" << std::endl;
261 car_cap.col(8) = DiffusionCapacity.Evolution(K, k0);
262 car_cap.col(9) = DiffusionCapacity.Evolution(K, car_cap.col(8));
265 std::cout <<
"Carrying Capacity 65kya - 50kya!" << std::endl;
270 car_cap.col(10) = DiffusionCapacity.Evolution(K, k0);
271 car_cap.col(10) *= 2;
273 std::cout <<
"Carrying Capacity 50kya - 45kya!" << std::endl;
279 car_cap.col(11) = DiffusionCapacity.Evolution(K, k0);
280 car_cap.col(12) = DiffusionCapacity.Evolution(K, car_cap.col(11));
281 car_cap.col(12) *= 8;
283 std::cout <<
"Carrying Capacity 45kya - 25kya!" << std::endl;
288 car_cap.col(13) = DiffusionCapacity.Evolution(K, k0);
289 car_cap.col(14) = DiffusionCapacity.Evolution(K, car_cap.col(13));
290 car_cap.col(14) *= 25;
292 std::cout <<
"Carrying Capacity 25kya - 15kya!" << std::endl;
298 car_cap.col(15) = DiffusionCapacity.Evolution(K, k0);
299 car_cap.col(15) *= 4;
301 std::cout <<
"Carrying Capacity 15kya - 0kya!" << std::endl;
302 std::cout <<
"Capacity maps are assembled!" << std::endl;
305 StrangSplit StrangSplitter(fe_space, T, m, lambda, c, h, L);
307 Eigen::MatrixXd sol(N_dofs, 40);
308 Eigen::VectorXd cap(N_dofs);
311 cap = car_cap.col(2);
312 sol.col(0) = StrangSplitter.Evolution(cap, u0);
314 std::cout <<
"Solution 200kya - 150kya!" << std::endl;
317 sol.col(1) = StrangSplitter.Evolution(cap, sol.col(0));
319 std::cout <<
"Solution 150kya - 130kya!" << std::endl;
322 cap = cap + car_cap.col(5);
323 sol.col(2) = StrangSplitter.Evolution(cap, sol.col(1));
325 std::cout <<
"Solution 130kya - 100kya!" << std::endl;
328 sol.col(3) = StrangSplitter.Evolution(cap, sol.col(2));
330 std::cout <<
"Solution 100kya - 70kya!" << std::endl;
333 cap = cap + car_cap.col(7);
334 sol.col(4) = StrangSplitter.Evolution(cap, sol.col(3));
335 sol.col(5) = StrangSplitter.Evolution(cap, sol.col(4));
337 std::cout <<
"Solution 70kya - 65kya!" << std::endl;
340 cap = cap + car_cap.col(9);
341 sol.col(6) = StrangSplitter.Evolution(cap, sol.col(5));
342 sol.col(7) = StrangSplitter.Evolution(cap, sol.col(6));
344 std::cout <<
"Solution 65kya - 50kya!" << std::endl;
347 cap = cap + car_cap.col(10);
348 sol.col(8) = StrangSplitter.Evolution(cap, sol.col(7));
350 std::cout <<
"Solution 50kya - 45kya!" << std::endl;
353 cap = cap + car_cap.col(12);
354 sol.col(9) = StrangSplitter.Evolution(cap, sol.col(8));
355 sol.col(10) = StrangSplitter.Evolution(cap, sol.col(9));
356 sol.col(11) = StrangSplitter.Evolution(cap, sol.col(10));
357 sol.col(12) = StrangSplitter.Evolution(cap, sol.col(11));
359 std::cout <<
"Solution 45kya - 25kya!" << std::endl;
362 cap = cap + car_cap.col(14);
363 sol.col(13) = StrangSplitter.Evolution(cap, sol.col(12));
364 sol.col(14) = StrangSplitter.Evolution(cap, sol.col(13));
366 std::cout <<
"Solution 25kya - 15kya!" << std::endl;
369 cap = cap + car_cap.col(15);
370 sol.col(15) = StrangSplitter.Evolution(cap, sol.col(14));
371 sol.col(16) = StrangSplitter.Evolution(cap, sol.col(15));
372 sol.col(17) = StrangSplitter.Evolution(cap, sol.col(16));
373 sol.col(18) = StrangSplitter.Evolution(cap, sol.col(17));
374 sol.col(19) = StrangSplitter.Evolution(cap, sol.col(18));
376 std::cout <<
"Solution 15kya - 0kya!" << std::endl;
380 auto nodal_data_cap =
381 lf::mesh::utils::make_CodimMeshDataSet<double>(mesh_p, 2);
382 for (
int global_idx = 0; global_idx < N_dofs; global_idx++) {
383 nodal_data_cap->operator()(dofh.Entity(global_idx)) = cap[global_idx];
385 vtk_writer_cap.WritePointData(
"cap", *nodal_data_cap);
387 for (
int k = 1; k < 21; k++) {
388 std::stringstream filename;
389 filename <<
"sol" << k <<
".vtk";
392 auto nodal_data = lf::mesh::utils::make_CodimMeshDataSet<double>(mesh_p, 2);
393 for (
int global_idx = 0; global_idx < N_dofs; global_idx++) {
394 nodal_data->operator()(dofh.Entity(global_idx)) =
395 sol.col(k - 1)[global_idx];
398 vtk_writer.WritePointData(
"sol", *nodal_data);
401 for (
int k = 1; k < 17; k++) {
402 std::stringstream filename_cap;
403 filename_cap <<
"cap" << k <<
".vtk";
406 auto nodal_data_caps =
407 lf::mesh::utils::make_CodimMeshDataSet<double>(mesh_p, 2);
408 for (
int global_idx = 0; global_idx < N_dofs; global_idx++) {
409 nodal_data_caps->operator()(dofh.Entity(global_idx)) =
410 car_cap.col(k - 1)[global_idx];
413 vtk_writer_caps.WritePointData(
"caps", *nodal_data_caps);
A general (interface) class for DOF handling, see Lecture Document Paragraph 2.7.4....
static constexpr RefEl kSegment()
Returns the (1-dimensional) reference segment.
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
MeshFunction wrapper for a simple function of physical coordinates.
auto squaredNorm(const A &a)
Pointwise squared norm of another mesh function.
Local edge contributions to element vector.
void AssembleVectorLocally(dim_t codim, const DofHandler &dof_handler, ENTITY_VECTOR_PROVIDER &entity_vector_provider, VECTOR &resultvector)
entity-local assembly of (right-hand-side) vectors from element vectors
QuadRule make_TriaQR_EdgeMidpointRule()
edge midpoint quadrature rule for reference triangles
auto localQuadFunction(const lf::mesh::Mesh &mesh, std::map< lf::base::RefEl, lf::quad::QuadRule > quadrules, FUNCTOR &&f, unsigned int codim, const std::function< bool(const lf::mesh::Entity &)> &pred)
Eigen::MatrixXd Corners(const Geometry &geo)
The corners of a shape with piecewise smooth boundary.
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
QuadRule make_QuadRule(base::RefEl ref_el, unsigned degree)
Returns a QuadRule object for the given Reference Element and Degree.
lf::assemble::size_type size_type