119 assert(
x.size() ==
size_);
122 gradv = Eigen::VectorXd::Zero(
size_);
125 if (!term.form->enabled())
128 Eigen::VectorXd local_grad;
129 term.form->first_derivative(
gather(
x, term), local_grad);
130 assert(local_grad.size() ==
blocks_[term.block].size());
132 for (
int i = 0; i < local_grad.size(); ++i)
139 assert(
x.size() ==
size_);
142 using StorageIndex =
typename StiffnessMatrix::StorageIndex;
143 std::vector<Eigen::Triplet<double, StorageIndex>>
entries;
147 if (!term.form->enabled())
151 term.form->second_derivative(
gather(
x, term), local_hessian);
152 const int local_size =
blocks_[term.block].size();
153 assert(local_hessian.rows() == local_size);
154 assert(local_hessian.cols() == local_size);
156 for (
int k = 0; k < local_hessian.outerSize(); ++k)
158 for (StiffnessMatrix::InnerIterator it(local_hessian, k); it; ++it)
196 int constraint_rows = 0;
200 assert(term.form->constraint_matrix().cols() ==
blocks_[term.block].size());
201 assert(term.form->constraint_value().rows() == term.form->constraint_matrix().rows());
202 constraint_rows += term.form->constraint_matrix().rows();
205 std::vector<Eigen::Triplet<double>> constraint_entries;
206 int constraint_offset = 0;
207 b_.resize(constraint_rows, 1);
213 for (
int k = 0; k < local_A.outerSize(); ++k)
215 for (StiffnessMatrix::InnerIterator it(local_A, k); it; ++it)
217 constraint_entries.emplace_back(
218 constraint_offset +
int(it.row()),
219 block.
offset() + int(it.col()),
224 b_.middleRows(constraint_offset, local_A.rows()) = term.form->constraint_value();
225 constraint_offset += local_A.rows();
228 A_.resize(constraint_rows,
size_);
229 A_.setFromTriplets(constraint_entries.begin(), constraint_entries.end());
232 std::vector<int> term_for_block(
blocks_.size(), -1);
234 for (
int i = 0; i < int(
terms_.size()); ++i)
237 if (term_for_block[term.
block] >= 0 || !term.
form->has_projection())
242 term_for_block[term.
block] = i;
252 int reduced_size = 0;
253 for (
int i = 0; i < int(
blocks_.size()); ++i)
255 if (term_for_block[i] >= 0)
256 reduced_size +=
terms_[term_for_block[i]].
form->constraint_projection_matrix().cols();
258 reduced_size +=
blocks_[i].size();
261 std::vector<Eigen::Triplet<double>> projection_entries;
263 int reduced_offset = 0;
264 for (
int i = 0; i < int(
blocks_.size()); ++i)
267 const int term_id = term_for_block[i];
271 for (
int j = 0; j < block.
size(); ++j)
272 projection_entries.emplace_back(block.
offset() + j, reduced_offset + j, 1.0);
273 reduced_offset += block.
size();
277 const auto &form =
terms_[term_id].form;
278 const StiffnessMatrix &local_projection = form->constraint_projection_matrix();
279 const Eigen::MatrixXd &local_projection_value = form->constraint_projection_vector();
280 assert(local_projection.rows() == block.
size());
281 assert(local_projection_value.rows() == block.
size());
283 for (
int k = 0; k < local_projection.outerSize(); ++k)
285 for (StiffnessMatrix::InnerIterator it(local_projection, k); it; ++it)
287 projection_entries.emplace_back(
288 block.
offset() +
int(it.row()),
289 reduced_offset +
int(it.col()),
295 reduced_offset += local_projection.cols();
299 A_proj_.setFromTriplets(projection_entries.begin(), projection_entries.end());