PolyFEM
Loading...
Searching...
No Matches
TransientForm.cpp
Go to the documentation of this file.
2
5
6#include <Eigen/Core>
7
8#include <cassert>
9#include <vector>
10
11namespace polyfem::solver
12{
14 {
15 std::vector<double> weights;
16 weights.assign(time_steps_ + 1, dt_);
17 if (transient_integral_type_ == "uniform")
18 {
19 weights[0] = 0;
20 }
21 else if (transient_integral_type_ == "trapezoidal")
22 {
23 weights[0] = dt_ / 2.;
24 weights[weights.size() - 1] = dt_ / 2.;
25 }
26 else if (transient_integral_type_ == "simpson")
27 {
28 weights[0] = dt_ / 3.;
29 weights[weights.size() - 1] = dt_ / 3.;
30 for (int i = 1; i < weights.size() - 1; i++)
31 {
32 if (i % 2)
33 weights[i] = dt_ * 4. / 3.;
34 else
35 weights[i] = dt_ * 2. / 4.;
36 }
37 }
38 else if (transient_integral_type_ == "final")
39 {
40 weights.assign(time_steps_ + 1, 0);
42 }
43 else if (transient_integral_type_ == "steps")
44 {
45 weights.assign(time_steps_ + 1, 0);
46 for (const int step : steps_)
47 {
48 assert(step > 0 && step < weights.size());
49 weights[step] += 1. / steps_.size();
50 }
51 }
52 else
53 assert(false);
54
55 return weights;
56 }
57
58 double TransientForm::value_unweighted(const Eigen::VectorXd &x) const
59 {
60 std::vector<double> weights = get_transient_quadrature_weights();
61
62 double value = 0;
63 for (int i = 0; i < time_steps_ + 1; i++)
64 {
65 if (weights[i] == 0)
66 continue;
67 const double tmp = obj_->value_unweighted_step(i, x);
68 value += (weights[i] * obj_->weight()) * tmp;
69 }
70
71 return value;
72 }
73 Eigen::MatrixXd TransientForm::compute_adjoint_rhs(const Eigen::VectorXd &x, const varform::DifferentiableVarForm &varform, const DiffCache &diff_cache) const
74 {
75 Eigen::MatrixXd terms;
76 terms.setZero(varform.primary_space().ndof(), time_steps_ + 1);
77 std::vector<double> weights = get_transient_quadrature_weights();
78
79 for (int i = 0; i < time_steps_ + 1; i++)
80 {
81 if (weights[i] == 0)
82 continue;
83 terms.col(i) = weights[i] * obj_->compute_adjoint_rhs_step(i, x, varform, diff_cache);
84 if (obj_->depends_on_step_prev() && i > 0)
85 terms.col(i - 1) = weights[i] * obj_->compute_adjoint_rhs_step_prev(i, x, varform, diff_cache);
86 }
87
88 return terms * weight();
89 }
90 void TransientForm::compute_partial_gradient(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
91 {
92 gradv.setZero(x.size());
93 std::vector<double> weights = get_transient_quadrature_weights();
94
95 Eigen::VectorXd tmp;
96 for (int i = 0; i < time_steps_ + 1; i++)
97 {
98 if (weights[i] == 0)
99 continue;
100 obj_->compute_partial_gradient_step(i, x, tmp);
101 gradv += weights[i] * tmp;
102 }
103
104 gradv *= weight();
105 }
106
107 void TransientForm::init(const Eigen::VectorXd &x)
108 {
109 obj_->init(x);
110 }
111
112 bool TransientForm::is_step_valid(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) const
113 {
114 return obj_->is_step_valid(x0, x1);
115 }
116
117 double TransientForm::max_step_size(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) const
118 {
119 return obj_->max_step_size(x0, x1);
120 }
121
122 void TransientForm::line_search_begin(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1)
123 {
124 obj_->line_search_begin(x0, x1);
125 }
126
128 {
129 obj_->line_search_end();
130 }
131
132 void TransientForm::post_step(const polysolve::nonlinear::PostStepData &data)
133 {
134 obj_->post_step(data);
135 }
136
137 void TransientForm::solution_changed(const Eigen::VectorXd &new_x)
138 {
140 // obj_->solution_changed(new_x);
141 std::vector<double> weights = get_transient_quadrature_weights();
142 for (int i = 0; i <= time_steps_; i++)
143 {
144 if (weights[i] == 0)
145 continue;
146 obj_->solution_changed_step(i, new_x);
147 }
148 }
149 bool TransientForm::is_step_collision_free(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) const
150 {
151 return obj_->is_step_collision_free(x0, x1);
152 }
153
154 double ProxyTransientForm::value_unweighted(const Eigen::VectorXd &x) const
155 {
156 Eigen::VectorXd vals(steps_.size());
157 int j = 0;
158 for (int i : steps_)
159 {
160 vals(j++) = obj_->value_unweighted_step(i, x);
161 }
162
163 return eval(vals);
164 }
165 Eigen::MatrixXd ProxyTransientForm::compute_adjoint_rhs(const Eigen::VectorXd &x, const varform::DifferentiableVarForm &varform, const DiffCache &diff_cache) const
166 {
167 Eigen::VectorXd vals(steps_.size());
168 Eigen::MatrixXd terms;
169 terms.setZero(varform.primary_space().ndof(), steps_.size());
170
171 int j = 0;
172 for (int i : steps_)
173 {
174 vals(j) = obj_->value_unweighted_step(i, x);
175 terms.col(j++) = obj_->compute_adjoint_rhs_step(i, x, varform, diff_cache);
176 }
177
178 const Eigen::VectorXd g = eval_grad(vals);
179 Eigen::MatrixXd out;
180 out.setZero(varform.primary_space().ndof(), time_steps_ + 1);
181 j = 0;
182 for (int i : steps_)
183 {
184 out.col(i) = terms.col(j) * (g(j) * weight());
185 j++;
186 }
187
188 return out;
189 }
190 void ProxyTransientForm::compute_partial_gradient(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
191 {
192 Eigen::VectorXd vals(steps_.size());
193 Eigen::MatrixXd terms;
194 terms.setZero(x.size(), steps_.size());
195
196 int j = 0;
197 Eigen::VectorXd tmp;
198 for (int i : steps_)
199 {
200 vals(j) = obj_->value_unweighted_step(i, x);
201 obj_->compute_partial_gradient_step(i, x, tmp);
202 terms.col(j++) = tmp;
203 }
204
205 gradv = terms * eval_grad(vals) * weight();
206 }
207
208 double ProxyTransientForm::eval(const Eigen::VectorXd &y) const
209 {
210 return 1. / y.array().inverse().sum();
211 }
212
213 Eigen::VectorXd ProxyTransientForm::eval_grad(const Eigen::VectorXd &y) const
214 {
215 return y.array().pow(-2.0) * pow(eval(y), 2);
216 }
217} // namespace polyfem::solver
ElementAssemblyValues vals
Definition Assembler.cpp:26
std::vector< std::pair< int, double > > weights
int y
int x
Storage for additional data required by differntial code.
Definition DiffCache.hpp:22
virtual void solution_changed(const Eigen::VectorXd &new_x) override
Update cached fields upon a change in the solution.
double value(const Eigen::VectorXd &x) const override
Compute the value of the form multiplied with the weigth.
virtual double weight() const
Get the form's multiplicative constant weight.
Definition Form.hpp:128
Eigen::VectorXd eval_grad(const Eigen::VectorXd &y) const
Eigen::MatrixXd compute_adjoint_rhs(const Eigen::VectorXd &x, const varform::DifferentiableVarForm &varform, const DiffCache &diff_cache) const override
double eval(const Eigen::VectorXd &y) const
void compute_partial_gradient(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const override
double value_unweighted(const Eigen::VectorXd &x) const override
Compute the value of the form.
virtual double value_unweighted(const Eigen::VectorXd &x) const override
Compute the value of the form.
void solution_changed(const Eigen::VectorXd &new_x) override
Update cached fields upon a change in the solution.
double max_step_size(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) const override
Determine the maximum step size allowable between the current and next solution.
bool is_step_collision_free(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) const override
Checks if the step is collision free.
virtual void compute_partial_gradient(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const override
bool is_step_valid(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) const override
Determine if a step from solution x0 to solution x1 is allowed.
virtual Eigen::MatrixXd compute_adjoint_rhs(const Eigen::VectorXd &x, const varform::DifferentiableVarForm &varform, const DiffCache &diff_cache) const override
std::shared_ptr< StaticForm > obj_
void init(const Eigen::VectorXd &x) override
Initialize the form.
void line_search_begin(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) override
Initialize variables used during the line search.
std::vector< double > get_transient_quadrature_weights() const
void line_search_end() override
Clear variables used during the line search.
void post_step(const polysolve::nonlinear::PostStepData &data) override
Update fields after a step in the optimization.
Optimization-facing interface implemented by differentiated VarForm adapters.
virtual const FESpace & primary_space() const =0