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 (%ld != %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();
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();
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");
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);
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);