10#include <SimpleBVH/BVH.hpp>
14 using namespace basis;
16 using namespace utils;
22 class LocalThreadMatStorage
25 std::vector<Eigen::Triplet<double>>
entries;
28 ElementAssemblyValues
vals;
32 LocalThreadMatStorage()
36 LocalThreadMatStorage(
const int buffer_size,
const int mat_size)
38 init(buffer_size, mat_size);
41 void init(
const int buffer_size,
const int mat_size)
44 tmp_mat.resize(mat_size, mat_size);
62 logger().debug(
"cleaning memory...");
73 const std::vector<ElementBases> &bases,
74 const std::vector<ElementBases> &gbases,
78 const int buffer_size = std::min(
long(1e8),
long(n_basis) * size);
81 mass.resize(n_basis * size, n_basis * size);
86 const int n_bases = int(bases.size());
91 for (
int e = start; e < end; ++e)
94 bases[e].compute_mass_quadrature(
vals.quadrature);
96 vals.compute(e, is_volume,
quadrature.points, bases[e], gbases[e]);
98 assert(MAX_QUAD_POINTS == -1 ||
quadrature.weights.size() < MAX_QUAD_POINTS);
100 const int n_loc_bases = int(
vals.basis_values.size());
102 for (
int i = 0; i < n_loc_bases; ++i)
104 const auto &global_i =
vals.basis_values[i].global;
106 for (
int j = 0; j <= i; ++j)
108 const auto &global_j =
vals.basis_values[j].global;
111 for (
int q = 0; q < local_storage.da.size(); ++q)
114 const double rho = density(
vals.quadrature.points.row(q),
vals.val.row(q), 0,
vals.element_id);
115 tmp += rho *
vals.basis_values[i].val(q) *
vals.basis_values[j].val(q) * local_storage.da(q);
118 for (
int n = 0; n < size; ++n)
124 const double local_value = tmp;
125 for (
size_t ii = 0; ii < global_i.size(); ++ii)
127 const auto gi = global_i[ii].index * size + m;
128 const auto wi = global_i[ii].val;
130 for (
size_t jj = 0; jj < global_j.size(); ++jj)
132 const auto gj = global_j[jj].index * size + n;
133 const auto wj = global_j[jj].val;
135 local_storage.entries.emplace_back(gi, gj, local_value * wi * wj);
138 local_storage.entries.emplace_back(gj, gi, local_value * wj * wi);
141 local_storage.condense();
158 for (LocalThreadMatStorage &local_storage : storage)
160 mass += local_storage.mass_mat;
161 local_storage.tmp_mat.setFromTriplets(local_storage.entries.begin(), local_storage.entries.end());
162 mass += local_storage.tmp_mat;
164 mass.makeCompressed();
172 const Eigen::MatrixXd &nodes,
const Eigen::Vector2d &uv)
174 assert(nodes.rows() == 3 && nodes.cols() == 2);
175 return (1 - uv[0] - uv[1]) * nodes.row(0) + uv[0] * nodes.row(1) + uv[1] * nodes.row(2);
179 const Eigen::MatrixXd &nodes,
const Eigen::Vector3d &uvw)
181 assert(nodes.rows() == 4 && nodes.cols() == 3);
182 return (1 - uvw[0] - uvw[1] - uvw[2]) * nodes.row(0) + uvw[0] * nodes.row(1) + uvw[1] * nodes.row(2) + uvw[2] * nodes.row(3);
187 const bool is_volume,
189 const int n_from_basis,
190 const std::vector<basis::ElementBases> &from_bases,
191 const std::vector<basis::ElementBases> &from_gbases,
192 const int n_to_basis,
193 const std::vector<basis::ElementBases> &to_bases,
194 const std::vector<basis::ElementBases> &to_gbases,
198 const int buffer_size = std::min(
long(1e8),
long(std::max(n_from_basis, n_to_basis)) * size);
201 mass.resize(n_to_basis * size, n_from_basis * size);
213 std::vector<std::array<Eigen::Vector3d, 2>> boxes(from_bases.size());
214 for (
int i = 0; i < from_bases.size(); i++)
216 const Eigen::MatrixXd from_nodes = from_bases[i].nodes();
217 boxes[i][0].setZero();
218 boxes[i][0].head(size) = from_nodes.colwise().minCoeff();
219 boxes[i][1].setZero();
220 boxes[i][1].head(size) = from_nodes.colwise().maxCoeff();
229 std::vector<Eigen::Triplet<double>> triplets;
233 const Eigen::MatrixXd to_nodes = to_element.nodes();
235 std::vector<unsigned int> candidates;
237 Eigen::Vector3d bbox_min = Eigen::Vector3d::Zero();
238 bbox_min.head(size) = to_nodes.colwise().minCoeff();
239 Eigen::Vector3d bbox_max = Eigen::Vector3d::Zero();
240 bbox_max.head(size) = to_nodes.colwise().maxCoeff();
241 bvh.intersect_box(bbox_min, bbox_max, candidates);
245 for (
const unsigned int from_element_i : candidates)
247 const ElementBases &from_element = from_bases[from_element_i];
248 const Eigen::MatrixXd from_nodes = from_element.
nodes();
251 const std::vector<Eigen::MatrixXd> overlap =
256 for (
const Eigen::MatrixXd &simplex : overlap)
259 if (abs(volume) == 0.0)
263 for (
int qi = 0; qi <
quadrature.size(); qi++)
267 const double w = (is_volume ? 6 : 2) * volume *
quadrature.weights[qi];
270 const VectorNd p = is_volume ? P1_3D_gmapping(simplex, q) : P1_2D_gmapping(simplex, q);
276 std::vector<AssemblyValues> from_phi, to_phi;
278 to_element.evaluate_bases(to_bc, to_phi);
281 Eigen::MatrixXd debug;
283 assert((debug.transpose() - p).norm() < 1e-12);
284 to_element.eval_geom_mapping(to_bc, debug);
285 assert((debug.transpose() - p).norm() < 1e-12);
288 for (
int n = 0; n < size; ++n)
293 for (
int to_local_i = 0; to_local_i < to_phi.size(); ++to_local_i)
295 const int to_global_i = to_element.bases[to_local_i].global()[0].index * size + m;
296 for (
int from_local_i = 0; from_local_i < from_phi.size(); ++from_local_i)
298 const auto from_global_i = from_element.
bases[from_local_i].global()[0].index * size + n;
299 triplets.emplace_back(
300 to_global_i, from_global_i,
301 w * from_phi[from_local_i].
val(0) * to_phi[to_local_i].
val(0));
311 mass.setFromTriplets(triplets.begin(), triplets.end());
312 mass.makeCompressed();
std::unique_ptr< MatrixCache > cache
ElementAssemblyValues vals
std::vector< Eigen::Triplet< double > > entries
Caches basis evaluation and geometric mapping at every element.
stores per element basis values at given quadrature points and geometric mapping
void assemble(const bool is_volume, const int size, const int n_basis, const Density &density, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const AssemblyValsCache &cache, StiffnessMatrix &mass) const
Assembles the mass matrix.
void assemble_cross(const bool is_volume, const int size, const int n_from_basis, const std::vector< basis::ElementBases > &from_bases, const std::vector< basis::ElementBases > &from_gbases, const int n_to_basis, const std::vector< basis::ElementBases > &to_bases, const std::vector< basis::ElementBases > &to_gbases, const AssemblyValsCache &cache, StiffnessMatrix &mass) const
Assembles the cross mass matrix between to function spaces.
Stores the basis functions for a given element in a mesh (facet in 2d, cell in 3d).
void eval_geom_mapping(const Eigen::MatrixXd &samples, Eigen::MatrixXd &mapped) const
Map the sample positions in the parametric domain to the object domain (if the element has no paramet...
void evaluate_bases(const Eigen::MatrixXd &uv, std::vector< assembler::AssemblyValues > &basis_values) const
evaluate stored bases at given points on the reference element saves results to basis_values
Eigen::MatrixXd nodes() const
Assemble the global nodal positions of the bases.
std::vector< Basis > bases
one basis function per node in the element
void get_quadrature(const int order, Quadrature &quad)
void get_quadrature(const int order, Quadrature &quad)
static std::vector< Eigen::MatrixXd > clip(const Eigen::MatrixXd &subject_tet, const Eigen::MatrixXd &clipping_tet)
Clip a tetrahedron using tetrahedron.
static std::vector< Eigen::MatrixXd > clip(const Eigen::MatrixXd &subject_triangle, const Eigen::MatrixXd &clipping_triangle)
Clip a triangle using triangle.
auto & get_local_thread_storage(Storages &storage, int thread_id)
double tetrahedron_volume(const Eigen::Vector3d &a, const Eigen::Vector3d &b, const Eigen::Vector3d &c, const Eigen::Vector3d &d)
Compute the signed volume of a tetrahedron defined by four points.
Eigen::VectorXd barycentric_coordinates(const Eigen::VectorXd &p, const Eigen::MatrixXd &V)
Compute barycentric coordinates for point p with respect to a simplex.
auto create_thread_storage(const LocalStorage &initial_local_storage)
double triangle_area(const Eigen::MatrixXd V)
Compute the signed area of a triangle defined by three points.
void maybe_parallel_for(int size, const std::function< void(int, int, int)> &partial_for)
spdlog::logger & logger()
Retrieves the current logger.
Eigen::Matrix< double, Eigen::Dynamic, 1, 0, 3, 1 > VectorNd
Eigen::Matrix< double, Eigen::Dynamic, 1, 0, MAX_QUAD_POINTS, 1 > QuadratureVector
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix