12#include <polysolve/linear/FEMSolver.hpp>
16#include <unsupported/Eigen/SparseExtra>
22 using namespace time_integrator;
23 using namespace utils;
24 using namespace solver;
31 logger().info(
"Assembling stiffness mat...");
37 StiffnessMatrix velocity_stiffness, mixed_stiffness, pressure_stiffness;
42 const int problem_dim =
problem->is_scalar() ? 1 :
mesh->dimension();
45 velocity_stiffness, mixed_stiffness, pressure_stiffness,
59 stats.
mat_size = (
long long)stiffness.rows() * (
long long)stiffness.cols();
62 const std::string full_mat_path =
args[
"output"][
"data"][
"full_mat"];
63 if (!full_mat_path.empty())
65 Eigen::saveMarket(stiffness, full_mat_path);
70 const std::unique_ptr<polysolve::linear::Solver> &solver,
73 const bool compute_spectrum,
74 Eigen::MatrixXd &sol, Eigen::MatrixXd &pressure)
79 const int problem_dim =
problem->is_scalar() ? 1 :
mesh->dimension();
80 const int full_size = A.rows();
81 int precond_num = problem_dim *
n_bases;
83 std::vector<int> boundary_nodes_tmp;
88 Eigen::MatrixXd tmp =
periodic_bc->full_to_periodic(b,
true);
98 prefactorize(*solver, A, boundary_nodes_tmp, precond_num,
args[
"output"][
"data"][
"stiffness_mat"]);
99 dirichlet_solve_prefactorized(*solver, A_tmp, b, boundary_nodes_tmp,
x);
104 *solver, A, b, boundary_nodes_tmp,
x, precond_num,
args[
"output"][
"data"][
"stiffness_mat"], compute_spectrum,
110 if (
args[
"/boundary_conditions/periodic_boundary/force_zero_mean"_json_pointer].get<bool>())
114 for (
int d = 0; d < problem_dim; d++)
115 sol(Eigen::seqN(d,
n_bases, problem_dim), 0).array() -= integral(d) / area;
123 const auto error = (A *
x - b).norm();
126 logger().error(
"Solver error: {}", error);
128 logger().debug(
"Solver error: {}", error);
136 assert(!
problem->is_time_dependent());
144 polysolve::linear::Solver::create(
args[
"solver"][
"linear"],
logger());
156 Eigen::VectorXd b =
rhs;
165 assert(sol.cols() == 1);
176 t,
problem->is_time_dependent() ?
args[
"time"][
"dt"].get<
double>() : 0.0,
184 false,
problem->is_time_dependent());
189 if (
problem->is_time_dependent())
204 Eigen::MatrixXd solution, velocity, acceleration;
206 solution.col(0) = sol;
207 assert(solution.rows() == sol.size());
209 assert(velocity.rows() == sol.size());
211 assert(acceleration.rows() == sol.size());
213 const double dt =
args[
"time"][
"dt"];
221 assert(sol.cols() == 1);
222 assert(
problem->is_time_dependent());
231 polysolve::linear::Solver::create(
args[
"solver"][
"linear"],
logger());
232 logger().info(
"{}...", solver->name());
236 std::shared_ptr<ImplicitTimeIntegrator> time_integrator;
237 if (is_scalar_or_mixed)
239 time_integrator = std::make_shared<BDF>();
240 time_integrator->set_parameters(
args[
"time"]);
241 time_integrator->init(sol, Eigen::VectorXd::Zero(sol.size()), Eigen::VectorXd::Zero(sol.size()), dt);
245 Eigen::MatrixXd solution, velocity, acceleration;
247 solution.col(0) = sol;
248 assert(solution.rows() == sol.size());
250 assert(velocity.rows() == sol.size());
252 assert(acceleration.rows() == sol.size());
255 time_integrator->init(solution, velocity, acceleration, dt);
268 Eigen::MatrixXd current_rhs =
rhs;
275 for (
int t = 1; t <= time_steps; ++t)
277 const double time = t0 + t * dt;
281 bool compute_spectrum =
args[
"output"][
"advanced"][
"spectrum"];
283 if (is_scalar_or_mixed)
303 std::shared_ptr<BDF> bdf = std::dynamic_pointer_cast<BDF>(time_integrator);
304 A =
mass / bdf->beta_dt() + stiffness;
305 b = (
mass * bdf->weighted_sum_x_prevs()) / bdf->beta_dt();
310 compute_spectrum &= t == time_steps;
319 std::vector<LocalBoundary>(), std::vector<int>(), n_b_samples,
local_neumann_boundary, current_rhs, sol, time);
321 current_rhs *= time_integrator->acceleration_scaling();
322 current_rhs +=
mass * time_integrator->x_tilde();
327 A = stiffness * time_integrator->acceleration_scaling() +
mass;
330 compute_spectrum &= t == 1;
333 solve_linear(solver, A, b, compute_spectrum, sol, pressure);
341 time_integrator->update_quantities(sol);
346 if (!state_path.empty())
347 time_integrator->save_state(state_path);
349 logger().info(
"{}/{} t={}", t, time_steps, time);
#define POLYFEM_SCOPED_TIMER(...)
io::OutRuntimeData timings
runtime statistics
std::shared_ptr< utils::PeriodicBoundary > periodic_bc
periodic BC and periodic mesh utils
int n_bases
number of bases
void cache_transient_adjoint_quantities(const int current_step, const Eigen::MatrixXd &sol, const Eigen::MatrixXd &disp_grad)
int n_pressure_bases
number of pressure bases
assembler::AssemblyValsCache ass_vals_cache
used to store assembly values for small problems
int n_boundary_samples() const
quadrature used for projecting boundary conditions
const std::vector< basis::ElementBases > & geom_bases() const
Get a constant reference to the geometry mapping bases.
void sol_to_pressure(Eigen::MatrixXd &sol, Eigen::MatrixXd &pressure)
splits the solution in solution and pressure for mixed problems
std::shared_ptr< assembler::Assembler > assembler
assemblers
bool use_avg_pressure
use average pressure for stokes problem to fix the additional dofs, true by default if false,...
std::string resolve_output_path(const std::string &path) const
Resolve output path relative to output_dir if the path is not absolute.
solver::CacheLevel optimization_enabled
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< basis::ElementBases > pressure_bases
FE pressure bases for mixed elements, the size is #elements.
void initial_solution(Eigen::MatrixXd &solution) const
Load or compute the initial solution.
std::shared_ptr< assembler::Assembler > pressure_assembler
std::shared_ptr< assembler::Mass > mass_matrix_assembler
std::unique_ptr< mesh::Mesh > mesh
current mesh, it can be a Mesh2D or Mesh3D
StiffnessMatrix mass
Mass matrix, it is computed only for time dependent problems.
bool has_periodic_bc() const
std::shared_ptr< assembler::Problem > problem
current problem, it contains rhs and bc
json args
main input arguments containing all defaults
void initial_velocity(Eigen::MatrixXd &velocity) const
Load or compute the initial velocity.
io::OutStatsData stats
Other statistics.
void initial_acceleration(Eigen::MatrixXd &acceleration) const
Load or compute the initial acceleration.
std::vector< basis::ElementBases > bases
FE bases, the size is #elements.
assembler::AssemblyValsCache pressure_ass_vals_cache
used to store assembly values for pressure for small problems
void build_stiffness_mat(StiffnessMatrix &stiffness)
utility that builds the stiffness matrix and collects stats, used only for linear problems
std::vector< mesh::LocalBoundary > local_boundary
mapping from elements to nodes for dirichlet boundary conditions
void init_linear_solve(Eigen::MatrixXd &sol, const double t=1.0)
initialize the linear solve
std::vector< int > boundary_nodes
list of boundary nodes
solver::SolveData solve_data
timedependent stuff cached
std::unique_ptr< polysolve::linear::Solver > lin_solver_cached
void solve_linear(Eigen::MatrixXd &sol, Eigen::MatrixXd &pressure)
solves a linear problem
bool is_contact_enabled() const
does the simulation has contact
std::vector< mesh::LocalBoundary > local_neumann_boundary
mapping from elements to nodes for neumann boundary conditions
void solve_transient_linear(const int time_steps, const double t0, const double dt, Eigen::MatrixXd &sol, Eigen::MatrixXd &pressure)
solves transient linear problem
std::shared_ptr< assembler::MixedAssembler > mixed_assembler
Eigen::MatrixXd rhs
System right-hand side.
static void merge_mixed_matrices(const int n_bases, const int n_pressure_bases, const int problem_dim, const bool add_average, const StiffnessMatrix &velocity_stiffness, const StiffnessMatrix &mixed_stiffness, const StiffnessMatrix &pressure_stiffness, StiffnessMatrix &stiffness)
utility to merge 3 blocks of mixed matrices, A=velocity_stiffness, B=mixed_stiffness,...
static Eigen::VectorXd integrate_function(const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const Eigen::MatrixXd &fun, const int dim, const int actual_dim)
double assembling_stiffness_mat_time
time to assembly
json solver_info
information of the solver, eg num iteration, time, errors, etc the informations varies depending on t...
Eigen::Vector4d spectrum
spectrum of the stiffness matrix, enable only if POLYSOLVE_WITH_SPECTRA is ON (off by default)
long long nn_zero
non zeros and sytem matrix size num dof is the total dof in the system
std::shared_ptr< solver::FrictionForm > friction_form
std::shared_ptr< solver::InertiaForm > inertia_form
void update_dt()
updates the dt inside the different forms
std::shared_ptr< solver::BodyForm > body_form
std::shared_ptr< solver::ContactForm > contact_form
std::shared_ptr< solver::ElasticForm > damping_form
std::shared_ptr< solver::ElasticForm > elastic_form
std::shared_ptr< time_integrator::ImplicitTimeIntegrator > time_integrator
std::shared_ptr< assembler::RhsAssembler > rhs_assembler
static std::shared_ptr< ImplicitTimeIntegrator > construct_time_integrator(const json ¶ms)
Factory method for constructing implicit time integrators from the name of the integrator.
spdlog::logger & logger()
Retrieves the current logger.
void log_and_throw_adjoint_error(const std::string &msg)
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix