15#ifdef MFEM_USE_MOONOLITH
23#include "moonolith_bounding_volume_with_span.hpp"
24#include "moonolith_n_tree_mutator_factory.hpp"
25#include "moonolith_n_tree_with_span_mutator_factory.hpp"
26#include "moonolith_n_tree_with_tags_mutator_factory.hpp"
27#include "moonolith_profiler.hpp"
28#include "moonolith_redistribute.hpp"
29#include "moonolith_sparse_matrix.hpp"
30#include "moonolith_tree.hpp"
31#include "par_moonolith.hpp"
35using namespace mfem::internal;
40struct ParMortarAssembler::Impl
44 std::shared_ptr<ParFiniteElementSpace> source;
45 std::shared_ptr<ParFiniteElementSpace> destination;
46 std::vector<std::shared_ptr<MortarIntegrator>> integrators;
48 std::shared_ptr<HypreParMatrix> coupling_matrix;
49 std::shared_ptr<HypreParMatrix> mass_matrix;
51 std::shared_ptr<IterativeSolver> solver;
55 bool assemble_mass_and_coupling_together{
true};
61 solver = std::make_shared<BiCGSTABSolver>(comm);
62 solver->SetMaxIter(20000);
63 solver->SetRelTol(1e-6);
67 bool is_vector_fe()
const
69 bool is_vector_fe =
false;
70 for (
auto i_ptr : integrators)
72 if (i_ptr->is_vector_fe())
100 impl_->solver = solver;
105 impl_->assemble_mass_and_coupling_together = value;
110 impl_->ensure_solver();
112 impl_->solver->SetMaxIter(max_solver_iterations);
116 const std::shared_ptr<MortarIntegrator> &integrator)
118 impl_->integrators.push_back(integrator);
123 impl_->verbose = verbose;
126template <
int Dimension>
class ElementAdapter :
public moonolith::Serializable
129 using Bound = moonolith::AABBWithKDOPSpan<Dimension, double>;
130 using Point = moonolith::Vector<double, Dimension>;
132 inline int tag()
const {
return tag_; }
134 const Bound &bound()
const {
return bound_; }
136 Bound &bound() {
return bound_; }
138 void applyRW(moonolith::Stream &stream)
142 stream &element_handle_;
146 const long element_handle,
const int tag)
147 : fe_(&fe), element_(element), element_handle_(element_handle), tag_(tag),
150 assert(element < fe.
GetNE());
156 for (
int j = 0; j <
pts.Width(); ++j)
158 for (
int i = 0; i <
pts.Height(); ++i)
160 p[i] =
pts.Elem(i, j);
163 bound_.static_bound() +=
p;
164 bound_.dynamic_bound() +=
p;
169 : fe_(nullptr), element_(-1), element_handle_(-1), tag_(-1),
172 inline long handle()
const {
return element_handle_; }
174 inline long element()
const {
return element_; }
179 assert(element_ < fe_->GetNE());
180 return *fe_->
GetFE(element_);
189 void set_dof_map(std::vector<long> *ptr) { dof_map_ = ptr; }
191 void get_elements_vdofs(
Array<int> &vdofs)
const
197 assert(dof_map_->size() == vdofs.
Size());
199 for (
int i = 0; i < vdofs.
Size(); ++i)
201 vdofs[i] = dof_map_->at(i);
214 long element_handle_;
217 std::vector<long> *dof_map_;
220template <
int _Dimension>
class TreeTraits
223 enum { Dimension = _Dimension };
225 using Bound = moonolith::AABBWithKDOPSpan<Dimension, double>;
226 using DataType = mfem::ElementAdapter<Dimension>;
229template <
int Dimension>
230class MFEMTree :
public moonolith::Tree<TreeTraits<Dimension>>
233 using Traits = mfem::TreeTraits<Dimension>;
237 static std::shared_ptr<MFEMTree>
238 New(
const int maxElementsXNode = moonolith::DEFAULT_REFINE_MAX_ELEMENTS,
239 const int maxDepth = moonolith::DEFAULT_REFINE_DEPTH)
241 using namespace moonolith;
243 std::shared_ptr<MFEMTree> tree = std::make_shared<MFEMTree>();
244 std::shared_ptr<NTreeWithSpanMutatorFactory<MFEMTree>> factory =
245 std::make_shared<NTreeWithSpanMutatorFactory<MFEMTree>>();
246 factory->set_refine_params(maxElementsXNode, maxDepth);
247 tree->set_mutator_factory(factory);
251 static std::shared_ptr<MFEMTree>
252 New(
const std::shared_ptr<moonolith::Predicate> &predicate,
253 const int maxElementsXNode = moonolith::DEFAULT_REFINE_MAX_ELEMENTS,
254 const int maxDepth = moonolith::DEFAULT_REFINE_DEPTH)
256 using namespace moonolith;
260 return New(maxElementsXNode, maxDepth);
263 std::shared_ptr<MFEMTree> tree = std::make_shared<MFEMTree>();
264 std::shared_ptr<NTreeWithTagsMutatorFactory<MFEMTree>> factory =
265 std::make_shared<NTreeWithTagsMutatorFactory<MFEMTree>>(predicate);
266 factory->set_refine_params(maxElementsXNode, maxDepth);
267 tree->set_mutator_factory(factory);
272class ElementDofMap :
public moonolith::Serializable
275 void read(moonolith::InputStream &is)
override
280 is.read(&global[0], n);
283 void write(moonolith::OutputStream &os)
const override
285 int n = global.size();
287 os.write(&global[0], n);
290 std::vector<long> global;
296 explicit Spaces(
const moonolith::Communicator &comm) : comm(comm)
298 must_destroy_attached[0] =
false;
299 must_destroy_attached[1] =
false;
302 Spaces(
const std::shared_ptr<ParFiniteElementSpace> &
source,
303 const std::shared_ptr<ParFiniteElementSpace> &destination)
306 spaces_.push_back(
source);
307 spaces_.push_back(destination);
309 must_destroy_attached[0] =
false;
310 must_destroy_attached[1] =
false;
312 copy_global_dofs(*
source, dof_maps_[0]);
313 copy_global_dofs(*destination, dof_maps_[1]);
321 for (
int i = 0; i < spaces_.size(); ++i)
323 if (spaces_[i] && must_destroy_attached[0])
325 m = spaces_[i]->GetMesh();
329 spaces_[i] = std::shared_ptr<FiniteElementSpace>();
337 inline long n_elements()
const
340 for (
auto s : spaces_)
351 inline std::vector<std::shared_ptr<FiniteElementSpace>> &spaces()
356 inline const std::vector<std::shared_ptr<FiniteElementSpace>> &
362 inline std::vector<ElementDofMap> &dof_map(
const int i)
369 inline const std::vector<ElementDofMap> &dof_map(
const int i)
const
376 inline void set_must_destroy_attached(
const int index,
const bool value)
380 must_destroy_attached[
index] = value;
384 std::vector<std::shared_ptr<FiniteElementSpace>> spaces_;
385 moonolith::Communicator comm;
386 std::vector<ElementDofMap> dof_maps_[2];
387 bool must_destroy_attached[2];
390 std::vector<ElementDofMap> &dof_map)
392 dof_map.resize(fe.
GetNE());
394 for (
int i = 0; i < fe.
GetNE(); ++i)
397 for (
int k = 0; k < vdofs.
Size(); ++k)
409 dof_map[i].global.push_back(g_dof);
415template <
class Iterator>
416static void write_space(
const Iterator &begin,
const Iterator &end,
418 const std::vector<ElementDofMap> &dof_map,
419 const int role, moonolith::OutputStream &os)
421 const int dim =
space.GetMesh()->Dimension();
422 const long n_elements = std::distance(begin, end);
424 std::set<long> nodeIds;
425 std::map<long, long> mapping;
428 for (Iterator it = begin; it != end; ++it)
431 space.GetElementVertices(i, verts);
433 for (
int j = 0; j < verts.
Size(); ++j)
435 nodeIds.insert(verts[j]);
439 long n_nodes = nodeIds.size();
442 os.request_space((n_elements * 8 + n_nodes *
dim) *
443 (
sizeof(
double) +
sizeof(
long)));
445 auto fe_coll =
space.FEColl();
446 const char *name = fe_coll->Name();
447 const int name_lenght = strlen(name);
451 os.write(name, name_lenght);
454 for (
auto nodeId : nodeIds)
456 mapping[nodeId] =
index++;
465 for (
auto node_id : nodeIds)
467 double *v =
space.GetMesh()->GetVertex(node_id);
468 for (
int i = 0; i <
dim; ++i)
475 for (Iterator it = begin; it != end; ++it)
478 space.GetElementVertices(k, verts);
480 const int attribute =
space.GetAttribute(k);
481 const int e_n_nodes = verts.
Size();
482 const int type =
space.GetElementType(k);
483 const int order =
space.GetOrder(k);
486 os << type << attribute << order << e_n_nodes;
488 for (
int i = 0; i < e_n_nodes; ++i)
490 auto it = mapping.find(verts[i]);
491 assert(it != mapping.end());
493 int index = it->second;
504template <
class Iterator>
505static void write_element_selection(
const Iterator &begin,
const Iterator &end,
506 const Spaces &spaces,
507 moonolith::OutputStream &os)
509 if (spaces.spaces().empty())
515 auto m = spaces.spaces()[0];
516 std::shared_ptr<FiniteElementSpace> s =
nullptr;
518 if (spaces.spaces().size() > 1)
520 s = spaces.spaces()[1];
523 std::vector<long> source_selection;
524 std::vector<long> destination_selection;
526 bool met_destination_selection =
false;
528 for (Iterator it = begin; it != end; ++it)
535 destination_selection.push_back(
index);
539 met_destination_selection =
true;
540 destination_selection.push_back(
index);
544 assert(!met_destination_selection);
546 source_selection.push_back(
index);
550 const bool has_source = !source_selection.empty();
551 const bool has_destination = !destination_selection.empty();
553 os << has_source << has_destination;
557 write_space(source_selection.begin(), source_selection.end(), *m,
558 spaces.dof_map(0), 0, os);
563 write_space(destination_selection.begin(), destination_selection.end(), *s,
564 spaces.dof_map(1), 1, os);
573static void read_space(moonolith::InputStream &is,
574 std::shared_ptr<FiniteElementSpace> &
space,
575 std::vector<ElementDofMap> &dof_map)
580 int dim, role, name_lenght;
584 std::string name(name_lenght, 0);
585 is.read(&name[0], name_lenght);
595 auto fe_coll = FECollFromName(name);
596 auto mesh_ptr =
new Mesh(
dim, n_nodes, n_elements);
598 for (
long i = 0; i < n_nodes; ++i)
601 for (
int i = 0; i <
dim; ++i)
607 mesh_ptr->AddVertex(v);
610 dof_map.resize(n_elements);
611 std::vector<int> e2v;
612 for (
long i = 0; i < n_elements; ++i)
615 int type, attribute, order, e_n_nodes;
616 is >> type >> attribute >> order >> e_n_nodes;
617 e2v.resize(e_n_nodes);
619 for (
int i = 0; i < e_n_nodes; ++i)
626 mesh_ptr->AddElement(NewElem(type, &e2v[0], attribute));
632 Finalize(*mesh_ptr,
true);
635 space = make_shared<FiniteElementSpace>(mesh_ptr, fe_coll);
638static void read_spaces(moonolith::InputStream &is, Spaces &spaces)
640 bool has_source, has_destination;
641 is >> has_source >> has_destination;
643 spaces.spaces().resize(2);
647 read_space(is, spaces.spaces()[0], spaces.dof_map(0));
648 spaces.set_must_destroy_attached(0,
true);
652 spaces.spaces()[0] =
nullptr;
657 read_space(is, spaces.spaces()[1], spaces.dof_map(1));
658 spaces.set_must_destroy_attached(1,
true);
662 spaces.spaces()[1] =
nullptr;
666template <
int Dimensions,
class Fun>
667static bool Assemble(moonolith::Communicator &comm,
668 std::shared_ptr<ParFiniteElementSpace> &
source,
669 std::shared_ptr<ParFiniteElementSpace> &destination,
670 Fun process_fun,
const moonolith::SearchSettings &settings,
673 using namespace moonolith;
675 typedef mfem::MFEMTree<Dimensions> NTreeT;
676 typedef typename NTreeT::DataContainer DataContainer;
677 typedef typename NTreeT::DataType Adapter;
679 long maxNElements = settings.max_elements;
680 long maxDepth = settings.max_depth;
682 const int n_elements_source =
source->GetNE();
683 const int n_elements_destination = destination->GetNE();
684 const int n_elements = n_elements_source + n_elements_destination;
686 auto predicate = std::make_shared<MasterAndSlave>();
687 predicate->add(0, 1);
689 MOONOLITH_EVENT_BEGIN(
"create_adapters");
691 std::shared_ptr<NTreeT> tree = NTreeT::New(predicate, maxNElements, maxDepth);
692 tree->reserve(n_elements);
694 std::shared_ptr<Spaces> local_spaces =
695 std::make_shared<Spaces>(
source, destination);
700 for (
auto s : local_spaces->spaces())
704 for (
int i = 0; i < s->GetNE(); ++i)
706 Adapter
a(*s, i, offset + i, space_num);
707 a.set_dof_map(&local_spaces->dof_map(space_num)[i].global);
711 offset += s->GetNE();
717 tree->root()->bound().static_bound().enlarge(1e-6);
719 MOONOLITH_EVENT_END(
"create_adapters");
722 std::map<long, std::shared_ptr<Spaces>> spaces;
723 std::map<long, std::vector<std::shared_ptr<Spaces>>> migrated_spaces;
725 auto read = [&spaces, &migrated_spaces,
726 comm](
const long ownerrank,
const long ,
727 bool is_forwarding, DataContainer &data, InputStream &in)
729 CHECK_STREAM_READ_BEGIN(
"vol_proj", in);
731 std::shared_ptr<Spaces> proc_space = std::make_shared<Spaces>(comm);
733 read_spaces(in, *proc_space);
737 assert(!spaces[ownerrank]);
738 spaces[ownerrank] = proc_space;
742 migrated_spaces[ownerrank].push_back(proc_space);
745 data.reserve(data.size() + proc_space->n_elements());
749 for (
auto s : proc_space->spaces())
753 for (
int i = 0; i < s->GetNE(); ++i)
755 data.push_back(Adapter(*s, i, offset + i, space_num));
756 data.back().set_dof_map(&proc_space->dof_map(space_num)[i].global);
759 offset += s->GetNE();
765 CHECK_STREAM_READ_END(
"vol_proj", in);
768 auto write = [&local_spaces, &spaces,
769 &comm](
const long ownerrank,
const long ,
770 const std::vector<long>::const_iterator &begin,
771 const std::vector<long>::const_iterator &end,
772 const DataContainer &, OutputStream &
out)
774 CHECK_STREAM_WRITE_BEGIN(
"vol_proj",
out);
776 if (ownerrank == comm.rank())
778 write_element_selection(begin, end, *local_spaces,
out);
782 auto it = spaces.find(ownerrank);
783 assert(it != spaces.end());
784 std::shared_ptr<Spaces> spaceptr = it->second;
785 assert(std::distance(begin, end) > 0);
786 write_element_selection(begin, end, *spaceptr,
out);
789 CHECK_STREAM_WRITE_END(
"vol_proj",
out);
792 long n_false_positives = 0, n_intersections = 0;
793 auto fun = [&n_false_positives, &n_intersections,
794 &process_fun](Adapter &
source, Adapter &destination) ->
bool
796 bool ok = process_fun(
source, destination);
812 moonolith::search_and_compute(comm, tree, predicate,
read,
write, fun,
817 long n_total_candidates = n_intersections + n_false_positives;
819 long n_collection[3] = {n_intersections, n_total_candidates,
822 comm.all_reduce(n_collection, 3, moonolith::MPISum());
826 mfem::out <<
"n_intersections: " << n_collection[0]
827 <<
", n_total_candidates: " << n_collection[1]
828 <<
", n_false_positives: " << n_collection[2] << std::endl;
835static void add_matrix(
const Array<int> &destination_vdofs,
837 const DenseMatrix &elem_mat, moonolith::SparseMatrix<double> &mat_buffer)
839 for (
int i = 0; i < destination_vdofs.
Size(); ++i)
841 long dof_I = destination_vdofs[i];
851 for (
int j = 0; j < source_vdofs.
Size(); ++j)
853 long dof_J = source_vdofs[j];
855 double sign_J = sign_I;
863 mat_buffer.add(dof_I, dof_J, sign_J * elem_mat.
Elem(i, j));
869 const std::vector<moonolith::Integer> &destination_ranges,
872 moonolith::SparseMatrix<double> &mat_buffer)
875 auto && comm = mat_buffer.comm();
877 moonolith::Redistribute<moonolith::SparseMatrix<double>> redist(comm.get());
878 redist.apply(destination_ranges, mat_buffer, moonolith::AddAssign<double>());
880 std::vector<int> I(s_offsets[1] - s_offsets[0] + 1);
883 std::vector<HYPRE_Int> J;
884 std::vector<double> data;
885 J.reserve(mat_buffer.n_local_entries());
886 data.reserve(J.size());
888 for (
auto it = mat_buffer.iter(); it; ++it)
890 I[it.row() - s_offsets[0] + 1]++;
891 J.push_back(it.col());
895 for (
int i = 1; i < I.size(); ++i)
900 return std::make_shared<HypreParMatrix>(
901 comm.get(), s_offsets[1] - s_offsets[0], mat_buffer.rows(),
902 mat_buffer.cols(), &I[0], &J[0], &data[0], s_offsets, m_offsets);
913template <
int Dimensions>
915Assemble(moonolith::Communicator &comm,
916 ParMortarAssembler::Impl &impl,
917 const moonolith::SearchSettings &settings,
const bool verbose)
919 auto &
source = impl.source;
920 auto &destination = impl.destination;
922 auto &integrators = impl.integrators;
923 auto &pmat = impl.coupling_matrix;
926 bool lump_mass =
false;
929 for (
auto i_ptr : integrators)
931 max_q_order = std::max(i_ptr->GetQuadratureOrder(), max_q_order);
934 const int dim =
source->GetMesh()->Dimension();
938 assert(
false &&
"NOT Supported!");
948 double local_element_matrices_sum = 0.0;
950 const auto m_global_n_dofs =
source->GlobalVSize();
951 auto *m_offsets =
source->GetDofOffsets();
953 const auto s_global_n_dofs = destination->GlobalVSize();
954 auto *s_offsets = destination->GetDofOffsets();
956 moonolith::SparseMatrix<double> mat_buffer(comm);
957 mat_buffer.set_size(s_global_n_dofs, m_global_n_dofs);
959 moonolith::SparseMatrix<double> mass_mat_buffer(comm);
960 mass_mat_buffer.set_size(s_global_n_dofs, s_global_n_dofs);
962 std::unique_ptr<BilinearFormIntegrator> mass_integr(impl.new_mass_integrator());
964 auto fun = [&](
const ElementAdapter<Dimensions> &
source,
965 const ElementAdapter<Dimensions> &destination) ->
bool
967 const auto &src =
source.space();
968 const auto &dest = destination.space();
970 const int src_index =
source.element();
971 const int dest_index = destination.element();
973 auto &src_fe = *src.GetFE(src_index);
974 auto &dest_fe = *dest.GetFE(dest_index);
977 *dest.GetElementTransformation(dest_index);
984 const int src_order = src_order_mult * src_fe.GetOrder();
985 const int dest_order = dest_order_mult * dest_fe.GetOrder();
987 int contraction_order = src_order + dest_order;
988 if (impl.assemble_mass_and_coupling_together)
990 contraction_order = std::max(contraction_order, 2 * dest_order);
993 const int order = contraction_order + dest_order_mult * dest_Trans.
OrderW() + max_q_order;
995 cut->SetIntegrationOrder(order);
997 if (cut->BuildQuadrature(src, src_index, dest, dest_index, src_ir,
1002 *src.GetElementTransformation(src_index);
1004 source.get_elements_vdofs(source_vdofs);
1005 destination.get_elements_vdofs(destination_vdofs);
1008 for (
auto i_ptr : integrators)
1012 i_ptr->AssembleElementMatrix(src_fe, src_ir, src_Trans, dest_fe,
1013 dest_ir, dest_Trans, cumulative_elemmat);
1018 i_ptr->AssembleElementMatrix(src_fe, src_ir, src_Trans, dest_fe,
1019 dest_ir, dest_Trans, elemmat);
1020 cumulative_elemmat += elemmat;
1024 local_element_matrices_sum += Sum(cumulative_elemmat);
1025 add_matrix(destination_vdofs, source_vdofs, cumulative_elemmat, mat_buffer);
1027 if (impl.assemble_mass_and_coupling_together)
1029 mass_integr->SetIntRule(&dest_ir);
1030 mass_integr->AssembleElementMatrix(dest_fe, dest_Trans, elemmat);
1034 int n = destination_vdofs.
Size();
1036 for (
int i = 0; i < n; ++i)
1038 double row_sum = 0.;
1039 for (
int j = 0; j < n; ++j)
1041 row_sum += elemmat(i, j);
1045 elemmat(i, i) = row_sum;
1049 add_matrix(destination_vdofs, destination_vdofs, elemmat, mass_mat_buffer);
1060 if (!Assemble<Dimensions>(comm,
source, destination, fun, settings,
1068 double volumes[2] = {local_element_matrices_sum};
1069 comm.all_reduce(volumes, 2, moonolith::MPISum());
1075 mfem::out <<
"sum(B): " << volumes[0] << std::endl;
1079 std::vector<moonolith::Integer> destination_ranges(comm.size() + 1, 0);
1081 std::copy(s_offsets, s_offsets + 2, destination_ranges.begin() + comm.rank());
1082 comm.all_reduce(&destination_ranges[0], destination_ranges.size(),
1083 moonolith::MPIMax());
1091 if (impl.assemble_mass_and_coupling_together)
1094 s_offsets, mass_mat_buffer);
1101 const std::shared_ptr<ParFiniteElementSpace> &
source,
1102 const std::shared_ptr<ParFiniteElementSpace> &destination)
1105 impl_->comm =
source->GetComm();
1107 impl_->destination = destination;
1112 assert(!impl_->integrators.empty() &&
1113 "it must have at least on integrator see class MortarIntegrator");
1115 moonolith::SearchSettings settings;
1121 moonolith::Communicator comm(impl_->comm);
1122 if (impl_->source->GetMesh()->Dimension() == 2)
1124 ok = mfem::Assemble<2>(comm, *impl_, settings,
1128 if (impl_->source->GetMesh()->Dimension() == 3)
1130 ok = mfem::Assemble<3>(comm, *impl_, settings,
1134 pmat = impl_->coupling_matrix;
1148 const bool verbose = impl_->verbose;
1150 if (!impl_->coupling_matrix)
1158 auto &B = *impl_->coupling_matrix;
1159 auto &D = *impl_->mass_matrix;
1161 auto &P_source = *impl_->source->Dof_TrueDof_Matrix();
1162 auto &P_destination = *impl_->destination->Dof_TrueDof_Matrix();
1164 impl_->ensure_solver();
1169 impl_->solver->SetOperator(D);
1173 impl_->solver->SetPrintLevel(3);
1176 Vector P_x_src_fun(B.Width());
1177 P_source.MultTranspose(src_fun, P_x_src_fun);
1179 Vector B_x_src_fun(B.Height());
1182 B.Mult(P_x_src_fun, B_x_src_fun);
1184 Vector R_x_dest_fun(D.Height());
1187 impl_->solver->Mult(B_x_src_fun, R_x_dest_fun);
1189 P_destination.Mult(R_x_dest_fun, dest_fun);
1194 int converged = impl_->solver->GetFinalNorm() < 1e-5;
1195 MPI_Allreduce(MPI_IN_PLACE, &converged, 1, MPI_INT, MPI_MIN, impl_->comm);
1201 using namespace std;
1202 const bool verbose = impl_->verbose;
1203 static const bool dof_transformation =
true;
1205 moonolith::Communicator comm(impl_->comm);
1210 moonolith::root_describe(
1211 "--------------------------------------------------------"
1212 "\nAssembly begin: ",
1216 if (!
Assemble(impl_->coupling_matrix))
1223 moonolith::root_describe(
1225 "--------------------------------------------------------",
1229 if (dof_transformation)
1231 impl_->coupling_matrix.reset(
RAP(impl_->destination->Dof_TrueDof_Matrix(),
1232 impl_->coupling_matrix.get(),
1233 impl_->source->Dof_TrueDof_Matrix()));
1236 auto &B = *impl_->coupling_matrix;
1238 if (!impl_->assemble_mass_and_coupling_together)
1244 impl_->mass_matrix = shared_ptr<HypreParMatrix>(b_form.
ParallelAssemble());
1250 if (verbose && comm.is_root())
1252 mfem::out <<
"P in R^(" << impl_->source->Dof_TrueDof_Matrix()->Height();
1253 mfem::out <<
" x " << impl_->source->Dof_TrueDof_Matrix()->Width() <<
")\n";
1255 << impl_->destination->Dof_TrueDof_Matrix()->Height();
1256 mfem::out <<
" x " << impl_->destination->Dof_TrueDof_Matrix()->Width()
1260 if (dof_transformation && impl_->assemble_mass_and_coupling_together)
1262 impl_->mass_matrix.reset(
RAP(impl_->destination->Dof_TrueDof_Matrix(),
1263 impl_->mass_matrix.get(),
1264 impl_->destination->Dof_TrueDof_Matrix()));
1267 auto &D = *impl_->mass_matrix;
1271 if (verbose && comm.is_root())
1273 mfem::out <<
"--------------------------------------------------------"
1275 mfem::out <<
"B in R^(" << B.GetGlobalNumRows() <<
" x "
1276 << B.GetGlobalNumCols() <<
")" << std::endl;
1277 mfem::out <<
"D in R^(" << D.GetGlobalNumRows() <<
" x "
1278 << D.GetGlobalNumCols() <<
")" << std::endl;
1279 mfem::out <<
"--------------------------------------------------------"
1293 double sum_Dv = Dv.
Sum();
1294 comm.all_reduce(&sum_Dv, 1, MPI_SUM);
1298 mfem::out <<
"sum(D): " << sum_Dv << std::endl;
int Size() const
Return the logical size of the array.
Data type dense matrix using column-major storage.
real_t & Elem(int i, int j) override
Returns reference to a_{ij}.
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
static FiniteElementCollection * New(const char *name)
Factory method: return a newly allocated FiniteElementCollection according to the given name.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
DofTransformation * GetElementVDofs(int i, Array< int > &vdofs) const
Returns indices of degrees of freedom for the i'th element. The returned indices are offsets into an ...
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
int GetNE() const
Returns number of elements in the mesh.
Mesh * GetMesh() const
Returns the mesh.
Abstract class for all finite elements.
Class for an integration rule - an Array of IntegrationPoint.
int GetNE() const
Returns number of elements.
void GetPointMatrix(int i, DenseMatrix &pointmat) const
Abstract parallel finite element space.
HYPRE_BigInt GetGlobalTDofNumber(int ldof) const
Returns the global tdof number of the given local degree of freedom.
Class for parallel grid function.
void Update() override
Transform by the Space UpdateMatrix (e.g., on Mesh change).
bool Apply(const ParGridFunction &src_fun, ParGridFunction &dest_fun)
transfer a function from source to destination. It requires that the Update function is called before
void SetSolver(const std::shared_ptr< IterativeSolver > &solver)
Changes the solver to be used for solving the mass-matrix linear system.
void SetMaxSolverIterations(const int max_solver_iterations)
Control the maximum numbers of conjugate gradients steps for mass matrix inversion.
bool Assemble(std::shared_ptr< HypreParMatrix > &B)
assembles the coupling matrix B. B : source -> destination If u is a coefficient associated with sour...
ParMortarAssembler(const std::shared_ptr< ParFiniteElementSpace > &source, const std::shared_ptr< ParFiniteElementSpace > &destination)
constructs the object with source and destination spaces
void SetAssembleMassAndCouplingTogether(const bool value)
Control if the Mass matrix is computed together with the coupling operator every time.
bool Transfer(const ParGridFunction &src_fun, ParGridFunction &dest_fun)
transfer a function from source to destination. if the transfer is to be performed multiple times use...
void SetVerbose(const bool verbose)
Expose process details with verbose output.
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...
bool Update()
assembles the various components necessary for the transfer. To be called before calling the Apply fu...
real_t Sum() const
Return the sum of the vector entries.
void source(const Vector &x, Vector &f)
int index(int i, int j, int nx, int ny)
void write(std::ostream &os, T value)
Write 'value' to stream.
T read(std::istream &is)
Read a value from the stream and return it.
std::shared_ptr< Cut > NewCut(const int dim)
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
void RAP(const DenseMatrix &A, const DenseMatrix &P, DenseMatrix &RAP)
int order_multiplier(const Geometry::Type type, const int dim)
std::shared_ptr< HypreParMatrix > convert_to_hypre_matrix(const std::vector< moonolith::Integer > &destination_ranges, HYPRE_BigInt *s_offsets, HYPRE_BigInt *m_offsets, moonolith::SparseMatrix< double > &mat_buffer)
real_t p(const Vector &x, real_t t)
void pts(int iphi, int t, real_t x[])