6 #define MatrixManagerFunctionBegin \
8 MOFEM_LOG_CHANNEL("WORLD"); \
9 MOFEM_LOG_CHANNEL("SYNC"); \
10 MOFEM_LOG_FUNCTION(); \
11 MOFEM_LOG_TAG("SYNC", "MatrixManager"); \
12 MOFEM_LOG_TAG("WORLD", "MatrixManager")
36 MPI_Comm comm = PETSC_COMM_WORLD,
51 template <
typename TAG>
54 std::vector<PetscInt> &
i, std::vector<PetscInt> &
j,
55 const bool no_diagonals =
true,
int verb =
QUIET)
const;
58 using AdjByEnt = FieldEntityEntFiniteElementAdjacencyMap_multiIndex::index<
66 template <
typename TAG>
68 ProblemsByName::iterator p_miit,
70 TAG>::type::iterator mit_row,
71 boost::shared_ptr<FieldEntity> mofem_ent_ptr,
72 std::vector<int> &dofs_col_view,
int verb)
const;
80 template <
typename TAG>
82 ProblemsByName::iterator p_miit,
84 TAG>::type::iterator mit_row,
85 boost::shared_ptr<FieldEntity> mofem_ent_ptr,
86 std::vector<int> &dofs_col_view,
int verb)
const {
90 BitRefLevel prb_mask = p_miit->getBitRefLevelMask();
94 dofs_col_view.clear();
96 mofem_ent_ptr->getLocalUniqueId());
97 r.first !=
r.second; ++
r.first) {
99 if (
r.first->byWhat &
BYROW) {
101 if ((
r.first->entFePtr->getId() & p_miit->getBitFEId()).none()) {
106 const BitRefLevel &fe_bit =
r.first->entFePtr->getBitRefLevel();
108 if ((fe_bit & prb_bit).any() && (fe_bit & prb_mask) == fe_bit) {
110 auto check_block = [&empty_field_blocks](
auto &r_if,
auto &col_id) {
111 for (
auto &b : empty_field_blocks) {
112 if ((b.first & r_if).any() && (b.second & col_id).any()) {
119 for (
auto &it :
r.first->entFePtr->getColFieldEnts()) {
120 if (
auto e = it.lock()) {
122 if (check_block((*mit_row)->getId(), e->getId())) {
124 if (
auto cache = e->entityCacheColDofs.lock()) {
125 const auto lo = cache->loHi[0];
126 const auto hi = cache->loHi[1];
127 for (
auto vit = lo; vit != hi; ++vit) {
129 const int idx = TAG::get_index(vit);
130 if (PetscLikely(idx >= 0))
131 dofs_col_view.push_back(idx);
134 const DofIdx nb_dofs_col = p_miit->getNbDofsCol();
135 if (PetscUnlikely(idx >= nb_dofs_col)) {
137 <<
"Problem with dof: " << std::endl
138 <<
"Rank " <<
rAnk <<
" : " << *(*vit);
141 "Index of dof larger than number of DOFs in column");
159 template <
typename TAG>
161 ProblemsByName::iterator p_miit,
const MatType
type,
162 std::vector<PetscInt> &
i, std::vector<PetscInt> &
j,
const bool no_diagonals,
168 auto cache = boost::make_shared<std::vector<EntityCacheNumeredDofs>>(
174 const auto uid = (*it)->getLocalUniqueId();
176 for (
auto lo =
r.first; lo !=
r.second; ++lo) {
178 if ((lo->getBitFEId() & p_miit->getBitFEId()).any()) {
180 const BitRefLevel &prb_bit = p_miit->getBitRefLevel();
181 const BitRefLevel &prb_mask = p_miit->getBitRefLevelMask();
182 const BitRefLevel &fe_bit = lo->entFePtr->getBitRefLevel();
185 if ((fe_bit & prb_mask) != fe_bit)
187 if ((fe_bit & prb_bit).none())
190 auto dit = p_miit->numeredColDofsPtr->lower_bound(uid);
192 decltype(dit) hi_dit;
193 if (dit != p_miit->numeredColDofsPtr->end())
194 hi_dit = p_miit->numeredColDofsPtr->upper_bound(
199 (*it)->entityCacheColDofs =
200 boost::shared_ptr<EntityCacheNumeredDofs>(cache, &((*cache)[idx]));
201 (*cache)[idx].loHi = {dit, hi_dit};
208 using NumeredDofEntitysByIdx =
213 const NumeredDofEntitysByIdx &dofs_row_by_idx =
214 p_miit->numeredRowDofsPtr->get<TAG>();
215 int nb_dofs_row = p_miit->getNbDofsRow();
216 if (nb_dofs_row == 0) {
218 p_miit->getName().c_str());
222 std::map<int, std::vector<int>> adjacent_dofs_on_other_parts;
229 TAG>::type::iterator miit_row,
232 if (TAG::IamNotPartitioned) {
237 CHKERR PetscLayoutSetBlockSize(layout, 1);
238 CHKERR PetscLayoutSetSize(layout, nb_dofs_row);
239 CHKERR PetscLayoutSetUp(layout);
240 PetscInt rstart, rend;
241 CHKERR PetscLayoutGetRange(layout, &rstart, &rend);
242 CHKERR PetscLayoutDestroy(&layout);
246 <<
"row lower " << rstart <<
" row upper " << rend;
250 miit_row = dofs_row_by_idx.lower_bound(rstart);
251 hi_miit_row = dofs_row_by_idx.lower_bound(rend);
252 if (std::distance(miit_row, hi_miit_row) != rend - rstart) {
255 "data inconsistency, std::distance(miit_row,hi_miit_row) != rend - "
256 "rstart (%d != %d - %d = %d) ",
257 std::distance(miit_row, hi_miit_row), rend, rstart, rend - rstart);
267 std::vector<std::vector<int>> dofs_vec(
sIze);
269 boost::shared_ptr<FieldEntity> mofem_ent_ptr;
270 std::vector<int> dofs_col_view;
273 TAG>::type::iterator mit_row,
276 mit_row = dofs_row_by_idx.begin();
277 hi_mit_row = dofs_row_by_idx.end();
278 for (; mit_row != hi_mit_row; mit_row++) {
286 unsigned char pstatus = (*mit_row)->getPStatus();
287 if ((pstatus & PSTATUS_NOT_OWNED) &&
288 (pstatus & (PSTATUS_SHARED | PSTATUS_MULTISHARED))) {
290 bool get_adj_col =
true;
292 if (mofem_ent_ptr->getLocalUniqueId() ==
293 (*mit_row)->getFieldEntityPtr()->getLocalUniqueId()) {
300 mofem_ent_ptr = (*mit_row)->getFieldEntityPtr();
301 CHKERR getEntityAdjacencies<TAG>(p_miit, mit_row, mofem_ent_ptr,
302 dofs_col_view, verb);
305 std::sort(dofs_col_view.begin(), dofs_col_view.end());
306 std::vector<int>::iterator new_end =
307 std::unique(dofs_col_view.begin(), dofs_col_view.end());
308 int new_size = std::distance(dofs_col_view.begin(), new_end);
309 dofs_col_view.resize(new_size);
313 int owner = (*mit_row)->getOwnerProc();
314 dofs_vec[owner].emplace_back(TAG::get_index(mit_row));
315 dofs_vec[owner].emplace_back(
316 dofs_col_view.size());
318 dofs_vec[owner].insert(dofs_vec[owner].end(), dofs_col_view.begin(),
319 dofs_col_view.end());
325 std::vector<int> dofs_vec_length(
sIze);
326 for (
int proc = 0; proc <
sIze; proc++) {
328 if (!dofs_vec[proc].empty()) {
330 dofs_vec_length[proc] = dofs_vec[proc].size();
335 dofs_vec_length[proc] = 0;
339 std::vector<MPI_Status> status(
sIze);
343 CHKERR PetscGatherNumberOfMessages(comm, NULL, &dofs_vec_length[0],
350 CHKERR PetscGatherMessageLengths(comm, nsends, nrecvs, &dofs_vec_length[0],
355 CHKERR PetscCommGetNewTag(comm, &tag);
360 MPI_Request *r_waits;
365 CHKERR PetscPostIrecvInt(comm, tag, nrecvs, onodes, olengths, &rbuf,
368 MPI_Request *s_waits;
369 CHKERR PetscMalloc1(nsends, &s_waits);
372 for (
int proc = 0, kk = 0; proc <
sIze; proc++) {
373 if (!dofs_vec_length[proc])
375 CHKERR MPI_Isend(&(dofs_vec[proc])[0],
376 dofs_vec_length[proc],
378 tag, comm, s_waits + kk);
384 CHKERR MPI_Waitall(nrecvs, r_waits, &status[0]);
388 CHKERR MPI_Waitall(nsends, s_waits, &status[0]);
391 for (
int kk = 0; kk < nrecvs; kk++) {
393 int len = olengths[kk];
394 int *data_from_proc = rbuf[kk];
396 for (
int ii = 0; ii < len;) {
398 int row_idx = data_from_proc[ii++];
399 int nb_adj_dofs = data_from_proc[ii++];
403 DofByGlobalPetscIndex::iterator dit;
409 "dof %d can not be found in problem", row_idx);
413 for (
int jj = 0; jj < nb_adj_dofs; jj++) {
414 adjacent_dofs_on_other_parts[row_idx].push_back(data_from_proc[ii++]);
420 CHKERR PetscFree(s_waits);
421 CHKERR PetscFree(rbuf[0]);
423 CHKERR PetscFree(r_waits);
425 CHKERR PetscFree(olengths);
427 miit_row = dofs_row_by_idx.begin();
428 hi_miit_row = dofs_row_by_idx.end();
430 CHKERR PetscCommDestroy(&comm);
433 boost::shared_ptr<FieldEntity> mofem_ent_ptr;
434 int row_last_evaluated_idx = -1;
436 std::vector<int> dofs_vec;
437 std::vector<int> dofs_col_view;
440 int nb_loc_row_from_iterators = 0;
441 unsigned int rows_to_fill = p_miit->getNbLocalDofsRow();
442 i.reserve(rows_to_fill + 1);
443 for (; miit_row != hi_miit_row; miit_row++) {
445 if (!TAG::IamNotPartitioned) {
446 if (
static_cast<int>((*miit_row)->getPart()) !=
rAnk)
450 nb_loc_row_from_iterators++;
453 i.push_back(
j.size());
460 : (mofem_ent_ptr->getLocalUniqueId() !=
461 (*miit_row)->getFieldEntityPtr()->getLocalUniqueId())) {
464 mofem_ent_ptr = (*miit_row)->getFieldEntityPtr();
465 CHKERR getEntityAdjacencies<TAG>(p_miit, miit_row, mofem_ent_ptr,
466 dofs_col_view, verb);
467 row_last_evaluated_idx = TAG::get_index(miit_row);
471 dofs_vec.insert(dofs_vec.end(), dofs_col_view.begin(),
472 dofs_col_view.end());
474 unsigned char pstatus = (*miit_row)->getPStatus();
476 std::map<int, std::vector<int>>::iterator mit;
477 mit = adjacent_dofs_on_other_parts.find(row_last_evaluated_idx);
478 if (mit == adjacent_dofs_on_other_parts.end()) {
486 dofs_vec.insert(dofs_vec.end(), mit->second.begin(),
492 sort(dofs_vec.begin(), dofs_vec.end());
493 std::vector<int>::iterator new_end =
494 unique(dofs_vec.begin(), dofs_vec.end());
495 int new_size = std::distance(dofs_vec.begin(), new_end);
496 dofs_vec.resize(new_size);
500 if (
j.capacity() <
j.size() + dofs_vec.size()) {
503 unsigned int nb_nonzero =
j.size() + dofs_vec.size();
504 unsigned int average_row_fill = nb_nonzero /
i.size() + 1;
505 j.reserve(rows_to_fill * average_row_fill);
508 auto hi_diit = dofs_vec.end();
509 for (
auto diit = dofs_vec.begin(); diit != hi_diit; diit++) {
512 if (*diit == TAG::get_index(miit_row)) {
521 i.push_back(
j.size());
523 if (strcmp(
type, MATMPIADJ) == 0) {
526 if (
i.size() - 1 != (
unsigned int)nb_loc_row_from_iterators) {
529 "Number of rows from iterator is different than size of rows in "
531 "matrix (unsigned int)nb_local_dofs_row != i.size() - 1, i.e. %d != "
533 (
unsigned int)nb_loc_row_from_iterators,
i.size() - 1);
536 }
else if (strcmp(
type, MATMPIAIJ) == 0) {
539 if (
i.size() - 1 != (
unsigned int)nb_loc_row_from_iterators) {
542 "Number of rows from iterator is different than size of rows in "
544 "matrix (unsigned int)nb_local_dofs_row != i.size() - 1, i.e. %d != "
546 (
unsigned int)nb_loc_row_from_iterators,
i.size() - 1);
548 PetscInt nb_local_dofs_row = p_miit->getNbLocalDofsRow();
549 if ((
unsigned int)nb_local_dofs_row !=
i.size() - 1) {
552 "Number of rows is different than size of rows in compressed row "
553 "matrix (unsigned int)nb_local_dofs_row != i.size() - 1, i.e. %d != "
555 (
unsigned int)nb_local_dofs_row,
i.size() - 1);
558 }
else if (strcmp(
type, MATAIJ) == 0) {
561 if (
i.size() - 1 != (
unsigned int)nb_loc_row_from_iterators) {
564 "Number of rows form iterator is different than size of rows in "
566 "matrix (unsigned int)nb_local_dofs_row != i.size() - 1, i.e. %d != "
568 (
unsigned int)nb_loc_row_from_iterators,
i.size() - 1);
570 PetscInt nb_local_dofs_row = p_miit->getNbLocalDofsRow();
571 if ((
unsigned int)nb_local_dofs_row !=
i.size() - 1) {
574 "Number of rows is different than size of rows in compressed row "
575 "matrix (unsigned int)nb_local_dofs_row != i.size() - 1, i.e. %d != "
577 (
unsigned int)nb_local_dofs_row,
i.size() - 1);
580 }
else if (strcmp(
type, MATAIJCUSPARSE) == 0) {
582 if (
i.size() - 1 != (
unsigned int)nb_loc_row_from_iterators) {
583 SETERRQ(
get_comm(), PETSC_ERR_ARG_SIZ,
"data inconsistency");
585 PetscInt nb_local_dofs_row = p_miit->getNbLocalDofsRow();
586 if ((
unsigned int)nb_local_dofs_row !=
i.size() - 1) {
587 SETERRQ(
get_comm(), PETSC_ERR_ARG_SIZ,
"data inconsistency");
592 SETERRQ(
get_comm(), PETSC_ERR_ARG_NULL,
"not implemented");
607 : cOre(const_cast<
MoFEM::
Core &>(core)) {
609 PetscLogEventRegister(
"MatMngCrtMPIAIJWthArr", 0,
611 PetscLogEventRegister(
"MatMngCrtMPIAdjWithArr", 0,
613 PetscLogEventRegister(
"MatMngCrtMPIAIJCUSPARSEWthArr", 0,
615 PetscLogEventRegister(
"MatMngCrtSeqAIJCUSPARSEWthArrs", 0,
617 PetscLogEventRegister(
"MatMngCrtSeqAIJWthArrs", 0,
619 PetscLogEventRegister(
"MatMngCrtCheckMPIAIJWthArrFillIn", 0,
625 const std::string name, Mat *Aij,
int verb) {
635 auto p_miit = prb.find(name);
636 if (p_miit == prb.end()) {
638 "problem < %s > is not found (top tip: check spelling)",
642 std::vector<int> i_vec, j_vec;
643 j_vec.reserve(10000);
645 p_miit, MATMPIAIJ, i_vec, j_vec,
false, verb);
647 int nb_row_dofs = p_miit->getNbDofsRow();
648 int nb_col_dofs = p_miit->getNbDofsCol();
649 int nb_local_dofs_row = p_miit->getNbLocalDofsRow();
650 int nb_local_dofs_col = p_miit->getNbLocalDofsCol();
652 CHKERR ::MatCreateMPIAIJWithArrays(
653 m_field.
get_comm(), nb_local_dofs_row, nb_local_dofs_col, nb_row_dofs,
654 nb_col_dofs, &*i_vec.begin(), &*j_vec.begin(), PETSC_NULL, Aij);
662 MatrixManager::createMPIAIJCUSPARSEWithArrays<PetscGlobalIdx_mi_tag>(
663 const std::string name, Mat *Aij,
int verb) {
673 auto p_miit = prb.find(name);
674 if (p_miit == prb.end()) {
676 "problem < %s > is not found (top tip: check spelling)",
680 std::vector<int> i_vec, j_vec;
681 j_vec.reserve(10000);
683 p_miit, MATAIJCUSPARSE, i_vec, j_vec,
false, verb);
685 int nb_local_dofs_row = p_miit->getNbLocalDofsRow();
686 int nb_local_dofs_col = p_miit->getNbLocalDofsCol();
688 auto get_layout = [&]() {
689 int start_ranges, end_ranges;
692 CHKERR PetscLayoutSetBlockSize(layout, 1);
693 CHKERR PetscLayoutSetLocalSize(layout, nb_local_dofs_col);
694 CHKERR PetscLayoutSetUp(layout);
695 CHKERR PetscLayoutGetRange(layout, &start_ranges, &end_ranges);
696 CHKERR PetscLayoutDestroy(&layout);
697 return std::make_pair(start_ranges, end_ranges);
700 auto get_nnz = [&](
auto &d_nnz,
auto &o_nnz) {
702 auto layout = get_layout();
704 for (
int i = 0;
i != nb_local_dofs_row; ++
i) {
705 for (;
j != i_vec[
i + 1]; ++
j) {
706 if (j_vec[
j] < layout.second && j_vec[
j] >= layout.first)
715 std::vector<int> d_nnz(nb_local_dofs_row, 0), o_nnz(nb_local_dofs_row, 0);
716 CHKERR get_nnz(d_nnz, o_nnz);
718 #ifdef PETSC_HAVE_CUDA
719 CHKERR ::MatCreateAIJCUSPARSE(m_field.
get_comm(), nb_local_dofs_row,
720 nb_local_dofs_col, nb_row_dofs, nb_col_dofs, 0,
721 &*d_nnz.begin(), 0, &*o_nnz.begin(), Aij);
724 "Error: To use this matrix type compile PETSc with CUDA.");
734 MatrixManager::createSeqAIJCUSPARSEWithArrays<PetscLocalIdx_mi_tag>(
735 const std::string name, Mat *Aij,
int verb) {
738 #ifdef PETSC_HAVE_CUDA
743 "Not implemented type of matrix yet, try MPI version (aijcusparse)");
751 MatrixManager::createMPIAIJ<PetscGlobalIdx_mi_tag>(
const std::string name,
752 Mat *Aij,
int verb) {
761 auto p_miit = prb.find(name);
762 if (p_miit == prb.end()) {
764 "problem < %s > is not found (top tip: check spelling)",
768 std::vector<int> i_vec, j_vec;
769 j_vec.reserve(10000);
771 p_miit, MATMPIAIJ, i_vec, j_vec,
false, verb);
773 int nb_row_dofs = p_miit->getNbDofsRow();
774 int nb_col_dofs = p_miit->getNbDofsCol();
775 int nb_local_dofs_row = p_miit->getNbLocalDofsRow();
776 int nb_local_dofs_col = p_miit->getNbLocalDofsCol();
778 auto get_layout = [&]() {
779 int start_ranges, end_ranges;
782 CHKERR PetscLayoutSetBlockSize(layout, 1);
783 CHKERR PetscLayoutSetLocalSize(layout, nb_local_dofs_col);
784 CHKERR PetscLayoutSetUp(layout);
785 CHKERR PetscLayoutGetRange(layout, &start_ranges, &end_ranges);
786 CHKERR PetscLayoutDestroy(&layout);
787 return std::make_pair(start_ranges, end_ranges);
790 auto get_nnz = [&](
auto &d_nnz,
auto &o_nnz) {
792 auto layout = get_layout();
794 for (
int i = 0;
i != nb_local_dofs_row; ++
i) {
795 for (;
j != i_vec[
i + 1]; ++
j) {
796 if (j_vec[
j] < layout.second && j_vec[
j] >= layout.first)
805 std::vector<int> d_nnz(nb_local_dofs_row, 0), o_nnz(nb_local_dofs_row, 0);
806 CHKERR get_nnz(d_nnz, o_nnz);
809 CHKERR MatSetSizes(*Aij, nb_local_dofs_row, nb_local_dofs_col, nb_row_dofs,
811 CHKERR MatSetType(*Aij, MATMPIAIJ);
812 CHKERR MatMPIAIJSetPreallocation(*Aij, 0, &*d_nnz.begin(), 0,
821 MatrixManager::createMPIAdjWithArrays<Idx_mi_tag>(
const std::string name,
822 Mat *Adj,
int verb) {
831 auto p_miit = prb.find(name);
832 if (p_miit == prb.end()) {
834 "problem < %s > is not found (top tip: check spelling)",
838 std::vector<int> i_vec, j_vec;
839 j_vec.reserve(10000);
843 CHKERR PetscMalloc(i_vec.size() *
sizeof(
int), &_i);
844 CHKERR PetscMalloc(j_vec.size() *
sizeof(
int), &_j);
845 copy(i_vec.begin(), i_vec.end(), _i);
846 copy(j_vec.begin(), j_vec.end(), _j);
848 int nb_col_dofs = p_miit->getNbDofsCol();
849 CHKERR MatCreateMPIAdj(m_field.
get_comm(), i_vec.size() - 1, nb_col_dofs, _i,
850 _j, PETSC_NULL, Adj);
851 CHKERR MatSetOption(*Adj, MAT_STRUCTURALLY_SYMMETRIC, PETSC_TRUE);
859 const std::string name, Mat *Aij,
int verb) {
868 auto p_miit = prb.find(name);
869 if (p_miit == prb.end()) {
871 "problem < %s > is not found (top tip: check spelling)",
875 std::vector<int> i_vec, j_vec;
876 j_vec.reserve(10000);
880 int nb_local_dofs_row = p_miit->getNbLocalDofsRow();
881 int nb_local_dofs_col = p_miit->getNbLocalDofsCol();
884 CHKERR PetscMalloc(j_vec.size() *
sizeof(
double), &_a);
887 CHKERR ::MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, nb_local_dofs_row,
888 nb_local_dofs_col, &*i_vec.begin(),
889 &*j_vec.begin(), _a, &tmpMat);
890 CHKERR MatDuplicate(tmpMat, MAT_SHARE_NONZERO_PATTERN, Aij);
891 CHKERR MatDestroy(&tmpMat);
900 int row_print,
int col_print,
907 struct TestMatrixFillIn :
public FEMethod {
912 int rowPrint, colPrint;
914 TestMatrixFillIn(
CoreInterface *m_field_ptr, Mat
a,
int row_print,
916 : mFieldPtr(m_field_ptr),
A(
a), rowPrint(row_print),
917 colPrint(col_print){};
927 if (refinedFiniteElementsPtr->find(
928 numeredEntFiniteElementPtr->getEnt()) ==
929 refinedFiniteElementsPtr->end()) {
931 "data inconsistency");
934 auto row_dofs = getRowDofsPtr();
935 auto col_dofs = getColDofsPtr();
937 for (
auto cit = col_dofs->begin(); cit != col_dofs->end(); cit++) {
939 if (refinedEntitiesPtr->find((*cit)->getEnt()) ==
940 refinedEntitiesPtr->end()) {
942 "data inconsistency");
944 if (!(*cit)->getActive()) {
946 "data inconsistency");
949 FieldEntityEntFiniteElementAdjacencyMap_multiIndex::index<
952 boost::make_tuple((*cit)->getFieldEntityPtr()->getLocalUniqueId(),
953 numeredEntFiniteElementPtr->getLocalUniqueId()));
954 if (ait == adjacenciesPtr->end()) {
956 "adjacencies data inconsistency");
958 UId uid = ait->getEntUniqueId();
959 if (entitiesPtr->find(uid) == entitiesPtr->end()) {
961 "data inconsistency");
963 if (dofsPtr->find((*cit)->getLocalUniqueId()) == dofsPtr->end()) {
965 "data inconsistency");
969 if ((*cit)->getEntType() != MBVERTEX) {
972 col_dofs->get<
Ent_mi_tag>().equal_range((*cit)->getEnt());
973 int nb_dofs_on_ent = std::distance(range.first, range.second);
975 int max_order = (*cit)->getMaxOrder();
976 if ((*cit)->getNbOfCoeffs() * (*cit)->getOrderNbDofs(max_order) !=
984 <<
"Warning: Number of Dofs in Col different than number "
985 "of dofs for given entity order "
986 << (*cit)->getNbOfCoeffs() * (*cit)->getOrderNbDofs(max_order)
987 <<
" " << nb_dofs_on_ent;
992 for (
auto rit = row_dofs->begin(); rit != row_dofs->end(); rit++) {
994 if (refinedEntitiesPtr->find((*rit)->getEnt()) ==
995 refinedEntitiesPtr->end()) {
997 "data inconsistency");
999 if (!(*rit)->getActive()) {
1001 "data inconsistency");
1004 FieldEntityEntFiniteElementAdjacencyMap_multiIndex::index<
1007 boost::make_tuple((*rit)->getFieldEntityPtr()->getLocalUniqueId(),
1008 numeredEntFiniteElementPtr->getLocalUniqueId()));
1009 if (ait == adjacenciesPtr->end()) {
1011 MOFEM_LOG(
"SELF", Sev::error) << *(*rit);
1012 MOFEM_LOG(
"SELF", Sev::error) << *(*rit);
1013 MOFEM_LOG(
"SELF", Sev::error) << *numeredEntFiniteElementPtr;
1014 MOFEM_LOG(
"SELF", Sev::error) <<
"dof: " << (*rit)->getBitRefLevel();
1016 <<
"fe: " << numeredEntFiniteElementPtr->getBitRefLevel();
1018 <<
"problem: " << problemPtr->getBitRefLevel();
1020 <<
"problem mask: " << problemPtr->getBitRefLevelMask();
1022 "adjacencies data inconsistency");
1024 UId uid = ait->getEntUniqueId();
1025 if (entitiesPtr->find(uid) == entitiesPtr->end()) {
1027 "data inconsistency");
1029 if (dofsPtr->find((*rit)->getLocalUniqueId()) == dofsPtr->end()) {
1031 "data inconsistency");
1034 int row = (*rit)->getPetscGlobalDofIdx();
1036 auto col_dofs = getColDofsPtr();
1037 for (
auto cit = col_dofs->begin(); cit != col_dofs->end(); cit++) {
1039 int col = (*cit)->getPetscGlobalDofIdx();
1041 if (row == rowPrint && col == colPrint) {
1042 MOFEM_LOG(
"SELF", Sev::noisy) <<
"fe:\n"
1043 << *numeredEntFiniteElementPtr;
1044 MOFEM_LOG(
"SELF", Sev::noisy) <<
"row:\n" << *(*rit);
1045 MOFEM_LOG(
"SELF", Sev::noisy) <<
"col:\n" << *(*cit);
1048 << numeredEntFiniteElementPtr->getBitRefLevel();
1049 MOFEM_LOG(
"SELF", Sev::noisy) <<
"row:\n"
1050 << (*rit)->getBitRefLevel();
1051 MOFEM_LOG(
"SELF", Sev::noisy) <<
"col:\n"
1052 << (*cit)->getBitRefLevel();
1055 CHKERR MatSetValue(
A, row, col, 1, INSERT_VALUES);
1058 if ((*rit)->getEntType() != MBVERTEX) {
1061 row_dofs->get<
Ent_mi_tag>().equal_range((*rit)->getEnt());
1062 int nb_dofs_on_ent = std::distance(range.first, range.second);
1064 int max_order = (*rit)->getMaxOrder();
1065 if ((*rit)->getNbOfCoeffs() * (*rit)->getOrderNbDofs(max_order) !=
1073 <<
"Warning: Number of Dofs in Row different than number "
1074 "of dofs for given entity order "
1075 << (*rit)->getNbOfCoeffs() * (*rit)->getOrderNbDofs(max_order)
1076 <<
" " << nb_dofs_on_ent;
1088 CHKERR MatAssemblyBegin(
A, MAT_FLUSH_ASSEMBLY);
1089 CHKERR MatAssemblyEnd(
A, MAT_FLUSH_ASSEMBLY);
1096 CHKERR MatSetOption(
A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);
1099 MatView(
A, PETSC_VIEWER_STDOUT_WORLD);
1102 if (verb >=
NOISY) {
1103 MatView(
A, PETSC_VIEWER_DRAW_WORLD);
1108 TestMatrixFillIn method(&m_field,
A, row_print, col_print);
1113 auto p_miit = prb_set.find(problem_name);
1114 if (p_miit == prb_set.end())
1116 "problem < %s > not found (top tip: check spelling)",
1117 problem_name.c_str());
1118 MOFEM_LOG_C(
"WORLD", Sev::inform,
"check problem < %s >",
1119 problem_name.c_str());
1123 for (
auto &fe : *fe_ptr) {
1124 MOFEM_LOG_C(
"WORLD", Sev::verbose,
"\tcheck element %s",
1125 fe->getName().c_str());
1131 CHKERR MatAssemblyBegin(
A, MAT_FINAL_ASSEMBLY);
1132 CHKERR MatAssemblyEnd(
A, MAT_FINAL_ASSEMBLY);
1141 MatrixManager::checkMPIAIJWithArraysMatrixFillIn<PetscGlobalIdx_mi_tag>(
1142 const std::string problem_name,
int row_print,
int col_print,
int verb) {
1146 CHKERR createMPIAIJWithArrays<PetscGlobalIdx_mi_tag>(problem_name,
A, verb);
1147 CHKERR MatSetOption(
A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);
1154 const std::string problem_name,
int row_print,
int col_print,
int verb) {
1158 CHKERR createMPIAIJ<PetscGlobalIdx_mi_tag>(problem_name,
A, verb);
1159 CHKERR MatSetOption(
A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);
1174 "problem < %s > is not found (top tip: check spelling)",
1175 problem_name.c_str());
1178 auto nb_rows = p_miit->getNbDofsRow();
1179 auto nb_cols = p_miit->getNbDofsCol();
1180 auto nb_loc_rows = p_miit->getNbLocalDofsRow();
1181 auto nb_loc_cols = p_miit->getNbLocalDofsCol();
1183 auto row_ptr = p_miit->getNumeredRowDofsPtr();
1184 auto col_ptr = p_miit->getNumeredColDofsPtr();
1187 for (
auto &
c : *col_ptr) {
1188 fields_ids |=
c->getId();
1191 std::vector<int> fields_bit_numbers;
1192 for (
auto &
f : *fields) {
1193 if ((fields_ids &
f->getId()).any()) {
1194 fields_bit_numbers.push_back(
f->getBitNumber());
1202 auto get_adj = [&](
auto ent,
auto dim) {
1203 if (prev_ent == ent && prev_dim == dim) {
1208 CHKERR m_field.
get_moab().get_adjacencies(&ent, 1, dim + 1,
false,
1210 CHKERR m_field.
get_moab().get_adjacencies(bridge, dim,
false, adj,
1211 moab::Interface::UNION);
1218 int prev_bit_number = -1;
1223 std::pair<IT, IT> pair_lo_hi;
1224 auto get_col_it = [&](
auto bit_number,
auto first_ent,
auto second_ent) {
1225 if (bit_number == prev_bit_number && first_ent == prev_first_ent &&
1226 second_ent == prev_second_ent) {
1233 pair_lo_hi = std::make_pair(lo_it, hi_it);
1234 prev_bit_number = bit_number;
1235 prev_first_ent = first_ent;
1236 prev_second_ent = second_ent;
1241 auto create_ghost_vec = [&]() {
1246 CHKERR VecGhostUpdateBegin(
v, INSERT_VALUES, SCATTER_FORWARD);
1247 CHKERR VecGhostUpdateEnd(
v, INSERT_VALUES, SCATTER_FORWARD);
1251 auto v_o_nnz = create_ghost_vec();
1252 auto v_d_nnz = create_ghost_vec();
1256 CHKERR VecGetArray(v_o_nnz, &o_nnz_real);
1258 CHKERR VecGetArray(v_d_nnz, &d_nnz_real);
1260 for (
auto r = row_ptr->begin();
r != row_ptr->end(); ++
r) {
1262 auto row_loc_idx = (*r)->getPetscLocalDofIdx();
1263 if (row_loc_idx < 0)
1266 auto ent = (*r)->getEnt();
1268 auto adj = get_adj(ent, dim);
1270 for (
auto p = adj.pair_begin(); p != adj.pair_end(); ++p) {
1271 auto first_ent = p->first;
1272 auto second_ent = p->second;
1274 for (
auto bit_number : fields_bit_numbers) {
1276 auto [lo_it, hi_it] = get_col_it(bit_number, first_ent, second_ent);
1278 for (; lo_it != hi_it; ++lo_it) {
1279 auto col_loc_idx = (*lo_it)->getPetscLocalDofIdx();
1280 if (col_loc_idx < 0)
1285 (*lo_it)->getOwnerProc() == (*r)->getOwnerProc()
1288 d_nnz_real[row_loc_idx] += 1;
1290 o_nnz_real[row_loc_idx] += 1;
1297 CHKERR VecRestoreArray(v_o_nnz, &o_nnz_real);
1298 CHKERR VecRestoreArray(v_d_nnz, &d_nnz_real);
1300 auto update_vec = [&](
auto v) {
1302 CHKERR VecGhostUpdateBegin(
v, ADD_VALUES, SCATTER_REVERSE);
1303 CHKERR VecGhostUpdateEnd(
v, ADD_VALUES, SCATTER_REVERSE);
1309 CHKERR update_vec(v_o_nnz);
1310 CHKERR update_vec(v_d_nnz);
1315 CHKERR VecGetArray(v_d_nnz, &d_nnz_real);
1316 CHKERR VecGetArray(v_o_nnz, &o_nnz_real);
1318 std::vector<int> d_nnz(nb_loc_rows, 0);
1319 std::vector<int> o_nnz(nb_loc_rows, 0);
1320 for (
auto r = row_ptr->begin();
r != row_ptr->end(); ++
r) {
1322 auto row_loc_idx = (*r)->getPetscLocalDofIdx();
1326 row_loc_idx >= 0 && row_loc_idx < nb_loc_rows
1329 auto row_loc_idx = (*r)->getPetscLocalDofIdx();
1330 d_nz += o_nnz_real[row_loc_idx];
1331 d_nnz[row_loc_idx] = d_nnz_real[row_loc_idx];
1332 o_nz += o_nnz_real[row_loc_idx];
1333 o_nnz[row_loc_idx] = o_nnz_real[row_loc_idx];
1338 CHKERR VecRestoreArray(v_o_nnz, &o_nnz_real);
1339 CHKERR VecRestoreArray(v_d_nnz, &d_nnz_real);
1341 if (verb >=
QUIET) {
1343 <<
"Hybrid L2 matrix d_nz: " << d_nz <<
" o_nz: " << o_nz;
1348 MOFEM_LOG(
"SYNC", Sev::noisy) <<
"Hybrid L2 matrix";
1350 for (
auto &
d : d_nnz) {
1351 MOFEM_LOG(
"SYNC", Sev::noisy) << idx <<
": " <<
d;
1358 CHKERR MatCreateAIJ(m_field.
get_comm(), nb_loc_rows, nb_loc_cols, nb_rows,
1359 nb_cols, 0, &*d_nnz.begin(), 0, &*o_nnz.begin(), &a_raw);
1360 CHKERR MatSetOption(a_raw, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);