13 #include "../../general/tic_toc.hpp"
21 #include "moonolith_aabb.hpp"
22 #include "moonolith_serial_hash_grid.hpp"
23 #include "moonolith_stream_utils.hpp"
24 #include "par_moonolith_config.hpp"
26 using namespace mfem::internal;
31 struct MortarAssembler::Impl
34 std::shared_ptr<FiniteElementSpace>
source;
35 std::shared_ptr<FiniteElementSpace> destination;
36 std::vector<std::shared_ptr<MortarIntegrator>> integrators;
37 std::shared_ptr<SparseMatrix> coupling_matrix;
38 std::shared_ptr<SparseMatrix> mass_matrix;
40 bool assemble_mass_and_coupling_together{
true};
41 int max_solver_iterations{400};
43 bool is_vector_fe()
const
45 bool is_vector_fe =
false;
46 for (
auto i_ptr : integrators)
48 if (i_ptr->is_vector_fe())
58 BilinearFormIntegrator * new_mass_integrator()
const
62 return new VectorFEMassIntegrator();
66 return new MassIntegrator();
75 impl_->assemble_mass_and_coupling_together = value;
80 impl_->max_solver_iterations = max_solver_iterations;
84 const std::shared_ptr<MortarIntegrator> &integrator)
86 impl_->integrators.push_back(integrator);
91 impl_->verbose = verbose;
96 std::vector<::moonolith::AABB<Dim, double>> &element_boxes)
102 element_boxes.resize(mesh.
GetNE());
105 for (
int i = 0; i < mesh.
GetNE(); ++i)
108 MinCol(pts, &element_boxes[i].min_[0],
false);
109 MaxCol(pts, &element_boxes[i].max_[0],
false);
114 std::vector<moonolith::Integer> &pairs)
122 std::vector<::moonolith::AABB<1, double>> src_boxes, dest_boxes;
126 ::moonolith::SerialHashGrid<1, double> grid;
127 return grid.detect(src_boxes, dest_boxes, pairs);
131 std::vector<::moonolith::AABB<2, double>> src_boxes, dest_boxes;
135 ::moonolith::SerialHashGrid<2, double> grid;
136 return grid.detect(src_boxes, dest_boxes, pairs);
140 std::vector<::moonolith::AABB<3, double>> src_boxes, dest_boxes;
144 ::moonolith::SerialHashGrid<3, double> grid;
145 return grid.detect(src_boxes, dest_boxes, pairs);
156 const std::shared_ptr<FiniteElementSpace> &
source,
157 const std::shared_ptr<FiniteElementSpace> &destination)
161 impl_->destination = destination;
174 const bool verbose = impl_->verbose;
176 const auto &source_mesh = *impl_->source->GetMesh();
177 const auto &destination_mesh = *impl_->destination->GetMesh();
179 int dim = source_mesh.Dimension();
181 std::vector<::moonolith::Integer> pairs;
190 assert(
false &&
"NOT Supported!");
199 B = make_shared<SparseMatrix>(impl_->destination->GetNDofs(),
200 impl_->source->GetNDofs());
203 std::unique_ptr<BilinearFormIntegrator> mass_integr(impl_->new_mass_integrator());
205 if(impl_->assemble_mass_and_coupling_together) {
206 impl_->mass_matrix = make_shared<SparseMatrix>(impl_->destination->GetNDofs(), impl_->destination->GetNDofs());
214 double local_element_matrices_sum = 0.0;
216 long n_intersections = 0;
217 long n_candidates = 0;
221 for (
auto i_ptr : impl_->integrators)
223 max_q_order = std::max(i_ptr->GetQuadratureOrder(), max_q_order);
226 bool intersected =
false;
227 for (
auto it = begin(pairs); it != end(pairs); )
229 const int source_index = *it++;
230 const int destination_index = *it++;
232 auto &source_fe = *impl_->source->GetFE(source_index);
233 auto &destination_fe = *impl_->destination->GetFE(destination_index);
236 *impl_->destination->GetElementTransformation(destination_index);
242 const int src_order = src_order_mult * source_fe.GetOrder();
243 const int dest_order = dest_order_mult * destination_fe.GetOrder();
245 int contraction_order = src_order + dest_order;
247 if(impl_->assemble_mass_and_coupling_together) {
248 contraction_order = std::max(contraction_order, 2 * dest_order);
251 const int order = contraction_order + dest_order_mult * destination_Trans.
OrderW() + max_q_order;
254 cut->SetIntegrationOrder(order);
258 if (cut->BuildQuadrature(*impl_->source, source_index, *impl_->destination,
259 destination_index, source_ir, destination_ir))
261 impl_->source->GetElementVDofs(source_index, source_vdofs);
262 impl_->destination->GetElementVDofs(destination_index, destination_vdofs);
265 *impl_->source->GetElementTransformation(source_index);
268 for (
auto i_ptr : impl_->integrators)
272 i_ptr->AssembleElementMatrix(source_fe, source_ir, source_Trans,
273 destination_fe, destination_ir,
274 destination_Trans, cumulative_elemmat);
279 i_ptr->AssembleElementMatrix(source_fe, source_ir, source_Trans,
280 destination_fe, destination_ir,
281 destination_Trans, elemmat);
282 cumulative_elemmat += elemmat;
286 local_element_matrices_sum += Sum(cumulative_elemmat);
288 B->AddSubMatrix(destination_vdofs, source_vdofs, cumulative_elemmat,
291 if(impl_->assemble_mass_and_coupling_together) {
292 mass_integr->SetIntRule(&destination_ir);
293 mass_integr->AssembleElementMatrix(destination_fe, destination_Trans, elemmat);
294 impl_->mass_matrix->AddSubMatrix(destination_vdofs, destination_vdofs, elemmat, skip_zeros);
309 if(impl_->assemble_mass_and_coupling_together) {
310 impl_->mass_matrix->Finalize();
315 mfem::out <<
"local_element_matrices_sum: " << local_element_matrices_sum
317 mfem::out <<
"B in R^(" << B->Height() <<
" x " << B->Width() <<
")"
320 mfem::out <<
"n_intersections: " << n_intersections
321 <<
", n_candidates: " << n_candidates <<
'\n';
338 if (!impl_->coupling_matrix)
346 Vector temp(impl_->coupling_matrix->Height());
347 impl_->coupling_matrix->Mult(src_fun, temp);
350 Dinv.
SetMaxIter(impl_->max_solver_iterations);
359 Dinv.
Mult(temp, dest_fun);
366 const bool verbose = impl_->verbose;
372 mfem::out <<
"\nAssembling coupling operator..." << endl;
377 if (!
Assemble(impl_->coupling_matrix))
386 mfem::out << chrono.RealTime() <<
" seconds" << endl;
389 if(!impl_->assemble_mass_and_coupling_together) {
397 impl_->mass_matrix = std::shared_ptr<SparseMatrix>(b_form.LoseMat());
402 Vector brs(impl_->coupling_matrix->Height());
403 impl_->coupling_matrix->GetRowSums(brs);
405 Vector drs(impl_->mass_matrix->Height());
406 impl_->mass_matrix->GetRowSums(drs);
408 mfem::out <<
"sum(B): " << brs.Sum() << std::endl;
409 mfem::out <<
"sum(D): " << drs.Sum() << std::endl;
void GetPointMatrix(int i, DenseMatrix &pointmat) const
Conjugate gradient method.
Class for an integration rule - an Array of IntegrationPoint.
Class for grid function - Vector with associated FE space.
int order_multiplier(const Geometry::Type type, const int dim)
bool Apply(const GridFunction &src_fun, GridFunction &dest_fun)
transfer a function from source to destination. It requires that the Update function is called before...
void SetVerbose(const bool verbose)
Expose process details with verbose output.
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
bool HashGridDetectIntersections(const Mesh &src, const Mesh &dest, std::vector< moonolith::Integer > &pairs)
Data type dense matrix using column-major storage.
int GetNE() const
Returns number of elements.
bool Update()
assembles the various components necessary for the transfer. To be called before calling the Apply fu...
void source(const Vector &x, Vector &f)
MortarAssembler(const std::shared_ptr< FiniteElementSpace > &source, const std::shared_ptr< FiniteElementSpace > &destination)
constructs the object with source and destination spaces
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
bool Transfer(const GridFunction &src_fun, GridFunction &dest_fun)
transfer a function from source to destination. if the transfer is to be performed multiple times use...
void SetMaxIter(int max_it)
void SetAssembleMassAndCouplingTogether(const bool value)
Control if the Mass matrix is computed together with the coupling operator every time.
void SetRelTol(double rtol)
std::shared_ptr< Cut > NewCut(const int dim)
void SetMaxSolverIterations(const int max_solver_iterations)
Control the maximum numbers of conjugate gradients steps for mass matrix inversion.
void BuildBoxes(const Mesh &mesh, std::vector<::moonolith::AABB< Dim, double >> &element_boxes)
void AddMortarIntegrator(const std::shared_ptr< MortarIntegrator > &integrator)
This method must be called before Assemble or Transfer. It will assemble the operator in all intersec...
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
bool Assemble(std::shared_ptr< SparseMatrix > &B)
assembles the coupling matrix B. B : source -> destination If u is a coefficient associated with sour...
void pts(int iphi, int t, double x[])
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...