45 std::vector<std::string> fields_name,
46 std::vector<boost::shared_ptr<Range>> field_ents,
49 std::vector<bool> sym_schur,
bool symm_op =
true,
50 boost::shared_ptr<BlockStructure> diag_blocks =
nullptr);
66 std::vector<std::string> fields_name,
67 std::vector<boost::shared_ptr<Range>> field_ents,
70 std::vector<bool> sym_schur, std::vector<double> diag_eps,
72 boost::shared_ptr<BlockStructure> diag_blocks =
nullptr);
122 struct SchurElemMats :
public boost::enable_shared_from_this<SchurElemMats> {
161 member<SchurElemMats, const UId, &SchurElemMats::uidRow>,
162 member<SchurElemMats, const UId, &SchurElemMats::uidCol>
171 static boost::ptr_vector<MatrixDouble>
locMats;
234 const_mem_fun<Indexes, int, &Indexes::getLocRow>,
235 const_mem_fun<Indexes, int, &Indexes::getLocCol>,
236 const_mem_fun<Indexes, int, &Indexes::getNbRows>,
237 const_mem_fun<Indexes, int, &Indexes::getNbCols>>
245 const_mem_fun<Indexes, int, &Indexes::getRow>,
246 const_mem_fun<Indexes, int, &Indexes::getCol>,
247 const_mem_fun<Indexes, int, &Indexes::getNbRows>,
248 const_mem_fun<Indexes, int, &Indexes::getNbCols>>
254 const_mem_fun<Indexes, int, &Indexes::rowShift>
260 const_mem_fun<Indexes, int, &Indexes::colShift>
285 std::pair<std::vector<const Indexes *>, std::vector<int>>;
315 : iDX(idx), uidRow(uid_row), uidCol(uid_col) {}
329 auto get_row_indices = [&]() ->
const VectorInt & {
331 if (
auto stored_data_ptr =
333 return stored_data_ptr->entityIndices;
339 const auto &row_ind = get_row_indices();
342 const auto nb_rows = row_ind.size();
343 const auto nb_cols = col_ind.size();
346 if (mat.size1() != nb_rows) {
348 "Wrong mat size %d != %d", mat.size1(), nb_rows);
350 if (mat.size2() != nb_cols) {
352 "Wrong mat size %d != %d", mat.size2(), nb_cols);
357 auto get_uid = [](
auto &data) {
358 if (data.getFieldEntities().size() == 1) {
360 return data.getFieldEntities()[0]->getLocalUniqueId();
369 auto &uid0 = data.getFieldEntities()[0]->getLocalUniqueId();
375 for (
auto i = 1;
i < data.getFieldEntities().size(); ++
i) {
382 data.getFieldEntities()[
i]->getLocalUniqueId())
396 auto uid_row = get_uid(row_data);
397 auto uid_col = get_uid(col_data);
401 .find(boost::make_tuple(uid_row, uid_col));
433 auto asmb = [&](
auto &sm) {
434 sm.resize(nb_rows, nb_cols,
false);
438 asmb((*p.first)->getMat());
440 auto add_indices = [](
auto &storage,
auto &ind) {
441 storage.resize(ind.size(),
false);
442 noalias(storage) = ind;
445 add_indices((*p.first)->getRowInd(), row_ind);
446 add_indices((*p.first)->getColInd(), col_ind);
451 auto asmb = [&](
auto &sm) {
455 if (sm.size1() != nb_rows) {
457 "Wrong mat or storage size %d != %d", sm.size1(), nb_rows);
459 if (sm.size2() != nb_cols) {
461 "Wrong mat or storage size %d != %d", sm.size2(), nb_cols);
474 "Assembly type not implemented");
479 CHKERR asmb((*it)->getMat());
498 MOFEM_LOG(
"SELF", Sev::noisy) <<
"Schur assemble begin";
507 std::vector<std::string> fields_name,
508 std::vector<boost::shared_ptr<Range>> field_ents,
511 std::vector<bool> sym_schur, std::vector<double> diag_eps,
bool symm_op,
512 boost::shared_ptr<BlockStructure> diag_blocks)
514 fieldEnts(field_ents), sequenceOfAOs(sequence_of_aos),
515 sequenceOfMats(sequence_of_mats), symSchur(sym_schur), diagEps(diag_eps),
516 diagBlocks(diag_blocks) {}
519 std::vector<std::string> fields_name,
520 std::vector<boost::shared_ptr<Range>> field_ents,
523 std::vector<bool> sym_schur,
bool symm_op,
524 boost::shared_ptr<BlockStructure> diag_blocks)
526 fields_name, field_ents, sequence_of_aos, sequence_of_mats, sym_schur,
527 std::vector<
double>(fields_name.size(), 0), symm_op, diag_blocks) {}
529 template <
typename I>
542 MOFEM_LOG(
"SELF", Sev::noisy) <<
"Schur assemble begin -> end";
546 auto get_field_name = [&](
auto uid) {
557 for (
auto &s : storage) {
558 auto &
m = s->getMat();
560 auto &row_ind = s->getRowInd();
561 auto &col_ind = s->getColInd();
563 if (
auto ierr = mat_set_values(
M, row_ind.size(), &*row_ind.begin(),
564 col_ind.size(), &*col_ind.begin(),
565 &*
m.data().begin(), ADD_VALUES)) {
568 auto row_ent_it = field_ents->find(s->uidRow);
569 auto col_ent_it = field_ents->find(s->uidCol);
571 if (row_ent_it != field_ents->end())
573 <<
"Assemble row entity: " << (*row_ent_it)->getName() <<
" "
574 << (*col_ent_it)->getEntTypeName() <<
" side "
575 << (*row_ent_it)->getSideNumber();
576 if (col_ent_it != field_ents->end())
578 <<
"Assemble col entity: " << (*col_ent_it)->getName() <<
" "
579 << (*col_ent_it)->getEntTypeName() <<
" side "
580 << (*col_ent_it)->getSideNumber();
590 auto apply_schur = [&](
auto &storage,
592 auto lo_uid,
auto hi_uid,
594 double eps,
bool symm) {
598 auto add_off_mat = [&](
auto uid_row,
auto uid_col,
auto &row_ind,
602 auto it = storage.template get<SchurElemMats::uid_mi_tag>().find(
603 boost::make_tuple(uid_row, uid_col));
605 if (it == storage.template get<SchurElemMats::uid_mi_tag>().end()) {
631 auto &mat = (*p.first)->
getMat();
632 auto &set_row_ind = (*p.first)->getRowInd();
633 auto &set_col_ind = (*p.first)->getColInd();
635 set_row_ind.resize(row_ind.size(),
false);
636 noalias(set_row_ind) = row_ind;
637 set_col_ind.resize(col_ind.size(),
false);
638 noalias(set_col_ind) = col_ind;
646 MOFEM_LOG(
"SELF", Sev::noisy) <<
"insert: " << get_field_name(uid_row)
647 <<
" " << get_field_name(uid_col) <<
" "
648 << mat.size1() <<
" " << mat.size2();
654 auto &mat = (*it)->getMat();
657 MOFEM_LOG(
"SELF", Sev::noisy) <<
"add: " << get_field_name(uid_row)
658 <<
" " << get_field_name(uid_col) <<
" "
659 << mat.size1() <<
" " << mat.size2();
666 "Wrong size %d != %d", mat.size1(),
671 "Wrong size %d != %d", mat.size2(),
680 auto get_row_view = [&]() {
682 storage.template get<SchurElemMats::uid_mi_tag>().lower_bound(
683 boost::make_tuple(lo_uid, 0));
685 storage.template get<SchurElemMats::uid_mi_tag>().upper_bound(
688 std::vector<const SchurElemMats *> schur_row_ptr_view;
689 schur_row_ptr_view.reserve(std::distance(row_it, hi_row_it));
690 for (; row_it != hi_row_it; ++row_it) {
691 schur_row_ptr_view.push_back(*row_it);
693 return schur_row_ptr_view;
696 auto get_col_view = [&]() {
698 storage.template get<SchurElemMats::col_mi_tag>().lower_bound(lo_uid);
700 storage.template get<SchurElemMats::col_mi_tag>().upper_bound(hi_uid);
701 std::vector<const SchurElemMats *> schur_col_ptr_view;
702 schur_col_ptr_view.reserve(std::distance(col_it, hi_col_it));
703 for (; col_it != hi_col_it; ++col_it) {
704 schur_col_ptr_view.push_back(*col_it);
706 return schur_col_ptr_view;
709 auto schur_row_ptr_view = get_row_view();
710 auto schur_col_ptr_view = get_col_view();
713 for (
auto row_it : schur_row_ptr_view) {
715 if (row_it->uidRow == row_it->uidCol) {
719 <<
"invert: uid_row " << get_field_name(row_it->uidRow)
720 <<
" row uid " << get_field_name(row_it->uidCol) <<
" : "
721 << (*row_it)->getMat().size1() <<
" "
722 << (*row_it)->getMat().size2();
730 for (
auto c_lo : schur_col_ptr_view) {
732 if (c_lo->uidCol != row_it->uidRow)
734 "Wrong size %d != %d", c_lo->uidCol, row_it->uidRow);
737 auto &uid_row = c_lo->uidRow;
738 if (uid_row == row_it->uidRow) {
742 auto &cc_off_mat = c_lo->getMat();
745 if (
invMat.size1() != cc_off_mat.size2()) {
747 <<
"row_uid " << get_field_name(row_it->uidRow) <<
" row uid "
748 << get_field_name(uid_row);
750 "Wrong size %d != %d",
invMat.size1(), cc_off_mat.size2());
756 cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
757 cc_off_mat.size1(),
invMat.size2(), cc_off_mat.size2(),
758 1., &*cc_off_mat.data().begin(), cc_off_mat.size2(),
763 for (
auto r_lo : schur_row_ptr_view) {
765 if (c_lo->uidCol != row_it->uidRow)
767 "Wrong size %d != %d", c_lo->uidCol, row_it->uidRow);
770 auto &uid_col = r_lo->uidCol;
773 if (uid_col == row_it->uidRow) {
778 if (symm && uid_row > uid_col) {
782 auto &rr_off_mat = r_lo->getMat();
784 rr_off_mat.size2(),
false);
788 <<
"uid_row " << get_field_name(row_it->uidRow)
789 <<
": col uid " << get_field_name(uid_col) <<
" row uid "
790 << get_field_name(uid_row);
792 "Wrong size %d != %d", rr_off_mat.size1(),
799 cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
803 &*rr_off_mat.data().begin(), rr_off_mat.size2(), 0.,
808 CHKERR add_off_mat(uid_row, uid_col, c_lo->getRowInd(),
811 if (symm && uid_row != uid_col) {
816 CHKERR add_off_mat(uid_col, uid_row, r_lo->getColInd(),
827 auto erase_factored = [&](
auto &storage,
auto lo_uid,
auto hi_uid) {
830 auto r_lo = storage.template get<SchurElemMats::uid_mi_tag>().lower_bound(
831 boost::make_tuple(lo_uid, 0));
832 auto r_hi = storage.template get<SchurElemMats::uid_mi_tag>().upper_bound(
833 boost::make_tuple(hi_uid,
835 storage.template get<SchurElemMats::uid_mi_tag>().erase(r_lo, r_hi);
838 storage.template get<SchurElemMats::col_mi_tag>().lower_bound(lo_uid);
840 storage.template get<SchurElemMats::col_mi_tag>().upper_bound(hi_uid);
841 storage.template get<SchurElemMats::col_mi_tag>().erase(c_lo, c_hi);
846 auto assemble_S = [&](
auto &storage,
auto ao,
auto mat) {
851 for (
auto &
m : storage) {
852 auto &ind_row =
m->getRowInd();
853 CHKERR AOApplicationToPetsc(ao, ind_row.size(), &*ind_row.begin());
854 auto &ind_col =
m->getColInd();
855 CHKERR AOApplicationToPetsc(ao, ind_col.size(), &*ind_col.begin());
867 auto assemble_A00 = [&](
auto &storage,
auto lo_uid,
auto hi_uid) {
870 auto add = [&](
auto lo,
auto hi) {
872 for (; lo != hi; ++lo) {
873 auto &
m = (*lo)->getMat();
874 if (
m.size1() &&
m.size2()) {
875 auto row_ind = (*lo)->getRowInd()[0];
876 auto col_ind = (*lo)->getColInd()[0];
877 auto nb_rows =
m.size1();
878 auto nb_cols =
m.size2();
879 auto it =
diagBlocks->blockIndex.get<1>().find(
880 boost::make_tuple(row_ind, col_ind, nb_rows, nb_cols));
881 if (it !=
diagBlocks->blockIndex.get<1>().end()) {
882 auto inv_shift = it->getInvShift();
883 if (inv_shift != -1) {
887 "No dataInvBlocksPtr");
889 auto *ptr = &((*
diagBlocks->dataInvBlocksPtr)[inv_shift]);
890 if (row_ind == col_ind && nb_rows == nb_cols) {
892 std::copy(
invMat.data().begin(),
invMat.data().end(), ptr);
896 std::copy(
m.data().begin(),
m.data().end(), ptr);
907 storage.template get<SchurElemMats::uid_mi_tag>().lower_bound(
908 boost::make_tuple(lo_uid, 0)),
909 storage.template get<SchurElemMats::uid_mi_tag>().upper_bound(
918 auto get_a00_uids = [&]() {
919 auto get_field_bit = [&](
auto &name) {
923 std::vector<std::pair<UId, UId>> a00_uids;
925 for (
auto ss = 0; ss !=
fieldsName.size(); ++ss) {
926 auto field_bit = get_field_bit(
fieldsName[ss]);
929 for (
auto p = row_ents->pair_begin(); p != row_ents->pair_end(); ++p) {
934 a00_uids.push_back(std::make_pair(lo_uid, hi_uid));
938 field_bit, get_id_for_min_type<MBVERTEX>());
940 field_bit, get_id_for_max_type<MBENTITYSET>());
941 a00_uids.push_back(std::make_pair(lo_uid, hi_uid));
948 auto list_storage = [&](
auto &storage) {
951 for (
auto &p : storage) {
953 <<
"List schur storage: " <<
i <<
" " << p->iDX <<
": "
954 << get_field_name(p->uidRow) <<
" " << get_field_name(p->uidCol)
955 <<
" : " << p->getMat().size1() <<
" " << p->getMat().size2();
962 auto assemble = [&](
auto &&a00_uids) {
966 for (
auto &p : a00_uids) {
967 auto [lo_uid, hi_uid] = p;
970 list_storage(storage);
972 <<
"Schur assemble: " << get_field_name(lo_uid) <<
" - "
973 << get_field_name(hi_uid);
978 CHKERR assemble_A00(storage, lo_uid, hi_uid);
979 CHKERR erase_factored(storage, lo_uid, hi_uid);
987 CHKERR assemble(get_a00_uids());
991 MOFEM_LOG(
"SELF", Sev::noisy) <<
"Schur assemble done";
1010 const int nb =
m.size1();
1013 for (
int cc = 0; cc != nb; ++cc) {
1018 inv.resize(nb, nb,
false);
1020 auto ptr = &*inv.data().begin();
1021 for (
int c = 0;
c != nb; ++
c, ptr += nb + 1)
1023 ipiv.resize(nb,
false);
1024 lapack_work.resize(nb * nb,
false);
1026 lapack_dsysv(
'L', nb, nb, &*
m.data().begin(), nb, &*ipiv.begin(),
1027 &*inv.data().begin(), nb, &*lapack_work.begin(), nb * nb);
1030 "Can not invert matrix info = %d", info);
1043 const auto nb =
m.size1();
1045 if (nb !=
m.size2()) {
1047 "It should be square matrix %d != %d", nb,
m.size2());
1052 for (
int cc = 0; cc != nb; ++cc) {
1057 inv.resize(nb, nb,
false);
1059 auto ptr = &*inv.data().begin();
1060 for (
int c = 0;
c != nb; ++
c, ptr += nb + 1)
1062 ipiv.resize(nb,
false);
1063 const auto info =
lapack_dgesv(nb, nb, &*
m.data().begin(), nb,
1064 &*ipiv.begin(), &*inv.data().begin(), nb);
1067 "Can not invert matrix info = %d", info);
1075 return doWorkImpl<SchurDSYSV>(side,
type, data);
1081 return doWorkImpl<SchurDGESV>(side,
type, data);
1091 auto cmp_uid_lo = [](
const boost::weak_ptr<FieldEntity> &
a,
const UId &b) {
1092 if (
auto a_ptr =
a.lock()) {
1093 if (a_ptr->getLocalUniqueId() < b)
1102 auto cmp_uid_hi = [](
const UId &b,
const boost::weak_ptr<FieldEntity> &
a) {
1103 if (
auto a_ptr =
a.lock()) {
1104 if (b < a_ptr->getLocalUniqueId())
1114 auto get_uid_pair = [](
const auto &field_id) {
1116 field_id, get_id_for_min_type<MBVERTEX>());
1118 field_id, get_id_for_max_type<MBENTITYSET>());
1119 return std::make_pair(lo_uid, hi_uid);
1124 auto lo = std::lower_bound(field_ents.begin(), field_ents.end(),
1126 auto hi = std::upper_bound(field_ents.begin(), field_ents.end(),
1128 return std::make_pair(lo, hi);
1131 auto row_extractor = [](
auto &e) {
return e->entityCacheRowDofs; };
1132 auto col_extractor = [](
auto &e) {
return e->entityCacheColDofs; };
1134 auto extract_data = [](
auto &&its,
auto extractor) {
1135 std::vector<std::tuple<int, int, int>> data;
1136 data.reserve(std::distance(its.first, its.second));
1137 for (; its.first != its.second; ++its.first) {
1138 if (
auto e = its.first->lock()) {
1139 if (
auto cache = extractor(e).lock()) {
1140 auto nb_dofs = std::distance(cache->loHi[0], cache->loHi[1]);
1142 auto glob = (*cache->loHi[0])->getPetscGlobalDofIdx();
1143 auto loc = (*cache->loHi[0])->getPetscLocalDofIdx();
1144 data.emplace_back(glob, nb_dofs, loc);
1148 for (
auto lo = cache->loHi[0]; lo != cache->loHi[1]; ++lo) {
1149 auto glob = (*lo)->getPetscGlobalDofIdx();
1152 "Wrong global index");
1164 auto data_ptr = boost::make_shared<BlockStructure>();
1168 auto fe_method = boost::shared_ptr<MoFEM::FEMethod>(
new MoFEM::FEMethod());
1170 for (
auto &
d : schur_fe_op_vec) {
1173 auto get_bit_numbers = [&
d](
auto op) {
1174 std::vector<FieldBitNumber> bit_numbers(
d.second.size());
1180 auto row_bit_numbers = get_bit_numbers(
1181 [&](
auto &p) {
return m_field_ptr->get_field_bit_number(p.first); });
1183 auto col_bit_numbers = get_bit_numbers(
1184 [&](
auto &p) {
return m_field_ptr->get_field_bit_number(p.second); });
1186 fe_method->preProcessHook = []() {
return 0; };
1187 fe_method->postProcessHook = []() {
return 0; };
1188 fe_method->operatorHook = [&]() {
1191 for (
auto f = 0;
f != row_bit_numbers.size(); ++
f) {
1194 extract_data(get_it_pair(fe_method->getRowFieldEnts(),
1195 get_uid_pair(row_bit_numbers[
f])),
1198 extract_data(get_it_pair(fe_method->getColFieldEnts(),
1199 get_uid_pair(col_bit_numbers[
f])),
1202 for (
auto &
r : row_data) {
1203 auto [r_glob, r_nb_dofs, r_loc] =
r;
1204 for (
auto &
c : col_data) {
1205 auto [c_glob, c_nb_dofs, c_loc] =
c;
1206 if (r_glob != -1 && c_glob != -1) {
1208 r_glob, c_glob, r_nb_dofs, c_nb_dofs, r_loc, c_loc, -1, -1});
1222 for (
auto &
v : data_ptr->blockIndex.get<0>()) {
1223 v.getMatShift() = mem_size;
1224 mem_size +=
v.getNbCols() *
v.getNbRows();
1227 std::vector<double> tmp;
1228 if (mem_size > tmp.max_size())
1231 data_ptr->dataBlocksPtr =
1232 boost::make_shared<std::vector<double>>(mem_size, 0);
1236 CHKERR VecSetDM(ghost_x, PETSC_NULL);
1237 CHKERR VecSetDM(ghost_y, PETSC_NULL);
1239 data_ptr->ghostX = ghost_x;
1240 data_ptr->ghostY = ghost_y;
1265 const PetscInt rows[], PetscScalar diag,
1270 CHKERR MatShellGetContext(
A, (
void **)&ctx);
1274 const int *ptr = &rows[0];
1279 CHKERR PetscObjectGetComm((PetscObject)
A, &comm);
1281 MPI_Comm_size(comm, &size);
1287 CHKERR ISGetSize(is_local, &is_nb_rows);
1290 CHKERR ISView(is_local, PETSC_VIEWER_STDOUT_WORLD);
1293 CHKERR ISGetIndices(is_local, &ptr);
1297 CHKERR MatGetLocalSize(
A, &loc_m, &loc_n);
1299 for (
auto n = 0;
n != is_nb_rows; ++
n) {
1301 auto rlo = ctx->blockIndex.get<2>().lower_bound(row);
1302 auto rhi = ctx->blockIndex.get<2>().end();
1303 for (; rlo != rhi; ++rlo) {
1304 auto r_shift = row - rlo->getRow();
1305 if (r_shift >= 0 && r_shift < rlo->getNbRows()) {
1306 auto *ptr = &(*ctx->dataBlocksPtr)[rlo->getMatShift()];
1307 for (
auto i = 0;
i != rlo->getNbCols(); ++
i) {
1308 ptr[
i + r_shift * rlo->getNbCols()] = 0;
1310 }
else if (rlo->getRow() + rlo->getNbRows() > row) {
1316 for (
auto n = 0;
n != is_nb_rows; ++
n) {
1318 auto clo = ctx->blockIndex.get<3>().lower_bound(col);
1319 auto chi = ctx->blockIndex.get<3>().end();
1320 for (; clo != chi; ++clo) {
1321 auto c_shift = col - clo->getCol();
1322 if (c_shift >= 0 && c_shift < clo->getNbCols()) {
1324 auto *ptr = &(*ctx->dataBlocksPtr)[clo->getMatShift()];
1325 for (
auto i = 0;
i != clo->getNbRows(); ++
i) {
1326 ptr[c_shift +
i * clo->getNbCols()] = 0;
1332 clo->getRow() == clo->getCol() && clo->getLocRow() < loc_m &&
1333 clo->getLocCol() < loc_n
1336 auto r_shift = col - clo->getCol();
1337 if (r_shift >= 0 && r_shift < clo->getNbRows()) {
1338 ptr[c_shift + r_shift * clo->getNbCols()] = diag;
1341 }
else if (clo->getCol() + clo->getNbCols() > col) {
1348 CHKERR ISRestoreIndices(is_local, &ptr);
1359 CHKERR MatShellGetContext(
m, (
void **)&ctx);
1360 if (ctx->dataBlocksPtr)
1361 std::fill(ctx->dataBlocksPtr->begin(), ctx->dataBlocksPtr->end(), 0.);
1362 if (ctx->dataInvBlocksPtr)
1363 std::fill(ctx->dataInvBlocksPtr->begin(), ctx->dataInvBlocksPtr->end(), 0.);
1364 if (ctx->preconditionerBlocksPtr)
1365 std::fill(ctx->preconditionerBlocksPtr->begin(),
1366 ctx->preconditionerBlocksPtr->end(), 0.);
1372 CHKERR MatShellSetManageScalingShifts(mat_raw);
1373 CHKERR MatShellSetOperation(mat_raw, MATOP_MULT, (
void (*)(
void))
mult);
1374 CHKERR MatShellSetOperation(mat_raw, MATOP_MULT_ADD,
1376 CHKERR MatShellSetOperation(mat_raw, MATOP_SOLVE, (
void (*)(
void))
solve);
1377 CHKERR MatShellSetOperation(mat_raw, MATOP_SOLVE_ADD,
1379 CHKERR MatShellSetOperation(mat_raw, MATOP_ZERO_ENTRIES,
1381 CHKERR MatShellSetOperation(mat_raw, MATOP_ZERO_ROWS_COLUMNS,
1388 boost::shared_ptr<BlockStructure> data) {
1391 auto nb_local = problem_ptr->nbLocDofsRow;
1392 auto nb_global = problem_ptr->nbDofsRow;
1395 if (nb_local != problem_ptr->nbLocDofsCol) {
1397 <<
"Wrong size " << nb_local <<
" != " << problem_ptr->nbLocDofsCol;
1399 "nb. cols is inconsistent with nb. rows");
1401 if (nb_global != problem_ptr->nbDofsCol) {
1403 <<
"Wrong size " << nb_global <<
" != " << problem_ptr->nbDofsCol;
1405 "nb. cols is inconsistent with nb. rows");
1410 CHKERR PetscObjectGetComm((PetscObject)dm, &comm);
1413 CHKERR MatCreateShell(comm, nb_local, nb_local, nb_global, nb_global,
1414 (
void *)data.get(), &mat_raw);
1425 CHKERR MatShellGetContext(mat, (
void **)&ctx);
1429 Vec ghost_x = ctx->ghostX;
1430 Vec ghost_y = ctx->ghostY;
1432 CHKERR VecCopy(x, ghost_x);
1434 CHKERR VecGhostUpdateBegin(ghost_x, INSERT_VALUES, SCATTER_FORWARD);
1435 CHKERR VecGhostUpdateEnd(ghost_x, INSERT_VALUES, SCATTER_FORWARD);
1439 CHKERR VecGhostGetLocalForm(ghost_x, &loc_ghost_x);
1440 CHKERR VecGetArray(loc_ghost_x, &x_array);
1444 CHKERR VecGhostGetLocalForm(ghost_y, &loc_ghost_y);
1446 CHKERR VecGetLocalSize(loc_ghost_y, &nb_y);
1447 CHKERR VecGetArray(loc_ghost_y, &y_array);
1448 for (
auto i = 0;
i != nb_y; ++
i)
1451 double *block_ptr = &*ctx->dataBlocksPtr->begin();
1453 auto it = ctx->blockIndex.get<0>().lower_bound(0);
1454 auto hi = ctx->blockIndex.get<0>().end();
1457 auto nb_rows = it->getNbRows();
1458 auto nb_cols = it->getNbCols();
1459 auto x_ptr = &x_array[it->getLocCol()];
1460 auto y_ptr = &y_array[it->getLocRow()];
1461 auto ptr = &block_ptr[it->getMatShift()];
1462 for (
auto r = 0;
r != nb_rows; ++
r) {
1463 for (
auto c = 0;
c != nb_cols; ++
c) {
1464 y_ptr[
r] += ptr[
r * nb_cols +
c] * x_ptr[
c];
1470 if (ctx->multiplyByPreconditioner) {
1472 if (!ctx->preconditionerBlocksPtr)
1474 "No parentBlockStructurePtr");
1476 auto preconditioner_ptr = &*ctx->preconditionerBlocksPtr->begin();
1478 auto it = ctx->blockIndex.get<0>().lower_bound(0);
1479 auto hi = ctx->blockIndex.get<0>().end();
1482 if (it->getInvShift() != -1) {
1483 auto nb_rows = it->getNbRows();
1484 auto nb_cols = it->getNbCols();
1485 auto x_ptr = &x_array[it->getLocCol()];
1486 auto y_ptr = &y_array[it->getLocRow()];
1487 auto ptr = &preconditioner_ptr[it->getInvShift()];
1488 for (
auto r = 0;
r != nb_rows; ++
r) {
1489 for (
auto c = 0;
c != nb_cols; ++
c) {
1490 y_ptr[
r] += ptr[
r * nb_cols +
c] * x_ptr[
c];
1498 CHKERR VecRestoreArray(loc_ghost_x, &x_array);
1499 CHKERR VecRestoreArray(loc_ghost_y, &y_array);
1500 CHKERR VecGhostRestoreLocalForm(ghost_x, &loc_ghost_x);
1501 CHKERR VecGhostRestoreLocalForm(ghost_y, &loc_ghost_y);
1503 CHKERR VecGhostUpdateBegin(ghost_y, ADD_VALUES, SCATTER_REVERSE);
1504 CHKERR VecGhostUpdateEnd(ghost_y, ADD_VALUES, SCATTER_REVERSE);
1508 CHKERR VecCopy(ghost_y, y);
1511 CHKERR VecAXPY(y, 1., ghost_y);
1519 auto print_norm = [&](
auto msg,
auto y) {
1522 CHKERR VecNorm(y, NORM_2, &norm);
1524 CHKERR VecGetLocalSize(y, &nb_loc_y);
1526 CHKERR VecGetSize(y, &nb_y);
1528 << msg <<
" " << nb_y <<
" " << nb_loc_y <<
" norm " << norm;
1534 print_norm(
"mult_schur_block_shell insert x", x);
1535 print_norm(
"mult_schur_block_shell insert y", y);
1538 print_norm(
"mult_schur_block_shell add x", x);
1539 print_norm(
"mult_schur_block_shell add y", y);
1557 CHKERR MatShellGetContext(mat, (
void **)&ctx);
1562 Vec ghost_x = ctx->ghostY;
1563 Vec ghost_y = ctx->ghostX;
1565 CHKERR VecCopy(y, ghost_y);
1566 CHKERR VecZeroEntries(ghost_x);
1568 CHKERR VecGhostUpdateBegin(ghost_y, INSERT_VALUES, SCATTER_FORWARD);
1569 CHKERR VecGhostUpdateEnd(ghost_y, INSERT_VALUES, SCATTER_FORWARD);
1573 CHKERR VecGhostGetLocalForm(ghost_x, &loc_ghost_x);
1574 CHKERR VecGetArray(loc_ghost_x, &x_array);
1578 CHKERR VecGhostGetLocalForm(ghost_y, &loc_ghost_y);
1579 CHKERR VecGetArray(loc_ghost_y, &y_array);
1581 auto data_inv_blocks = ctx->dataInvBlocksPtr;
1582 auto inv_block_ptr = &*data_inv_blocks->begin();
1583 auto data_blocks = ctx->dataBlocksPtr;
1584 auto block_ptr = &*data_blocks->begin();
1589 std::vector<double>
f;
1591 for (
auto s1 = 0; s1 != index_view->second.size() - 1; ++s1) {
1592 auto lo = index_view->second[s1];
1593 auto hi = index_view->second[s1 + 1];
1595 auto diag_index_ptr = index_view->first[lo];
1598 auto row = diag_index_ptr->getLocRow();
1599 auto col = diag_index_ptr->getLocCol();
1600 auto nb_rows = diag_index_ptr->getNbRows();
1601 auto nb_cols = diag_index_ptr->getNbCols();
1602 auto inv_shift = diag_index_ptr->getInvShift();
1605 std::copy(&y_array[col], &y_array[col + nb_cols],
f.begin());
1607 for (; lo != hi; ++lo) {
1608 auto off_index_ptr = index_view->first[lo];
1609 auto off_col = off_index_ptr->getLocCol();
1610 auto off_nb_cols = off_index_ptr->getNbCols();
1611 auto off_shift = off_index_ptr->getMatShift();
1612 auto x_ptr = &x_array[off_col];
1613 auto ptr = &block_ptr[off_shift];
1614 for (
auto r = 0;
r != nb_rows; ++
r) {
1615 for (
auto c = 0;
c != off_nb_cols; ++
c) {
1616 f[
r] -= ptr[
r * off_nb_cols +
c] * x_ptr[
c];
1622 if (inv_shift == -1)
1624 if (inv_shift + nb_rows * nb_cols > data_inv_blocks->size())
1626 "inv_shift out of range %d > %d", inv_shift + nb_rows * nb_cols,
1627 data_inv_blocks->size());
1630 auto ptr = &inv_block_ptr[inv_shift];
1631 for (
auto r = 0;
r != nb_rows; ++
r) {
1632 for (
auto c = 0;
c != nb_cols; ++
c) {
1633 x_array[row +
r] -= ptr[
r * nb_cols +
c] *
f[
c];
1638 CHKERR VecRestoreArray(loc_ghost_x, &x_array);
1639 CHKERR VecRestoreArray(loc_ghost_y, &y_array);
1640 CHKERR VecGhostRestoreLocalForm(ghost_x, &loc_ghost_x);
1641 CHKERR VecGhostRestoreLocalForm(ghost_y, &loc_ghost_y);
1643 CHKERR VecGhostUpdateBegin(ghost_y, ADD_VALUES, SCATTER_REVERSE);
1644 CHKERR VecGhostUpdateEnd(ghost_y, ADD_VALUES, SCATTER_REVERSE);
1648 CHKERR VecCopy(ghost_x, x);
1651 CHKERR VecAXPY(x, 1., ghost_x);
1659 auto print_norm = [&](
auto msg,
auto y) {
1662 CHKERR VecNorm(y, NORM_2, &norm);
1664 CHKERR VecGetLocalSize(y, &nb_loc_y);
1666 CHKERR VecGetSize(y, &nb_y);
1668 << msg <<
" " << nb_y <<
" " << nb_loc_y <<
" norm " << norm;
1674 print_norm(
"solve_schur_block_shell insert x", x);
1675 print_norm(
"solve_schur_block_shell insert y", y);
1678 print_norm(
"solve_schur_block_shell add x", x);
1679 print_norm(
"solve_schur_block_shell add y", y);
1698 boost::shared_ptr<std::vector<double>> data_blocks_ptr) {
1714 auto get_row_data = [&]() -> std::pair<bool, VectorInt> {
1716 if (
auto stored_data_ptr =
1718 return std::make_pair(
true, stored_data_ptr->entityIndices);
1721 return std::make_pair(
false, row_data.
getIndices());
1724 auto row_indices = get_row_data();
1725 auto it_r = std::find(row_indices.second.begin(), row_indices.second.end(),
1726 -1) == row_indices.second.end();
1736 row_indices.second.size()
1747 boost::make_tuple(row_indices.second[0], col_data.
getIndices()[0],
1748 row_indices.second.size(),
1758 <<
"missing block: " << row_data.
getFieldDofs()[0]->getName() <<
" : "
1765 auto shift = shift_extractor(&*it);
1768 auto nbr = row_indices.second.size();
1770 auto mat_row_ptr = &mat(0, 0);
1771 auto s_mat = &(*data_blocks_ptr)[shift];
1772 if (iora == ADD_VALUES) {
1773 for (
int r = 0;
r != nbr; ++
r) {
1774 for (
int c = 0;
c != nbc; ++
c) {
1775 *s_mat += *mat_row_ptr;
1781 for (
int r = 0;
r != nbr; ++
r) {
1782 for (
int c = 0;
c != nbc; ++
c) {
1783 *s_mat = *mat_row_ptr;
1796 std::vector<int> row_ent_idx;
1797 std::vector<int> col_ent_idx;
1799 auto get_ent_idx = [&](
auto lo,
auto hi,
auto &idx) {
1801 idx.reserve(std::distance(lo, hi));
1802 for (; lo != hi; ++lo) {
1803 idx.emplace_back((*lo)->getEntDofIdx());
1809 if (
auto r_cache = rent->entityCacheRowDofs.lock()) {
1811 auto rlo = r_cache->loHi[0];
1812 auto rhi = r_cache->loHi[1];
1816 get_ent_idx(rlo, rhi, row_ent_idx);
1817 auto gr = (*rlo)->getPetscGlobalDofIdx();
1818 auto nbr = std::distance(rlo, rhi);
1822 if (
auto c_cache = cent->entityCacheColDofs.lock()) {
1824 auto clo = c_cache->loHi[0];
1825 auto chi = c_cache->loHi[1];
1829 auto nbc = std::distance(clo, chi);
1832 boost::make_tuple(gr, (*clo)->getPetscGlobalDofIdx(), nbr, nbc)
1841 <<
"missing block: " << row_data.
getFieldDofs()[0]->getName()
1844 "Block not allocated");
1849 auto shift = shift_extractor(&*it);
1852 auto mat_row_ptr0 = &mat(row, col);
1853 auto s_mat = &(*data_blocks_ptr)[shift];
1857 nbr == rent->getNbDofsOnEnt() && nbc == cent->getNbDofsOnEnt()
1863 if (iora == ADD_VALUES) {
1864 for (
int r = 0;
r != nbr; ++
r) {
1865 auto mat_row_ptr = mat_row_ptr0 +
r * mat.size2();
1866 for (
int c = 0;
c != nbc; ++
c) {
1867 *s_mat += *mat_row_ptr;
1873 for (
int r = 0;
r != nbr; ++
r) {
1874 auto mat_row_ptr = mat_row_ptr0 +
r * mat.size2();
1875 for (
int c = 0;
c != nbc; ++
c) {
1876 *s_mat = *mat_row_ptr;
1885 nbc == cent->getNbDofsOnEnt()
1891 if (iora == ADD_VALUES) {
1892 for (
auto r : row_ent_idx) {
1893 auto mat_row_ptr = mat_row_ptr0 +
r * mat.size2();
1894 for (
int c = 0;
c != nbc; ++
c) {
1895 *s_mat += *mat_row_ptr;
1901 for (
auto r : row_ent_idx) {
1902 auto mat_row_ptr = mat_row_ptr0 +
r * mat.size2();
1903 for (
int c = 0;
c != nbc; ++
c) {
1904 *s_mat = *mat_row_ptr;
1913 get_ent_idx(clo, chi, col_ent_idx);
1914 auto row_idx = &row_indices.second[row];
1916 if (iora == ADD_VALUES) {
1917 for (
auto r : row_ent_idx) {
1918 auto mat_row_ptr = mat_row_ptr0 +
r * mat.size2();
1919 for (
auto c : col_ent_idx) {
1920 if (row_idx[
r] != -1 && col_idx[
c] != -1)
1921 *s_mat += mat_row_ptr[
c];
1926 for (
auto r : row_ent_idx) {
1927 auto mat_row_ptr = mat_row_ptr0 +
r * mat.size2();
1928 for (
auto c : col_ent_idx) {
1929 if (row_idx[
r] != -1 && col_idx[
c] != -1)
1930 *s_mat = mat_row_ptr[
c];
1938 col += cent->getNbDofsOnEnt();
1941 row += rent->getNbDofsOnEnt();
1958 PetscBool is_mat_shell = PETSC_FALSE;
1959 PetscObjectTypeCompare((PetscObject)
M, MATSHELL, &is_mat_shell);
1962 CHKERR MatShellGetContext(
M, (
void **)&ctx);
1964 ctx, row_data, col_data, mat, iora,
1966 ctx->dataBlocksPtr);
1968 CHKERR MatSetValues<AssemblyTypeSelector<PETSC>>(
M, row_data, col_data, mat,
1980 CHKERR MatShellGetContext(
M, (
void **)&ctx);
1981 if (!ctx->preconditionerBlocksPtr)
1983 "No preconditionerBlocksPtr");
1985 ctx, row_data, col_data, mat, iora,
1987 ctx->preconditionerBlocksPtr);
1994 boost::shared_ptr<BlockStructure> block_mat_data_ptr,
1996 std::vector<std::string> fields_names,
1997 std::vector<boost::shared_ptr<Range>>
1999 bool add_preconditioner_block) {
2001 if (!block_mat_data_ptr) {
2005 auto [schur_dm, block_dm] = dms;
2010 auto schur_dofs_row = schur_prb->getNumeredRowDofsPtr();
2011 auto schur_dofs_col = schur_prb->getNumeredColDofsPtr();
2012 auto block_dofs_row = block_prb->getNumeredRowDofsPtr();
2013 auto block_dofs_col = block_prb->getNumeredColDofsPtr();
2015 auto ao_schur_row = schur_prb->getSubData()->getSmartRowMap();
2016 auto ao_schur_col = schur_prb->getSubData()->getSmartColMap();
2017 auto ao_block_row = block_prb->getSubData()->getSmartRowMap();
2018 auto ao_block_col = block_prb->getSubData()->getSmartColMap();
2024 CHKERR VecSetDM(schur_vec_x, PETSC_NULL);
2025 CHKERR VecSetDM(block_vec_x, PETSC_NULL);
2026 CHKERR VecSetDM(schur_vec_y, PETSC_NULL);
2027 CHKERR VecSetDM(block_vec_y, PETSC_NULL);
2029 auto get_vec = [&](
auto schur_data) {
2030 std::vector<int> vec_r, vec_c;
2031 vec_r.reserve(schur_data->blockIndex.size());
2032 vec_c.reserve(schur_data->blockIndex.size());
2033 for (
auto &
d : schur_data->blockIndex.template get<1>()) {
2034 vec_r.push_back(
d.getRow());
2035 vec_c.push_back(
d.getCol());
2037 return std::make_pair(vec_r, vec_c);
2040 auto [vec_r_schur, vec_c_schur] = get_vec(block_mat_data_ptr);
2041 CHKERR AOApplicationToPetsc(ao_schur_row, vec_r_schur.size(),
2042 &*vec_r_schur.begin());
2043 CHKERR AOApplicationToPetsc(ao_schur_col, vec_c_schur.size(),
2044 &*vec_c_schur.begin());
2045 auto [vec_r_block, vec_c_block] = get_vec(block_mat_data_ptr);
2046 CHKERR AOApplicationToPetsc(ao_block_row, vec_r_block.size(),
2047 &*vec_r_block.begin());
2048 CHKERR AOApplicationToPetsc(ao_block_col, vec_c_block.size(),
2049 &*vec_c_block.begin());
2051 std::array<boost::shared_ptr<BlockStructure>, 4> data_ptrs;
2053 for (
auto r = 0;
r != 3; ++
r) {
2054 data_ptrs[
r] = boost::make_shared<BlockStructure>();
2055 data_ptrs[
r]->dataBlocksPtr = block_mat_data_ptr->dataBlocksPtr;
2057 data_ptrs[3] = boost::make_shared<DiagBlockInvStruture>();
2058 data_ptrs[3]->dataBlocksPtr = block_mat_data_ptr->dataBlocksPtr;
2060 data_ptrs[0]->ghostX = schur_vec_x;
2061 data_ptrs[0]->ghostY = schur_vec_y;
2062 data_ptrs[1]->ghostX = block_vec_x;
2063 data_ptrs[1]->ghostY = schur_vec_y;
2064 data_ptrs[2]->ghostX = schur_vec_x;
2065 data_ptrs[2]->ghostY = block_vec_y;
2066 data_ptrs[3]->ghostX = block_vec_x;
2067 data_ptrs[3]->ghostY = block_vec_y;
2070 int inv_mem_size = 0;
2071 for (
auto &
d : block_mat_data_ptr->blockIndex.get<1>()) {
2073 auto insert = [&](
auto &
m,
auto &dof_r,
auto &dof_c,
auto &
d) {
2077 dof_r->getPetscGlobalDofIdx(), dof_c->getPetscGlobalDofIdx(),
2079 d.getNbRows(),
d.getNbCols(),
2081 dof_r->getPetscLocalDofIdx(), dof_c->getPetscLocalDofIdx(),
2083 d.getMatShift(),
d.getInvShift()}
2088 if (vec_r_schur[idx] != -1 && vec_c_schur[idx] != -1) {
2101 insert(data_ptrs[0]->blockIndex, *schur_dof_r, *schur_dof_c,
d);
2104 if (vec_r_schur[idx] != -1 && vec_c_block[idx] != -1) {
2117 insert(data_ptrs[1]->blockIndex, *schur_dof_r, *block_dof_c,
d);
2120 if (vec_r_block[idx] != -1 && vec_c_schur[idx] != -1) {
2133 insert(data_ptrs[2]->blockIndex, *block_dof_r, *schur_dof_c,
d);
2136 if (vec_r_block[idx] != -1 && vec_c_block[idx] != -1) {
2141 if (
d.getRow() ==
d.getCol() &&
d.getNbRows() ==
d.getNbCols()) {
2143 d.getInvShift() = inv_mem_size;
2144 inv_mem_size +=
d.getNbCols() *
d.getNbCols();
2146 insert(data_ptrs[3]->blockIndex, *block_dof_r, *block_dof_c,
d);
2152 auto set_up_a00_data = [&](
auto inv_block_data) {
2155 auto get_a00_uids = [&]() {
2157 return m_field_ptr->get_field_bit_number(
field_name);
2160 std::vector<std::pair<UId, UId>> a00_uids;
2161 a00_uids.reserve(fields_names.size());
2162 for (
auto ss = 0; ss != fields_names.size(); ++ss) {
2163 auto field_bit = get_field_bit(fields_names[ss]);
2164 auto row_ents = field_ents[ss];
2166 for (
auto p = row_ents->pair_begin(); p != row_ents->pair_end();
2172 a00_uids.push_back(std::make_pair(lo_uid, hi_uid));
2176 field_bit, get_id_for_min_type<MBVERTEX>());
2178 field_bit, get_id_for_max_type<MBENTITYSET>());
2179 a00_uids.push_back(std::make_pair(lo_uid, hi_uid));
2185 auto get_glob_idex_pairs = [&](
auto &&uid_pairs) {
2186 std::vector<std::pair<int, int>> glob_idex_pairs;
2187 glob_idex_pairs.reserve(uid_pairs.size());
2188 auto dofs = block_prb->getNumeredRowDofsPtr();
2190 auto it = uid_pairs.rbegin();
2191 auto hi = uid_pairs.rend();
2193 for (; it != hi; ++it) {
2194 auto [lo_uid, hi_uid] = *it;
2195 auto lo_it = dofs->lower_bound(lo_uid);
2196 auto hi_it = dofs->upper_bound(hi_uid);
2197 if (lo_it != hi_it) {
2198 auto lo_idx = (*lo_it)->getPetscGlobalDofIdx();
2199 glob_idex_pairs.emplace_back(lo_idx, std::distance(lo_it, hi_it));
2202 return glob_idex_pairs;
2206 boost::dynamic_pointer_cast<DiagBlockInvStruture>(inv_block_data)
2209 index_view.first.resize(0);
2210 index_view.second.resize(0);
2211 index_view.first.reserve(inv_block_data->blockIndex.size());
2212 index_view.second.reserve(inv_block_data->blockIndex.size());
2213 index_view.second.push_back(0);
2216 using BlockIndexView = multi_index_container<
2227 BlockIndexView block_index_view;
2228 for (
auto it = inv_block_data->blockIndex.template get<1>().begin();
2229 it != inv_block_data->blockIndex.template get<1>().end(); ++it) {
2230 block_index_view.insert(&*it);
2233 auto glob_idx_pairs = get_glob_idex_pairs(get_a00_uids());
2236 for (
auto s1 = 0; s1 != glob_idx_pairs.size(); ++s1) {
2239 auto [lo_idx, nb] = glob_idx_pairs[s1];
2240 auto it = block_index_view.lower_bound(lo_idx);
2241 auto hi = block_index_view.end();
2245 ((*it)->getRow() + (*it)->getNbRows()) <= lo_idx + nb) {
2247 auto row = (*it)->getRow();
2249 auto get_diag_index =
2251 while (it != hi && (*it)->getRow() == row) {
2252 if ((*it)->getCol() == row &&
2253 (*it)->getNbCols() == (*it)->getNbRows()) {
2263 auto push_off_diag = [&](
auto it,
auto s1) {
2264 while (it != hi && (*it)->getRow() == row) {
2265 for (
int s2 = 0; s2 < s1; ++s2) {
2266 auto [col_lo_idx, col_nb] = glob_idx_pairs[s2];
2267 if ((*it)->getCol() >= col_lo_idx &&
2268 (*it)->getCol() + (*it)->getNbCols() <= col_lo_idx + col_nb) {
2269 index_view.first.push_back(*it);
2276 index_view.first.push_back(get_diag_index(it));
2277 push_off_diag(it, s1);
2278 index_view.second.push_back(index_view.first.size());
2280 while (it != hi && (*it)->getRow() == row) {
2286 auto get_vec = [&]() {
2287 std::vector<int> vec_r, vec_c;
2288 vec_r.reserve(index_view.first.size());
2289 vec_c.reserve(index_view.first.size());
2290 for (
auto &
i : index_view.first) {
2291 vec_r.push_back(
i->getRow());
2292 vec_c.push_back(
i->getCol());
2294 return std::make_pair(vec_r, vec_c);
2297 auto [vec_r_block, vec_c_block] = get_vec();
2298 CHKERR AOPetscToApplication(ao_block_row, vec_r_block.size(),
2299 &*vec_r_block.begin());
2300 CHKERR AOPetscToApplication(ao_block_col, vec_c_block.size(),
2301 &*vec_c_block.begin());
2303 int inv_mem_size = 0;
2304 for (
auto s1 = 0; s1 != index_view.second.size() - 1; ++s1) {
2305 auto lo = index_view.second[s1];
2308 auto diag_index_ptr = index_view.first[lo];
2309 auto row = vec_r_block[lo];
2310 auto col = vec_c_block[lo];
2311 auto nb_rows = diag_index_ptr->getNbRows();
2312 auto nb_cols = diag_index_ptr->getNbCols();
2315 auto it = block_mat_data_ptr->blockIndex.get<1>().find(
2316 boost::make_tuple(row, col, nb_rows, nb_cols));
2317 if (it == block_mat_data_ptr->blockIndex.get<1>().end()) {
2321 it->getInvShift() = inv_mem_size;
2322 diag_index_ptr->getInvShift() = it->getInvShift();
2323 inv_mem_size += nb_rows * nb_cols;
2330 boost::make_shared<std::vector<double>>(inv_mem_size, 0);
2331 data_ptrs[3]->dataInvBlocksPtr = inv_data_ptr;
2332 block_mat_data_ptr->dataInvBlocksPtr = data_ptrs[3]->dataInvBlocksPtr;
2334 if (add_preconditioner_block) {
2335 auto preconditioned_block =
2336 boost::make_shared<std::vector<double>>(inv_mem_size, 0);
2337 data_ptrs[3]->preconditionerBlocksPtr = preconditioned_block;
2338 data_ptrs[3]->multiplyByPreconditioner =
true;
2339 block_mat_data_ptr->preconditionerBlocksPtr =
2340 data_ptrs[3]->preconditionerBlocksPtr;
2341 block_mat_data_ptr->multiplyByPreconditioner =
false;
2347 CHKERR set_up_a00_data(data_ptrs[3]);
2350 CHKERR PetscObjectGetComm((PetscObject)schur_dm, &comm);
2352 auto create_shell_mat = [&](
auto nb_r_loc,
auto nb_c_loc,
auto nb_r_glob,
2353 auto nb_c_glob,
auto data_ptr) {
2355 CHKERR MatCreateShell(comm, nb_r_loc, nb_c_loc, nb_r_glob, nb_c_glob,
2356 (
void *)data_ptr.get(), &mat_raw);
2361 auto schur_nb_global = schur_prb->getNbDofsRow();
2362 auto block_nb_global = block_prb->getNbDofsRow();
2363 auto schur_nb_local = schur_prb->getNbLocalDofsRow();
2364 auto block_nb_local = block_prb->getNbLocalDofsRow();
2366 std::array<SmartPetscObj<Mat>, 4> mats_array;
2368 create_shell_mat(schur_nb_local, schur_nb_local, schur_nb_global,
2369 schur_nb_global, data_ptrs[0]);
2371 create_shell_mat(schur_nb_local, block_nb_local, schur_nb_global,
2372 block_nb_global, data_ptrs[1]);
2374 create_shell_mat(block_nb_local, schur_nb_local, block_nb_global,
2375 schur_nb_global, data_ptrs[2]);
2377 create_shell_mat(block_nb_local, block_nb_local, block_nb_global,
2378 block_nb_global, data_ptrs[3]);
2381 <<
"(0, 0) " << schur_nb_local <<
" " << schur_nb_global <<
" "
2382 << data_ptrs[0]->blockIndex.size();
2384 <<
"(0, 1) " << schur_nb_local <<
" " << block_nb_local <<
" "
2385 << schur_nb_global <<
" " << block_nb_global <<
" "
2386 << data_ptrs[1]->blockIndex.size();
2388 <<
"(1, 0) " << block_nb_local <<
" " << schur_nb_local <<
" "
2389 << block_nb_global <<
" " << schur_nb_global <<
" "
2390 << data_ptrs[2]->blockIndex.size();
2392 <<
"(1, 1) " << block_nb_local <<
" " << block_nb_global <<
" "
2393 << data_ptrs[3]->blockIndex.size();
2397 auto schur_is = schur_prb->getSubData()->getSmartRowIs();
2398 auto block_is = block_prb->getSubData()->getSmartRowIs();
2400 return boost::make_shared<NestSchurData>(
2402 mats_array, data_ptrs, block_mat_data_ptr,
2403 std::make_pair(schur_is, block_is)
2408 std::pair<SmartPetscObj<Mat>, boost::shared_ptr<NestSchurData>>
2411 if (!schur_net_data_ptr)
2414 auto [mat_arrays, data_ptrs, block_mat_data_ptr, iss] = *schur_net_data_ptr;
2415 auto [schur_is, block_is] = iss;
2417 std::array<IS, 2> is_a = {schur_is, block_is};
2418 std::array<Mat, 4> mats_a = {
2420 mat_arrays[0], mat_arrays[1], mat_arrays[2], mat_arrays[3]
2425 CHKERR PetscObjectGetComm((PetscObject)mat_arrays[0], &comm);
2430 comm, 2, is_a.data(), 2, is_a.data(), mats_a.data(), &mat_raw
2441 OpSchurAssembleBase *
2443 std::vector<boost::shared_ptr<Range>> field_ents,
2446 std::vector<bool> sym_schur,
bool symm_op,
2447 boost::shared_ptr<BlockStructure> diag_blocks) {
2450 sequence_of_aos, sequence_of_mats,
2451 sym_schur, symm_op, diag_blocks);
2454 sequence_of_aos, sequence_of_mats,
2455 sym_schur, symm_op, diag_blocks);
2458 OpSchurAssembleBase *
2460 std::vector<boost::shared_ptr<Range>> field_ents,
2463 std::vector<bool> sym_schur,
2464 std::vector<double> diag_eps,
bool symm_op,
2465 boost::shared_ptr<BlockStructure> diag_blocks) {
2468 fields_name, field_ents, sequence_of_aos, sequence_of_mats, sym_schur,
2469 diag_eps, symm_op, diag_blocks);
2472 fields_name, field_ents, sequence_of_aos, sequence_of_mats, sym_schur,
2473 diag_eps, symm_op, diag_blocks);
2479 auto apply = [](PC pc,
Vec f,
Vec x) {
2487 CHKERR PCSetType(pc, PCSHELL);
2488 CHKERR PCShellSetApply(pc, apply);
2489 CHKERR PCShellSetName(pc,
"MoFEMSchurBlockPC");
2514 return MatSetValues<AssemblyTypeSelector<PETSC>>(
M, row_data, col_data, mat,
2573 col_data, mat, iora);
2605 M, row_data, col_data, mat, iora);
2622 if (block_mat_data->multiplyByPreconditioner) {
2623 block_mat_data->multiplyByPreconditioner =
false;
2625 if (!block_mat_data->preconditionerBlocksPtr) {
2627 "preconditionerBlocksPtr not set");
2629 block_mat_data->multiplyByPreconditioner =
true;
2636 std::string filename) {
2642 ReadUtilIface *iface;
2643 CHKERR moab.query_interface(iface);
2645 auto size = block_mat_data->blockIndex.size();
2648 vector<double *> arrays_coord;
2649 CHKERR iface->get_node_coords(3, 4 * size, 0, starting_vertex, arrays_coord);
2652 CHKERR iface->get_element_connect(size, 4, MBQUAD, 0, starting_handle, array);
2654 double def_val_nrm2 = 0;
2656 CHKERR moab.tag_get_handle(
"nrm2", 1, MB_TYPE_DOUBLE, th_nrm2,
2657 MB_TAG_CREAT | MB_TAG_DENSE, &def_val_nrm2);
2659 double def_val_mat_shift = 0;
2661 CHKERR moab.tag_get_handle(
"mat_shift", 1, MB_TYPE_INTEGER, th_mat_shift,
2662 MB_TAG_CREAT | MB_TAG_DENSE, &def_val_mat_shift);
2665 for (
auto &
d : block_mat_data->blockIndex) {
2666 auto row =
d.getRow();
2667 auto col =
d.getCol();
2668 auto nb_rows =
d.getNbRows();
2669 auto nb_cols =
d.getNbCols();
2670 auto mat_shift =
d.getMatShift();
2673 arrays_coord[0][4 *
i + 0] = row;
2674 arrays_coord[1][4 *
i + 0] = col;
2675 arrays_coord[2][4 *
i + 0] = 0;
2678 arrays_coord[0][4 *
i + 1] = row + nb_rows;
2679 arrays_coord[1][4 *
i + 1] = col;
2680 arrays_coord[2][4 *
i + 1] = 0;
2683 arrays_coord[0][4 *
i + 2] = row + nb_rows;
2684 arrays_coord[1][4 *
i + 2] = col + nb_cols;
2685 arrays_coord[2][4 *
i + 2] = 0;
2688 arrays_coord[0][4 *
i + 3] = row;
2689 arrays_coord[1][4 *
i + 3] = col + nb_cols;
2690 arrays_coord[2][4 *
i + 3] = 0;
2693 array[4 *
i + 0] = starting_vertex + 4 *
i + 0;
2694 array[4 *
i + 1] = starting_vertex + 4 *
i + 1;
2695 array[4 *
i + 2] = starting_vertex + 4 *
i + 2;
2696 array[4 *
i + 3] = starting_vertex + 4 *
i + 3;
2698 auto prt = &(*block_mat_data->dataBlocksPtr)[
d.getMatShift()];
2699 auto nrm2 = cblas_dnrm2(nb_rows * nb_cols, prt, 1);
2701 CHKERR moab.tag_set_data(th_nrm2, &ele, 1, &nrm2);
2702 CHKERR moab.tag_set_data(th_mat_shift, &ele, 1, &mat_shift);
2707 CHKERR iface->update_adjacencies(starting_handle, size, 4, array);
2708 CHKERR moab.write_file(filename.c_str(),
"VTK",
"");