17 class LocalThreadVecStorage
24 LocalThreadVecStorage(
const int size)
31 double dot(
const Eigen::MatrixXd &A,
const Eigen::MatrixXd &B) {
return (A.array() * B.array()).sum(); }
35 const std::vector<basis::ElementBases> &bases,
36 const std::vector<basis::ElementBases> &geom_bases,
39 const double t,
const double dt,
43 geom_bases_(geom_bases),
44 assembler_(assembler),
45 ass_vals_cache_(ass_vals_cache),
53 mat_cache_ = std::make_unique<utils::SparseMatrixCache>();
67 assert(abs(out.sum() -
value_unweighted(
x)) < std::max(1e-10 * out.sum(), 1e-10));
83 hessian.resize(
x.size(),
x.size());
101 Eigen::VectorXd grad;
104 if (grad.array().isNaN().any())
129 const int n_elements = int(
bases_.size());
140 for (
int e = start; e < end; ++e)
148 Eigen::MatrixXd u, grad_u, prev_u, prev_grad_u, p, grad_p;
153 for (
int q = 0; q < local_storage.da.size(); ++q)
155 Eigen::MatrixXd grad_p_i, grad_u_i, prev_grad_u_i;
160 Eigen::MatrixXd f_prime_dpsi, f_prime_dphi;
164 local_storage.vec(0) += -dot(f_prime_dpsi, grad_p_i) * local_storage.da(q);
165 local_storage.vec(1) += -dot(f_prime_dphi, grad_p_i) * local_storage.da(q);
170 for (
const LocalThreadVecStorage &local_storage : storage)
171 term += local_storage.vec;
175 term.setZero(n_elements * 2, 1);
182 for (
int e = start; e < end; ++e)
190 Eigen::MatrixXd u, grad_u, p, grad_p;
194 for (
int q = 0; q < local_storage.da.size(); ++q)
196 Eigen::MatrixXd grad_p_i, grad_u_i;
200 Eigen::MatrixXd f_prime_dmu, f_prime_dlambda;
204 local_storage.vec(e + n_elements) += -dot(f_prime_dmu, grad_p_i) * local_storage.da(q);
205 local_storage.vec(e) += -dot(f_prime_dlambda, grad_p_i) * local_storage.da(q);
210 for (
const LocalThreadVecStorage &local_storage : storage)
211 term += local_storage.vec;
218 const int actual_dim = (
assembler_.
name() ==
"Laplacian") ? 1 : dim;
220 const int n_elements = int(
bases_.size());
221 term.setZero(n_verts * dim, 1);
230 for (
int e = start; e < end; ++e)
240 Eigen::MatrixXd u, grad_u, prev_u, prev_grad_u, p, grad_p;
245 Eigen::MatrixXd grad_u_i, grad_p_i, prev_grad_u_i;
246 Eigen::MatrixXd grad_v_i;
247 Eigen::MatrixXd stress_tensor, f_prime_gradu_gradv;
248 Eigen::MatrixXd f_prev_prime_prev_gradu_gradv;
250 for (
int q = 0; q < local_storage.da.size(); ++q)
256 for (
auto &v :
gvals.basis_values)
258 Eigen::MatrixXd stress_grad, stress_prev_grad;
261 for (
int d = 0; d < dim; d++)
263 grad_v_i.setZero(dim, dim);
264 grad_v_i.row(d) = v.grad_t_m.row(q);
266 f_prime_gradu_gradv.setZero(dim, dim);
267 Eigen::MatrixXd tmp = grad_u_i * grad_v_i;
268 for (
int i = 0; i < f_prime_gradu_gradv.rows(); i++)
269 for (
int j = 0; j < f_prime_gradu_gradv.cols(); j++)
270 for (
int k = 0; k < tmp.rows(); k++)
271 for (
int l = 0; l < tmp.cols(); l++)
272 f_prime_gradu_gradv(i, j) += stress_grad(i * dim + j, k * dim + l) * tmp(k, l);
274 f_prev_prime_prev_gradu_gradv.setZero(dim, dim);
275 tmp = prev_grad_u_i * grad_v_i;
276 for (
int i = 0; i < f_prev_prime_prev_gradu_gradv.rows(); i++)
277 for (
int j = 0; j < f_prev_prime_prev_gradu_gradv.cols(); j++)
278 for (
int k = 0; k < tmp.rows(); k++)
279 for (
int l = 0; l < tmp.cols(); l++)
280 f_prev_prime_prev_gradu_gradv(i, j) += stress_prev_grad(i * dim + j, k * dim + l) * tmp(k, l);
282 tmp = grad_v_i - grad_v_i.trace() * Eigen::MatrixXd::Identity(dim, dim);
283 local_storage.vec(v.global[0].index * dim + d) -= dot(f_prime_gradu_gradv + f_prev_prime_prev_gradu_gradv + stress_tensor * tmp.transpose(), grad_p_i) * local_storage.da(q);
295 for (
int e = start; e < end; ++e)
305 Eigen::MatrixXd u, grad_u, p, grad_p;
310 for (
int q = 0; q < local_storage.da.size(); ++q)
312 Eigen::MatrixXd grad_u_i, grad_p_i, stiffness_i;
315 grad_u_i = grad_u.row(q);
316 grad_p_i = grad_p.row(q);
326 for (
auto &v :
gvals.basis_values)
328 for (
int d = 0; d < dim; d++)
330 Eigen::MatrixXd grad_v_i;
331 grad_v_i.setZero(dim, dim);
332 grad_v_i.row(d) = v.grad_t_m.row(q);
334 Eigen::MatrixXd stress_tensor, f_prime_gradu_gradv;
338 Eigen::MatrixXd tmp = grad_v_i - grad_v_i.trace() * Eigen::MatrixXd::Identity(dim, dim);
339 local_storage.vec(v.global[0].index * dim + d) -= dot(f_prime_gradu_gradv + stress_tensor * tmp.transpose(), grad_p_i) * local_storage.da(q);
347 for (
const LocalThreadVecStorage &local_storage : storage)
348 term += local_storage.vec;
ElementAssemblyValues vals
assembler::ElementAssemblyValues gvals
#define POLYFEM_SCOPED_TIMER(...)
virtual void assemble(const bool is_volume, const int n_basis, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const AssemblyValsCache &cache, const double t, StiffnessMatrix &stiffness, const bool is_mass=false) const
virtual void compute_dstress_dmu_dlambda(const OptAssemblerData &data, Eigen::MatrixXd &dstress_dmu, Eigen::MatrixXd &dstress_dlambda) const
virtual void compute_stress_grad_multiply_mat(const OptAssemblerData &data, const Eigen::MatrixXd &mat, Eigen::MatrixXd &stress, Eigen::MatrixXd &result) const
virtual std::string name() const =0
virtual Eigen::VectorXd assemble_energy_per_element(const bool is_volume, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const AssemblyValsCache &cache, const double t, const double dt, const Eigen::MatrixXd &displacement, const Eigen::MatrixXd &displacement_prev) const
virtual void assemble_gradient(const bool is_volume, const int n_basis, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const AssemblyValsCache &cache, const double t, const double dt, const Eigen::MatrixXd &displacement, const Eigen::MatrixXd &displacement_prev, Eigen::MatrixXd &rhs) const
virtual void compute_stress_grad(const OptAssemblerData &data, const Eigen::MatrixXd &prev_grad_u_i, Eigen::MatrixXd &stress, Eigen::MatrixXd &result) const
virtual void assemble_hessian(const bool is_volume, const int n_basis, const bool project_to_psd, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const AssemblyValsCache &cache, const double t, const double dt, const Eigen::MatrixXd &displacement, const Eigen::MatrixXd &displacement_prev, utils::MatrixCache &mat_cache, StiffnessMatrix &grad) const
virtual double assemble_energy(const bool is_volume, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const AssemblyValsCache &cache, const double t, const double dt, const Eigen::MatrixXd &displacement, const Eigen::MatrixXd &displacement_prev) const
virtual bool is_linear() const =0
virtual void compute_stress_prev_grad(const OptAssemblerData &data, const Eigen::MatrixXd &prev_grad_u_i, Eigen::MatrixXd &result) const
Caches basis evaluation and geometric mapping at every element.
void compute(const int el_index, const bool is_volume, const basis::ElementBases &basis, const basis::ElementBases &gbasis, ElementAssemblyValues &vals) const
retrieves cached basis evaluation and geometric for the given element if it doesn't exist,...
stores per element basis values at given quadrature points and geometric mapping
void compute(const int el_index, const bool is_volume, const Eigen::MatrixXd &pts, const basis::ElementBases &basis, const basis::ElementBases &gbasis)
computes the per element values at the local (ref el) points (pts) sets basis_values,...
quadrature::Quadrature quadrature
static void compute_dstress_dpsi_dphi(const OptAssemblerData &data, const Eigen::MatrixXd &prev_grad_u_i, Eigen::MatrixXd &dstress_dpsi, Eigen::MatrixXd &dstress_dphi)
static void interpolate_at_local_vals(const mesh::Mesh &mesh, const bool is_problem_scalar, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const int el_index, const Eigen::MatrixXd &local_pts, const Eigen::MatrixXd &fun, Eigen::MatrixXd &result, Eigen::MatrixXd &result_grad)
interpolate solution and gradient at element (calls interpolate_at_local_vals with sol)
void vector2matrix(const Eigen::VectorXd &vec, Eigen::MatrixXd &mat)
auto & get_local_thread_storage(Storages &storage, int thread_id)
auto create_thread_storage(const LocalStorage &initial_local_storage)
void maybe_parallel_for(int size, const std::function< void(int, int, int)> &partial_for)
Eigen::Matrix< double, Eigen::Dynamic, 1, 0, MAX_QUAD_POINTS, 1 > QuadratureVector
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix