86 const int n_from_basis,
87 const std::vector<basis::ElementBases> &from_bases,
88 const std::vector<basis::ElementBases> &from_gbases,
90 const std::vector<basis::ElementBases> &to_bases,
91 const std::vector<basis::ElementBases> &to_gbases,
95 const int buffer_size = std::min(
long(1e8),
long(std::max(n_from_basis, n_to_basis)) * size);
98 mass.resize(n_to_basis * size, n_from_basis * size);
110 std::vector<std::array<Eigen::Vector3d, 2>> boxes(from_bases.size());
111 for (
int i = 0; i < from_bases.size(); i++)
113 const Eigen::MatrixXd from_nodes = from_bases[i].nodes();
114 boxes[i][0].setZero();
115 boxes[i][0].head(size) = from_nodes.colwise().minCoeff();
116 boxes[i][1].setZero();
117 boxes[i][1].head(size) = from_nodes.colwise().maxCoeff();
126 std::vector<Eigen::Triplet<double>> triplets;
130 const Eigen::MatrixXd to_nodes = to_element.nodes();
132 std::vector<unsigned int> candidates;
134 Eigen::Vector3d bbox_min = Eigen::Vector3d::Zero();
135 bbox_min.head(size) = to_nodes.colwise().minCoeff();
136 Eigen::Vector3d bbox_max = Eigen::Vector3d::Zero();
137 bbox_max.head(size) = to_nodes.colwise().maxCoeff();
138 bvh.intersect_box(bbox_min, bbox_max, candidates);
142 for (
const unsigned int from_element_i : candidates)
144 const ElementBases &from_element = from_bases[from_element_i];
145 const Eigen::MatrixXd from_nodes = from_element.
nodes();
148 const std::vector<Eigen::MatrixXd> overlap =
153 for (
const Eigen::MatrixXd &simplex : overlap)
156 if (abs(volume) == 0.0)
160 for (
int qi = 0; qi <
quadrature.size(); qi++)
164 const double w = (is_volume ? 6 : 2) * volume *
quadrature.weights[qi];
167 const VectorNd p = is_volume ? P1_3D_gmapping(simplex, q) : P1_2D_gmapping(simplex, q);
173 std::vector<AssemblyValues> from_phi, to_phi;
175 to_element.evaluate_bases(to_bc, to_phi);
178 Eigen::MatrixXd debug;
180 assert((debug.transpose() - p).norm() < 1e-12);
181 to_element.eval_geom_mapping(to_bc, debug);
182 assert((debug.transpose() - p).norm() < 1e-12);
185 for (
int n = 0; n < size; ++n)
190 for (
int to_local_i = 0; to_local_i < to_phi.size(); ++to_local_i)
192 const int to_global_i = to_element.bases[to_local_i].global()[0].index * size + m;
193 for (
int from_local_i = 0; from_local_i < from_phi.size(); ++from_local_i)
195 const auto from_global_i = from_element.
bases[from_local_i].global()[0].index * size + n;
196 triplets.emplace_back(
197 to_global_i, from_global_i,
198 w * from_phi[from_local_i].
val(0) * to_phi[to_local_i].
val(0));
208 mass.setFromTriplets(triplets.begin(), triplets.end());
209 mass.makeCompressed();
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.