PolyFEM
Loading...
Searching...
No Matches
StateSolveOperatorSplitting.cpp
Go to the documentation of this file.
2
11
12#include <Eigen/Core>
13
14#include <cassert>
15#include <vector>
16
17namespace polyfem::legacy
18{
20 const int time_steps,
21 const double dt,
22 Eigen::MatrixXd &sol,
23 Eigen::MatrixXd &pressure,
24 UserPostStepCallback user_post_step)
25 {
26 assert(assembler->name() == "OperatorSplitting" && problem->is_time_dependent());
27
28 Eigen::MatrixXd local_pts;
29 auto &gbases = geom_bases();
30 if (mesh->dimension() == 2)
31 {
32 if (gbases[0].bases.size() == 3)
33 autogen::p_nodes_2d(args["space"]["discr_order"], local_pts);
34 else
35 autogen::q_nodes_2d(args["space"]["discr_order"], local_pts);
36 }
37 else
38 {
39 if (gbases[0].bases.size() == 4)
40 autogen::p_nodes_3d(args["space"]["discr_order"], local_pts);
41 else
42 autogen::q_nodes_3d(args["space"]["discr_order"], local_pts);
43 }
44
45 std::vector<int> bnd_nodes;
46 bnd_nodes.reserve(boundary_nodes.size() / mesh->dimension());
47 for (const int node : boundary_nodes)
48 {
49 if (node % mesh->dimension() == 0)
50 continue;
51 bnd_nodes.push_back(node / mesh->dimension());
52 }
53
54 const int n_el = int(bases.size());
55 const int shape = gbases[0].bases.size();
56 auto fluid_assembler = std::dynamic_pointer_cast<assembler::OperatorSplitting>(assembler);
57 if (!fluid_assembler)
58 log_and_throw_error("Invalid assembler {}!", assembler->name());
59 const double viscosity = fluid_assembler->viscosity()(0, 0, 0, 0, 0);
60 assert(viscosity >= 0);
61
62 logger().info("Matrices assembly...");
63 StiffnessMatrix stiffness_viscosity, mixed_stiffness, velocity_mass, stiffness;
64 build_stiffness_mat(stiffness);
65
66 assembler::Laplacian laplacian;
67 laplacian.set_size(1);
68 laplacian.assemble(mesh->is_volume(), n_bases, bases, gbases, ass_vals_cache, 0, stiffness_viscosity);
69 mass_matrix_assembler->set_size(1);
70 mass_matrix_assembler->assemble(mesh->is_volume(), n_bases, bases, gbases, mass_ass_vals_cache, 0, mass, true);
71 laplacian.assemble(mesh->is_volume(), n_pressure_bases, pressure_bases, gbases, pressure_ass_vals_cache, 0, stiffness);
72
73 mixed_assembler->assemble(
74 mesh->is_volume(), n_pressure_bases, n_bases,
75 pressure_bases, bases, gbases,
76 pressure_ass_vals_cache, ass_vals_cache, 0, mixed_stiffness);
77 mass_matrix_assembler->set_size(mesh->dimension());
78 mass_matrix_assembler->assemble(mesh->is_volume(), n_bases, bases, gbases, mass_ass_vals_cache, 0, velocity_mass, true);
79 mixed_stiffness = mixed_stiffness.transpose();
80 logger().info("Matrices assembly ends!");
81
82 solver::OperatorSplittingSolver splitting_solver(
83 *mesh, shape, n_el, local_boundary, boundary_nodes,
84 pressure_boundary_nodes, bnd_nodes, mass,
85 stiffness_viscosity, stiffness, velocity_mass,
86 dt, viscosity, args["solver"]["linear"]);
87
88 pressure = Eigen::MatrixXd::Zero(n_pressure_bases, 1);
89 if (user_post_step)
90 user_post_step(0, *this, sol, nullptr, &pressure);
91
92 const QuadratureOrders &boundary_samples = n_boundary_samples();
93 for (int step = 1; step <= time_steps; ++step)
94 {
95 const double time = step * dt;
96 logger().info("{}/{} steps, t={}s", step, time_steps, time);
97
98 if (args["space"]["advanced"]["use_particle_advection"])
99 splitting_solver.advection_FLIP(*mesh, gbases, bases, sol, dt, local_pts);
100 else
101 splitting_solver.advection(*mesh, gbases, bases, sol, dt, local_pts);
102
104 local_boundary, boundary_nodes, boundary_samples,
105 local_neumann_boundary, sol, Eigen::MatrixXd(), time);
106
107 if (viscosity > 0)
108 splitting_solver.solve_diffusion_1st(mass, bnd_nodes, sol);
109 splitting_solver.external_force(
110 *mesh, *assembler, gbases, bases, dt, sol, local_pts, problem, time);
111 splitting_solver.solve_pressure(mixed_stiffness, pressure_boundary_nodes, sol, pressure);
112 splitting_solver.projection(
113 n_bases, gbases, bases, pressure_bases, local_pts, pressure, sol);
114 pressure /= dt;
115
117 local_boundary, boundary_nodes, boundary_samples,
118 local_neumann_boundary, sol, Eigen::MatrixXd(), time);
119
120 save_timestep(time, step, 0, dt, sol, pressure);
121 if (user_post_step)
122 user_post_step(step, *this, sol, nullptr, &pressure);
123 }
124 }
125} // namespace polyfem::legacy
virtual void set_size(const int size)
Definition Assembler.hpp:66
Eigen::Matrix< double, Eigen::Dynamic, 1, 0, 9, 1 > assemble(const LinearAssemblerData &data) const override
computes local stiffness matrix (1x1) for bases i,j where i,j is passed in through data ie integral o...
Definition Laplacian.cpp:62
std::shared_ptr< assembler::Problem > problem
current problem, it contains rhs and bc
Definition State.hpp:204
const std::vector< basis::ElementBases > & geom_bases() const
Get a constant reference to the geometry mapping bases.
Definition State.hpp:264
StiffnessMatrix mass
Mass matrix, it is computed only for time dependent problems.
Definition State.hpp:239
std::vector< mesh::LocalBoundary > local_boundary
mapping from elements to nodes for dirichlet boundary conditions
Definition State.hpp:541
std::shared_ptr< assembler::Mass > mass_matrix_assembler
Definition State.hpp:192
std::vector< int > pressure_boundary_nodes
list of neumann boundary nodes
Definition State.hpp:537
std::unique_ptr< mesh::Mesh > mesh
current mesh, it can be a Mesh2D or Mesh3D
Definition State.hpp:574
json args
main input arguments containing all defaults
Definition State.hpp:136
void solve_transient_navier_stokes_split(const int time_steps, const double dt, Eigen::MatrixXd &sol, Eigen::MatrixXd &pressure, UserPostStepCallback user_post_step={})
solves transient navier stokes with operator splitting
int n_pressure_bases
number of pressure bases
Definition State.hpp:216
assembler::AssemblyValsCache pressure_ass_vals_cache
used to store assembly values for pressure for small problems
Definition State.hpp:236
int n_bases
number of bases
Definition State.hpp:214
void build_stiffness_mat(StiffnessMatrix &stiffness)
utility that builds the stiffness matrix and collects stats, used only for linear problems
std::vector< basis::ElementBases > pressure_bases
FE pressure bases for mixed elements, the size is #elements.
Definition State.hpp:209
assembler::AssemblyValsCache ass_vals_cache
used to store assembly values for small problems
Definition State.hpp:232
assembler::AssemblyValsCache mass_ass_vals_cache
Definition State.hpp:233
QuadratureOrders n_boundary_samples() const
quadrature used for projecting boundary conditions
Definition State.hpp:304
std::shared_ptr< assembler::Assembler > assembler
assemblers
Definition State.hpp:190
std::vector< basis::ElementBases > bases
FE bases, the size is #elements.
Definition State.hpp:207
void save_timestep(const double time, const int t, const double t0, const double dt, const Eigen::MatrixXd &sol, const Eigen::MatrixXd &pressure)
saves a timestep
std::vector< mesh::LocalBoundary > local_neumann_boundary
mapping from elements to nodes for neumann boundary conditions
Definition State.hpp:543
std::vector< int > boundary_nodes
list of boundary nodes
Definition State.hpp:535
solver::SolveData solve_data
timedependent stuff cached
Definition State.hpp:382
std::shared_ptr< assembler::MixedAssembler > mixed_assembler
Definition State.hpp:195
void solve_pressure(const StiffnessMatrix &mixed_stiffness, const std::vector< int > &pressure_boundary_nodes, Eigen::MatrixXd &sol, Eigen::MatrixXd &pressure)
void projection(const StiffnessMatrix &velocity_mass, const StiffnessMatrix &mixed_stiffness, const std::vector< int > &boundary_nodes_, Eigen::MatrixXd &sol, const Eigen::MatrixXd &pressure)
void external_force(const mesh::Mesh &mesh, const assembler::Assembler &assembler, const std::vector< basis::ElementBases > &gbases, const std::vector< basis::ElementBases > &bases, const double dt, Eigen::MatrixXd &sol, const Eigen::MatrixXd &local_pts, const std::shared_ptr< assembler::Problem > problem, const double time)
void advection(const mesh::Mesh &mesh, const std::vector< basis::ElementBases > &gbases, const std::vector< basis::ElementBases > &bases, Eigen::MatrixXd &sol, const double dt, const Eigen::MatrixXd &local_pts, const int order=1, const int RK=1)
void advection_FLIP(const mesh::Mesh &mesh, const std::vector< basis::ElementBases > &gbases, const std::vector< basis::ElementBases > &bases, Eigen::MatrixXd &sol, const double dt, const Eigen::MatrixXd &local_pts, const int order=1)
void solve_diffusion_1st(const StiffnessMatrix &mass, const std::vector< int > &bnd_nodes, Eigen::MatrixXd &sol)
std::shared_ptr< assembler::RhsAssembler > rhs_assembler
void q_nodes_2d(const int q, Eigen::MatrixXd &val)
void p_nodes_2d(const int p, Eigen::MatrixXd &val)
void p_nodes_3d(const int p, Eigen::MatrixXd &val)
void q_nodes_3d(const int q, Eigen::MatrixXd &val)
std::function< void(int step, State &state, const Eigen::MatrixXd &sol, const Eigen::MatrixXd *disp_grad, const Eigen::MatrixXd *pressure)> UserPostStepCallback
User callback at the end of every solver step.
Definition State.hpp:87
spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:44
std::array< int, 2 > QuadratureOrders
Definition Types.hpp:19
void log_and_throw_error(const std::string &msg)
Definition Logger.cpp:73
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
Definition Types.hpp:24