16#include <polysolve/nonlinear/Solver.hpp>
18#include <spdlog/sinks/stdout_color_sinks.h>
19#include <spdlog/sinks/basic_file_sink.h>
20#include <spdlog/sinks/ostream_sink.h>
31 spdlog::level::level_enum,
32 {{spdlog::level::level_enum::trace,
"trace"},
33 {spdlog::level::level_enum::debug,
"debug"},
34 {spdlog::level::level_enum::info,
"info"},
35 {spdlog::level::level_enum::warn,
"warning"},
36 {spdlog::level::level_enum::err,
"error"},
37 {spdlog::level::level_enum::critical,
"critical"},
38 {spdlog::level::level_enum::off,
"off"},
39 {spdlog::level::level_enum::trace, 0},
40 {spdlog::level::level_enum::debug, 1},
41 {spdlog::level::level_enum::info, 2},
42 {spdlog::level::level_enum::warn, 3},
43 {spdlog::level::level_enum::err, 3},
44 {spdlog::level::level_enum::critical, 4},
45 {spdlog::level::level_enum::off, 5}})
60 const std::string &log_file,
61 const spdlog::level::level_enum log_level,
62 const spdlog::level::level_enum file_log_level,
65 std::vector<spdlog::sink_ptr> sinks;
69 console_sink_ = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
73 if (!log_file.empty())
75 file_sink_ = std::make_shared<spdlog::sinks::basic_file_sink_mt>(log_file,
true);
82 spdlog::flush_every(std::chrono::seconds(3));
87 std::vector<spdlog::sink_ptr> sinks;
88 sinks.emplace_back(std::make_shared<spdlog::sinks::ostream_sink_mt>(os,
false));
93 const std::vector<spdlog::sink_ptr> &sinks,
94 const spdlog::level::level_enum log_level)
96 set_adjoint_logger(std::make_shared<spdlog::logger>(
"adjoint-polyfem", sinks.begin(), sinks.end()));
112 json args_in = p_args_in;
117 if (!output_dir.empty())
119 std::filesystem::create_directories(
output_dir);
123 std::string out_path_log = this->
args[
"output"][
"log"][
"path"];
124 if (!out_path_log.empty())
131 this->
args[
"output"][
"log"][
"level"],
132 this->
args[
"output"][
"log"][
"file_level"],
133 this->
args[
"output"][
"log"][
"quiet"]);
137 const int thread_in = this->
args[
"solver"][
"max_threads"];
146 max_threads <= 0 ? std::numeric_limits<unsigned int>::max() : max_threads,
147 args[
"output"][
"log"]);
152 diff_cache = std::make_shared<DiffCache>();
162 for (
int i = 0; i <
states.size(); ++i)
170 "legacy::State {}: transient linear problem is not supported in optimization.", i);
176 if (!state.
args[
"contact"][
"use_gcp_formulation"].get<
bool>()
177 && !state.
args[
"contact"][
"use_convergent_formulation"].get<
bool>())
180 "legacy::State {}: non-convergent contact formulation is not supported in optimization.", i);
184 if (state.
args[
"/solver/contact/barrier_stiffness"_json_pointer].is_string())
187 "legacy::State {}: only constant barrier stiffness is supported in optimization.", i);
192 if (state.
args.contains(
"boundary_conditions") && state.
args[
"boundary_conditions"].contains(
"rhs"))
194 const json &rhs = state.
args[
"boundary_conditions"][
"rhs"];
195 if (rhs.is_string() || (rhs.is_array() && rhs.size() > 0 && rhs[0].is_string()))
198 "legacy::State {}: only constant rhs over space is supported in optimization.", i);
203 for (
const auto &element_bases : state.
geom_bases())
205 for (
const auto &basis : element_bases.bases)
207 if (basis.order() > 1)
210 "legacy::State {}: high-order geometry basis is not supported in optimization.", i);
219 const json ¶meters =
args[
"parameters"];
220 bool is_auto = parameters.is_string() && parameters.get<std::string>() ==
"auto";
226 if (
args[
"variable_to_simulation"].size() != 1)
229 "Auto parameters are only supported with a single variable to simulation.");
234 if (composition[
"type"].get<std::string>() ==
"slice")
252 for (
const auto &arg :
args[
"parameters"])
267 int inv_dof = var2sim->inverse_dof();
271 "VariableToSimulation {} (type {}) expects {} DOF, but parameters define {} DOF.",
272 i, var2sim->name(), inv_dof,
ndof);
284 std::vector<std::shared_ptr<solver::AdjointForm>> stopping_conditions;
285 for (
const auto &arg :
args[
"stopping_conditions"])
286 stopping_conditions.push_back(
289 nl_problem = std::make_unique<solver::AdjointNLProblem>(
309 args[
"solver"][
"nonlinear"],
310 args[
"solver"][
"linear"],
311 args[
"solver"][
"advanced"][
"characteristic_length"]);
void solve(Eigen::VectorXd &x)
void initial_guess(Eigen::VectorXd &x)
void set_log_level(const spdlog::level::level_enum log_level)
change log level
void create_states(const int max_threads=-1)
create the opt states
json args
main input arguments containing all defaults
void init(const json &args, const bool strict_validation)
initialize the polyfem solver with a json settings
std::vector< std::shared_ptr< DiffCache > > diff_caches
spdlog::sink_ptr file_sink_
std::string root_path() const
void check_unsupported() const
Check and throw if any forward simulation legacy::State is not supported.
double eval(Eigen::VectorXd &x) const
std::vector< int > variable_sizes
variables
std::unique_ptr< solver::AdjointNLProblem > nl_problem
std::string output_dir
Directory for output files.
std::vector< std::shared_ptr< legacy::State > > states
legacy::State used in the opt
spdlog::sink_ptr console_sink_
logger sink to stdout
void init_logger(const std::string &log_file, const spdlog::level::level_enum log_level, const spdlog::level::level_enum file_log_level, const bool is_quiet)
initializing the logger
solver::VariableToSimulationGroup variable_to_simulations
void init_variables()
init variables
main class that contains the polyfem solver and all its state
std::shared_ptr< assembler::Problem > problem
current problem, it contains rhs and bc
const std::vector< basis::ElementBases > & geom_bases() const
Get a constant reference to the geometry mapping bases.
json args
main input arguments containing all defaults
bool is_problem_linear() const
Returns whether the system is linear. Collisions and pressure add nonlinearity to the problem.
bool is_contact_enabled() const
does the simulation have contact
void update(const Eigen::VectorXd &x)
std::vector< std::shared_ptr< VariableToSimulation > > data
void set_logger(spdlog::logger &logger)
static GeogramUtils & instance()
void set_num_threads(const int max_threads)
std::vector< std::shared_ptr< legacy::State > > build_states(const std::string &root_path, const json &args, const size_t max_threads, const json &output_log)
solver::VariableToSimulationGroup build_variable_to_simulation_group(const json &args, const std::vector< std::shared_ptr< legacy::State > > &states, const std::vector< std::shared_ptr< DiffCache > > &diff_caches, const std::vector< int > &variable_sizes)
std::shared_ptr< solver::AdjointForm > build_form(const json &args, const solver::VariableToSimulationGroup &var2sim, const std::vector< std::shared_ptr< legacy::State > > &states, const std::vector< std::shared_ptr< DiffCache > > &diff_caches)
NLOHMANN_JSON_SERIALIZE_ENUM(CollisionProxyTessellation, {{CollisionProxyTessellation::REGULAR, "regular"}, {CollisionProxyTessellation::IRREGULAR, "irregular"}})
std::string resolve_path(const std::string &path, const std::string &input_file_path, const bool only_if_exists=false)
std::vector< T > json_as_array(const json &j)
Return the value of a json object as an array.
spdlog::logger & adjoint_logger()
Retrieves the current logger for adjoint.
void set_adjoint_logger(std::shared_ptr< spdlog::logger > p_logger)
Setup a logger object to be used by adjoint Polyfem.
void log_and_throw_adjoint_error(const std::string &msg)
static int compute_variable_size(const json &args, const std::vector< std::shared_ptr< legacy::State > > &states)
static std::shared_ptr< polysolve::nonlinear::Solver > make_nl_solver(const json &solver_params, const json &linear_solver_params, const double characteristic_length)
static json apply_opt_json_spec(const json &input_args, bool strict_validation)
static Eigen::VectorXd inverse_evaluation(const json &args, const int ndof, const std::vector< int > &variable_sizes, VariableToSimulationGroup &var2sim)