51 S, row_ind.size(), &*row_ind.begin(), col_ind.size(), &*col_ind.begin(),
52 &*
m.data().begin(), iora
73 template <
typename OP_SCHUR_ASSEMBLE_BASE>
91 std::vector<std::string> fields_name,
92 std::vector<boost::shared_ptr<Range>> field_ents,
96 bool sym_schur,
bool symm_op);
147 struct SchurElemMats :
public boost::enable_shared_from_this<SchurElemMats> {
172 template <
typename OP_SCHUR_ASSEMBLE_BASE>
187 member<SchurElemMats, const UId, &SchurElemMats::uidRow>,
188 member<SchurElemMats, const UId, &SchurElemMats::uidCol>
197 static boost::ptr_vector<MatrixDouble>
locMats;
264 const_mem_fun<Indexes, UId, &Indexes::getRowUId>,
265 const_mem_fun<Indexes, UId, &Indexes::getColUId>>
271 const_mem_fun<Indexes, UId, &Indexes::getFEUId>
317 : iDX(idx), uidRow(uid_row), uidCol(uid_col) {}
331 auto get_row_indices = [&]() ->
const VectorInt & {
333 if (
auto stored_data_ptr =
335 return stored_data_ptr->entityIndices;
341 const auto &row_ind = get_row_indices();
344 const auto nb_rows = row_ind.size();
345 const auto nb_cols = col_ind.size();
348 if (mat.size1() != nb_rows) {
350 "Wrong mat size %d != %d", mat.size1(), nb_rows);
352 if (mat.size2() != nb_cols) {
354 "Wrong mat size %d != %d", mat.size2(), nb_cols);
359 auto get_uid = [](
auto &data) {
360 if (data.getFieldEntities().size() == 1) {
362 return data.getFieldEntities()[0]->getLocalUniqueId();
371 auto &uid0 = data.getFieldEntities()[0]->getLocalUniqueId();
377 for (
auto i = 1;
i < data.getFieldEntities().size(); ++
i) {
384 data.getFieldEntities()[
i]->getLocalUniqueId())
398 auto uid_row = get_uid(row_data);
399 auto uid_col = get_uid(col_data);
403 .find(boost::make_tuple(uid_row, uid_col));
435 auto asmb = [&](
auto &sm) {
436 sm.resize(nb_rows, nb_cols,
false);
440 asmb((*p.first)->getMat());
442 auto add_indices = [](
auto &storage,
auto &
ind) {
443 storage.resize(
ind.size(),
false);
444 noalias(storage) =
ind;
447 add_indices((*p.first)->getRowInd(), row_ind);
448 add_indices((*p.first)->getColInd(), col_ind);
453 auto asmb = [&](
auto &sm) {
457 if (sm.size1() != nb_rows) {
459 "Wrong mat or storage size %d != %d", sm.size1(), nb_rows);
461 if (sm.size2() != nb_cols) {
463 "Wrong mat or storage size %d != %d", sm.size2(), nb_cols);
476 "Assembly type not implemented");
481 CHKERR asmb((*it)->getMat());
501 MOFEM_LOG(
"SELF", Sev::noisy) <<
"Schur assemble begin";
509 template <
typename OP_SCHUR_ASSEMBLE_BASE>
511 std::vector<std::string> fields_name,
512 std::vector<boost::shared_ptr<Range>> field_ents,
515 :
OP(
NOSPACE,
OP::OPSPACE, symm_op), fieldsName(fields_name),
516 fieldEnts(field_ents), schurAO(schur_ao), schurMat(schur_mat),
517 symSchur(sym_schur) {}
519 template <
typename OP_SCHUR_ASSEMBLE_BASE>
520 template <
typename I>
527 PetscLogEventBegin(SchurEvents::MOFEM_EVENT_opSchurAssembleEnd, 0, 0, 0, 0);
532 MOFEM_LOG(
"SELF", Sev::noisy) <<
"Schur assemble begin -> end";
535 auto get_field_name = [&](
auto uid) {
537 FieldEntity::getFieldBitNumberFromUniqueId(uid)));
540 auto get_a00_uids = [&]() {
541 auto get_field_bit = [&](
auto &name) {
542 return OP::getPtrFE()->mField.get_field_bit_number(name);
545 std::vector<std::pair<UId, UId>> a00_uids;
546 a00_uids.reserve(fieldsName.size());
547 for (
auto ss = 0; ss != fieldsName.size(); ++ss) {
548 auto field_bit = get_field_bit(fieldsName[ss]);
549 auto row_ents = fieldEnts[ss];
551 for (
auto p = row_ents->pair_begin(); p != row_ents->pair_end(); ++p) {
553 FieldEntity::getLoLocalEntityBitNumber(field_bit, p->first);
555 FieldEntity::getHiLocalEntityBitNumber(field_bit, p->second);
556 a00_uids.push_back(std::make_pair(lo_uid, hi_uid));
559 auto lo_uid = FieldEntity::getLoLocalEntityBitNumber(
560 field_bit, get_id_for_min_type<MBVERTEX>());
561 auto hi_uid = FieldEntity::getHiLocalEntityBitNumber(
562 field_bit, get_id_for_max_type<MBENTITYSET>());
563 a00_uids.push_back(std::make_pair(lo_uid, hi_uid));
570 auto list_storage = [&](
auto &storage) {
573 for (
auto &p : storage) {
575 <<
"List schur storage: " <<
i <<
" " << p->iDX <<
": "
576 << get_field_name(p->uidRow) <<
" " << get_field_name(p->uidCol)
577 <<
" : " << p->getMat().size1() <<
" " << p->getMat().size2();
584 auto assemble_dense_blocks = [&]() {
585 using matrix_range = ublas::matrix_range<MatrixDouble>;
586 using range = ublas::range;
588 auto &storage = SchurElemMats::schurL2Storage;
590 auto assemble_schur = [
this](
auto &
m,
auto &uid_row,
auto &uid_col,
591 auto *row_ind_ptr,
auto *col_ind_ptr) {
596 if (
auto ierr = this->assembleSchurMat(
598 schurMat, uid_row, *row_ind_ptr, uid_col, *col_ind_ptr,
m,
603 auto field_ents = OP::getPtrFE()->mField.get_field_ents();
604 auto row_ent_it = field_ents->find(uid_row);
605 auto col_ent_it = field_ents->find(uid_col);
607 if (row_ent_it != field_ents->end())
609 <<
"Assemble row entity: " << (*row_ent_it)->getName() <<
" "
610 << (*col_ent_it)->getEntTypeName() <<
" side "
611 << (*row_ent_it)->getSideNumber();
612 if (col_ent_it != field_ents->end())
614 <<
"Assemble col entity: " << (*col_ent_it)->getName() <<
" "
615 << (*col_ent_it)->getEntTypeName() <<
" side "
616 << (*col_ent_it)->getSideNumber();
625 auto a00_uids = get_a00_uids();
627 auto get_block_indexing = [&](
auto &a00_uids) {
629 std::vector<const SchurElemMats *> block_list;
630 block_list.reserve(storage.size());
631 for (
auto &rp_uid : a00_uids) {
632 auto [rlo_uid, rhi_uid] = rp_uid;
633 for (
auto &cp_uid : a00_uids) {
634 auto [clo_uid, chi_uid] = cp_uid;
637 storage.template get<SchurElemMats::uid_mi_tag>().lower_bound(
638 boost::make_tuple(rlo_uid, clo_uid));
640 storage.template get<SchurElemMats::uid_mi_tag>().upper_bound(
641 boost::make_tuple(rhi_uid, chi_uid));
643 for (; it != hi_it; ++it) {
644 if ((*it)->uidRow >= rlo_uid && (*it)->uidRow < rhi_uid &&
645 (*it)->uidCol >= clo_uid && (*it)->uidCol < chi_uid) {
646 block_list.push_back(*it);
653 std::map<UId, std::pair<size_t, const VectorInt *>>
655 for (
auto d : block_list) {
656 if (block_indexing.find(
d->uidRow) == block_indexing.end()) {
657 block_indexing[
d->uidRow] =
658 std::make_pair(
d->getRowInd().size(), &(
d->getRowInd()));
663 int mat_block_size = 0;
664 for (
auto &p_uid : a00_uids) {
665 auto [lo_uid, hi_uid] = p_uid;
666 auto lo = block_indexing.lower_bound(lo_uid);
667 auto up = block_indexing.upper_bound(hi_uid);
668 for (; lo != up; ++lo) {
669 lo->second.first = mat_block_size;
670 mat_block_size += lo->second.second->size();
674 return std::make_tuple(block_list, block_indexing, mat_block_size);
677 auto get_schur_block_list = [&](
auto &block_indexing) {
678 std::vector<const SchurElemMats *> block_list;
679 block_list.reserve(storage.size());
680 for (
auto &s : storage) {
681 if (block_indexing.find(s->uidRow) == block_indexing.end() &&
682 block_indexing.find(s->uidCol) == block_indexing.end()) {
683 block_list.push_back(s);
689 auto [block_list, block_indexing, block_mat_size] =
690 get_block_indexing(a00_uids);
692 if (block_mat_size == 0) {
695 for (
auto &s : storage) {
696 CHKERR AOApplicationToPetsc(schurAO, s->getRowInd().size(),
697 &*s->getRowInd().begin());
698 CHKERR AOApplicationToPetsc(schurAO, s->getColInd().size(),
699 &*s->getColInd().begin());
703 for (
auto &s : storage) {
704 auto &
m = s->getMat();
705 CHKERR assemble_schur(
m, s->uidRow, s->uidCol, &(s->getRowInd()),
711 blockMat.resize(block_mat_size, block_mat_size,
false);
714 auto get_range = [](
auto &bi) {
715 return range(bi.first, bi.first + bi.second->size());
718 for (
auto &s : block_list) {
719 auto &
m = s->getMat();
721 if (block_indexing.find(s->uidRow) == block_indexing.end())
723 if (block_indexing.find(s->uidCol) == block_indexing.end())
727 auto &rbi = block_indexing.at(s->uidRow);
728 auto &cbi = block_indexing.at(s->uidCol);
730 auto sub_mat = matrix_range(blockMat, get_range(rbi), get_range(cbi));
734 auto get_zeroed_indices = [&](
auto extractor_uid,
auto extractor_ind) {
735 std::vector<int> zeroed_indices;
736 zeroed_indices.reserve(block_mat_size);
737 for (
auto &s : block_list) {
738 auto &bi = block_indexing.at(extractor_uid(s));
739 auto &
ind = extractor_ind(s);
740 for (
auto it =
ind.begin(); it !=
ind.end(); ++it) {
742 auto idx = bi.first + std::distance(
ind.begin(), it);
743 zeroed_indices.push_back(idx);
747 std::sort(zeroed_indices.begin(), zeroed_indices.end());
748 auto it = std::unique(zeroed_indices.begin(), zeroed_indices.end());
749 zeroed_indices.resize(std::distance(zeroed_indices.begin(), it));
750 return zeroed_indices;
752 auto zero_rows = get_zeroed_indices(
753 [](
auto &s) {
return s->uidRow; },
754 [](
auto &s) ->
VectorInt & {
return s->getRowInd(); });
755 auto zero_cols = get_zeroed_indices(
756 [](
auto &s) {
return s->uidCol; },
757 [](
auto &s) ->
VectorInt & {
return s->getColInd(); });
759 for (
auto i : zero_rows) {
760 for (
auto j = 0;
j != blockMat.size2(); ++
j) {
764 for (
auto j : zero_cols) {
765 for (
auto i = 0;
i != blockMat.size1(); ++
i) {
769 for (
auto i : zero_rows) {
773 CHKERR I::invertMat(blockMat, invMat);
776 for (
auto &s : block_list) {
777 auto it = storage.template get<SchurElemMats::uid_mi_tag>().find(
778 boost::make_tuple(s->uidRow, s->uidCol));
779 storage.template get<SchurElemMats::uid_mi_tag>().erase(it);
784 for (
auto &s : storage) {
785 if (block_indexing.find(s->uidRow) == block_indexing.end()) {
786 CHKERR AOApplicationToPetsc(schurAO, s->getRowInd().size(),
787 &*s->getRowInd().begin());
789 if (block_indexing.find(s->uidCol) == block_indexing.end()) {
790 CHKERR AOApplicationToPetsc(schurAO, s->getColInd().size(),
791 &*s->getColInd().begin());
796 auto schur_block_list = get_schur_block_list(block_indexing);
797 for(
auto &s : schur_block_list) {
798 auto &
m = s->getMat();
799 CHKERR assemble_schur(
m, s->uidRow, s->uidCol, &(s->getRowInd()),
802 for (
auto &s : schur_block_list) {
803 auto it = storage.template get<SchurElemMats::uid_mi_tag>().find(
804 boost::make_tuple(s->uidRow, s->uidCol));
805 storage.template get<SchurElemMats::uid_mi_tag>().erase(it);
807 schur_block_list.clear();
811 auto rp_uid_it = a00_uids.begin(); rp_uid_it != a00_uids.end();
815 auto [rlo_uid, rhi_uid] = *rp_uid_it;
816 for (
auto rm = block_indexing.lower_bound(rlo_uid);
817 rm != block_indexing.upper_bound(rhi_uid); ++rm) {
818 auto &rbi = rm->second;
821 storage.template get<SchurElemMats::col_mi_tag>().lower_bound(
824 storage.template get<SchurElemMats::col_mi_tag>().upper_bound(
829 auto cp_uid_it = (symSchur) ? rp_uid_it : a00_uids.begin();
830 cp_uid_it != a00_uids.end(); ++cp_uid_it
833 auto [clo_uid, chi_uid] = *cp_uid_it;
834 for (
auto cm = block_indexing.lower_bound(clo_uid);
835 cm != block_indexing.upper_bound(chi_uid); ++cm) {
836 auto &cbi = cm->second;
839 storage.template get<SchurElemMats::uid_mi_tag>().lower_bound(
840 boost::make_tuple(cm->first, 0));
842 storage.template get<SchurElemMats::uid_mi_tag>().upper_bound(
843 boost::make_tuple(cm->first, FieldEntity::getHiBitNumberUId(
847 matrix_range(invMat, get_range(rbi), get_range(cbi));
848 bM.resize(sub_inv_mat.size1(), sub_inv_mat.size2());
849 noalias(bM) = sub_inv_mat;
851 for (
auto a_lo = a_lo_tmp; a_lo != a_hi; ++a_lo) {
853 if (block_indexing.find((*a_lo)->uidRow) != block_indexing.end())
855 "Wrong a_lo->uidRow");
858 auto &
a = (*a_lo)->getMat();
859 abM.resize(
a.size1(), bM.size2(),
false);
861 cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
863 a.size1(), bM.size2(),
a.size2(), 1.,
865 &*
a.data().begin(),
a.size2(),
867 &*bM.data().begin(), bM.size2(), 0.,
869 &*abM.data().begin(), abM.size2());
871 for (
auto c_lo = c_lo_tmp; c_lo != c_hi; ++c_lo) {
873 if (block_indexing.find((*c_lo)->uidCol) !=
874 block_indexing.end())
876 "Wrong a_lo->uidRow");
879 auto &
c = (*c_lo)->getMat();
881 abcM.resize(abM.size1(),
c.size2(),
false);
884 cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
885 abM.size1(),
c.size2(), abM.size2(), -1.,
887 &*abM.data().begin(), abM.size2(),
889 &*
c.data().begin(),
c.size2(), 0.,
891 &*abcM.data().begin(), abcM.size2());
893 CHKERR assemble_schur(abcM, (*a_lo)->uidRow, (*c_lo)->uidCol,
894 &((*a_lo)->getRowInd()),
895 &((*c_lo)->getColInd()));
897 if (symSchur && rp_uid_it != cp_uid_it) {
899 CHKERR assemble_schur(abcM, (*c_lo)->uidCol, (*a_lo)->uidRow,
900 &((*c_lo)->getColInd()),
901 &((*a_lo)->getRowInd()));
914 CHKERR assemble_dense_blocks();
918 MOFEM_LOG(
"SELF", Sev::noisy) <<
"Schur assemble done";
922 PetscLogEventEnd(SchurEvents::MOFEM_EVENT_opSchurAssembleEnd, 0, 0, 0, 0);
933 const auto nb =
m.size1();
935 if (nb !=
m.size2()) {
937 "It should be square matrix %d != %d", nb,
m.size2());
941 inv.resize(nb, nb,
false);
943 m.resize(2 * nb, 2 * nb,
false);
950 info =
lapack_dgetrf(nb, nb, &*inv.data().begin(), nb, &*ipiv.begin());
953 "lapack error info = %d", info);
954 info =
lapack_dgetri(nb, &*inv.data().begin(), nb, &*ipiv.begin(),
955 &*
m.data().begin(),
m.data().size());
958 "lapack error info = %d", info);
969 const auto nb =
m.size1();
971 if (nb !=
m.size2()) {
973 "It should be square matrix %d != %d", nb,
m.size2());
977 inv.resize(nb, nb,
false);
983 info =
lapack_dgetrf(nb, nb, &*inv.data().begin(), nb, &*ipiv.begin());
986 "lapack error info = %d", info);
987 info =
lapack_dgetri(nb, &*inv.data().begin(), nb, &*ipiv.begin(),
988 &*
m.data().begin(),
m.data().size());
991 "lapack error info = %d", info);
1000 return doWorkImpl<SchurDSYSV>(side,
type, data);
1006 return doWorkImpl<SchurDGESV>(side,
type, data);
1016 auto cmp_uid_lo = [](
const boost::weak_ptr<FieldEntity> &
a,
const UId &b) {
1017 if (
auto a_ptr =
a.lock()) {
1018 if (a_ptr->getLocalUniqueId() < b)
1027 auto cmp_uid_hi = [](
const UId &b,
const boost::weak_ptr<FieldEntity> &
a) {
1028 if (
auto a_ptr =
a.lock()) {
1029 if (b < a_ptr->getLocalUniqueId())
1039 auto get_uid_pair = [](
const auto &field_id) {
1040 auto lo_uid = FieldEntity::getLocalUniqueIdCalculate(
1041 field_id, get_id_for_min_type<MBVERTEX>());
1042 auto hi_uid = FieldEntity::getLocalUniqueIdCalculate(
1043 field_id, get_id_for_max_type<MBENTITYSET>());
1044 return std::make_pair(lo_uid, hi_uid);
1049 auto lo = std::lower_bound(field_ents.begin(), field_ents.end(),
1051 auto hi = std::upper_bound(field_ents.begin(), field_ents.end(),
1053 return std::make_pair(lo, hi);
1058 auto row_extractor = [](
auto &e) {
return e->entityCacheRowDofs; };
1059 auto col_extractor = [](
auto &e) {
return e->entityCacheColDofs; };
1061 auto extract_data = [](
auto &&its,
auto extractor) {
1062 std::vector<std::tuple<UId, int, int, int>> data;
1063 data.reserve(std::distance(its.first, its.second));
1065 for (; its.first != its.second; ++its.first) {
1066 if (
auto e = its.first->lock()) {
1067 if (
auto cache = extractor(e).lock()) {
1069 for (
auto dof = cache->loHi[0]; dof != cache->loHi[1]; ++dof) {
1070 if ((*dof)->getPetscGlobalDofIdx() != -1)
1073 auto uid = e->getLocalUniqueId();
1076 auto glob = (*cache->loHi[0])->getPetscGlobalDofIdx();
1077 auto loc = (*cache->loHi[0])->getPetscLocalDofIdx();
1078 while (glob == -1 && cache->loHi[0] != cache->loHi[1]) {
1080 glob = (*cache->loHi[0])->getPetscGlobalDofIdx();
1081 loc = (*cache->loHi[0])->getPetscLocalDofIdx();
1083 data.emplace_back(uid, glob, nb_dofs, loc);
1087 for (
auto lo = cache->loHi[0]; lo != cache->loHi[1]; ++lo) {
1088 auto glob = (*lo)->getPetscGlobalDofIdx();
1091 "Wrong global index");
1097 data.emplace_back(uid, -1, 0, -1);
1105 auto data_ptr = boost::make_shared<BlockStructure>();
1109 auto fe_method = boost::shared_ptr<MoFEM::FEMethod>(
new MoFEM::FEMethod());
1111 for (
auto &
d : schur_fe_op_vec) {
1114 auto get_bit_numbers = [&
d](
auto op) {
1115 std::vector<FieldBitNumber> bit_numbers(
d.second.size());
1121 auto row_bit_numbers = get_bit_numbers(
1122 [&](
auto &p) {
return m_field_ptr->get_field_bit_number(p.first); });
1124 auto col_bit_numbers = get_bit_numbers(
1125 [&](
auto &p) {
return m_field_ptr->get_field_bit_number(p.second); });
1127 fe_method->preProcessHook = []() {
return 0; };
1128 fe_method->postProcessHook = []() {
return 0; };
1129 fe_method->operatorHook = [&]() {
1132 auto fe_uid = fe_method->numeredEntFiniteElementPtr->getLocalUniqueId();
1134 for (
auto f = 0;
f != row_bit_numbers.size(); ++
f) {
1137 extract_data(get_it_pair(fe_method->getRowFieldEnts(),
1138 get_uid_pair(row_bit_numbers[
f])),
1141 extract_data(get_it_pair(fe_method->getColFieldEnts(),
1142 get_uid_pair(col_bit_numbers[
f])),
1145 for (
auto &
r : row_data) {
1146 auto [r_uid, r_glob, r_nb_dofs, r_loc] =
r;
1147 for (
auto &
c : col_data) {
1148 auto [c_uid, c_glob, c_nb_dofs, c_loc] =
c;
1150 r_uid, c_uid, fe_uid, r_glob, c_glob, r_nb_dofs, c_nb_dofs,
1160 m_field_ptr->get_comm_size());
1165 for (
auto &
v : data_ptr->blockIndex.get<0>()) {
1166 v.getMatShift() = mem_size;
1167 mem_size +=
v.getNbCols() *
v.getNbRows();
1170 std::vector<double> tmp;
1171 if (mem_size > tmp.max_size())
1174 data_ptr->dataBlocksPtr =
1175 boost::make_shared<std::vector<double>>(mem_size, 0);
1179 CHKERR VecSetDM(ghost_x, PETSC_NULL);
1180 CHKERR VecSetDM(ghost_y, PETSC_NULL);
1182 data_ptr->ghostX = ghost_x;
1183 data_ptr->ghostY = ghost_y;
1189 Mat mat,
Vec x,
Vec y, InsertMode iora,
1191 int(DiagBlockIndex::BlockIndex::nth_index<0>::type::iterator)>
1193 boost::shared_ptr<std::vector<double>> data_blocks_ptr,
1194 bool multiply_by_preconditioner);
1201 CHKERR MatShellGetContext(mat, (
void **)&ctx);
1203 mat, x, y, INSERT_VALUES,
1205 [](DiagBlockIndex::BlockIndex::nth_index<0>::type::iterator it) {
1206 return it->getMatShift();
1209 ctx->dataBlocksPtr,
true);
1213 CHKERR MatShellGetContext(mat, (
void **)&ctx);
1215 mat, x, y, ADD_VALUES,
1217 [](DiagBlockIndex::BlockIndex::nth_index<0>::type::iterator it) {
1218 return it->getMatShift();
1221 ctx->dataBlocksPtr,
true);
1231 const PetscInt rows[], PetscScalar diag,
1236 CHKERR MatShellGetContext(
A, (
void **)&ctx);
1238 PetscLogEventBegin(SchurEvents::MOFEM_EVENT_zeroRowsAndCols, 0, 0, 0, 0);
1240 using BlockIndexView = multi_index_container<
1249 &DiagBlockIndex::Indexes::rowShift>
1256 &DiagBlockIndex::Indexes::colShift>
1262 BlockIndexView view;
1263 auto hint = view.get<0>().end();
1264 for (
auto &
v : ctx->blockIndex) {
1265 hint = view.insert(hint, &
v);
1268 const int *ptr = &rows[0];
1273 CHKERR PetscObjectGetComm((PetscObject)
A, &comm);
1275 MPI_Comm_size(comm, &size);
1281 CHKERR ISGetSize(is_local, &is_nb_rows);
1284 CHKERR ISView(is_local, PETSC_VIEWER_STDOUT_WORLD);
1287 CHKERR ISGetIndices(is_local, &ptr);
1291 CHKERR MatGetLocalSize(
A, &loc_m, &loc_n);
1293 for (
auto n = 0;
n != is_nb_rows; ++
n) {
1295 auto rlo = view.get<0>().lower_bound(row);
1296 auto rhi = view.get<0>().end();
1297 for (; rlo != rhi; ++rlo) {
1298 auto r_shift = row - (*rlo)->getRow();
1299 if (r_shift >= 0 && r_shift < (*rlo)->getNbRows()) {
1300 auto *ptr = &(*ctx->dataBlocksPtr)[(*rlo)->getMatShift()];
1301 for (
auto i = 0;
i != (*rlo)->getNbCols(); ++
i) {
1302 ptr[
i + r_shift * (*rlo)->getNbCols()] = 0;
1304 }
else if ((*rlo)->getRow() + (*rlo)->getNbRows() > row) {
1310 for (
auto n = 0;
n != is_nb_rows; ++
n) {
1312 auto clo = view.get<1>().lower_bound(col);
1313 auto chi = view.get<1>().end();
1314 for (; clo != chi; ++clo) {
1315 auto c_shift = col - (*clo)->getCol();
1316 if (c_shift >= 0 && c_shift < (*clo)->getNbCols()) {
1318 auto *ptr = &(*ctx->dataBlocksPtr)[(*clo)->getMatShift()];
1319 for (
auto i = 0;
i != (*clo)->getNbRows(); ++
i) {
1320 ptr[c_shift +
i * (*clo)->getNbCols()] = 0;
1326 (*clo)->getRow() == (*clo)->getCol() &&
1327 (*clo)->getLocRow() < loc_m && (*clo)->getLocCol() < loc_n
1330 auto r_shift = col - (*clo)->getCol();
1331 if (r_shift >= 0 && r_shift < (*clo)->getNbRows()) {
1332 ptr[c_shift + r_shift * (*clo)->getNbCols()] = diag;
1335 }
else if ((*clo)->getCol() + (*clo)->getNbCols() > col) {
1342 CHKERR ISRestoreIndices(is_local, &ptr);
1345 PetscLogEventEnd(SchurEvents::MOFEM_EVENT_zeroRowsAndCols, 0, 0, 0, 0);
1353 CHKERR MatShellGetContext(
m, (
void **)&ctx);
1354 if (ctx->dataBlocksPtr)
1355 std::fill(ctx->dataBlocksPtr->begin(), ctx->dataBlocksPtr->end(), 0.);
1356 if (ctx->preconditionerBlocksPtr)
1357 std::fill(ctx->preconditionerBlocksPtr->begin(),
1358 ctx->preconditionerBlocksPtr->end(), 0.);
1364 CHKERR MatShellSetManageScalingShifts(mat_raw);
1365 CHKERR MatShellSetOperation(mat_raw, MATOP_MULT, (
void (*)(
void))
mult);
1366 CHKERR MatShellSetOperation(mat_raw, MATOP_MULT_ADD,
1368 CHKERR MatShellSetOperation(mat_raw, MATOP_SOLVE, (
void (*)(
void))
solve);
1369 CHKERR MatShellSetOperation(mat_raw, MATOP_SOLVE_ADD,
1371 CHKERR MatShellSetOperation(mat_raw, MATOP_ZERO_ENTRIES,
1373 CHKERR MatShellSetOperation(mat_raw, MATOP_ZERO_ROWS_COLUMNS,
1380 boost::shared_ptr<BlockStructure> data) {
1383 auto nb_local = problem_ptr->nbLocDofsRow;
1384 auto nb_global = problem_ptr->nbDofsRow;
1387 if (nb_local != problem_ptr->nbLocDofsCol) {
1389 <<
"Wrong size " << nb_local <<
" != " << problem_ptr->nbLocDofsCol;
1391 "nb. cols is inconsistent with nb. rows");
1393 if (nb_global != problem_ptr->nbDofsCol) {
1395 <<
"Wrong size " << nb_global <<
" != " << problem_ptr->nbDofsCol;
1397 "nb. cols is inconsistent with nb. rows");
1402 CHKERR PetscObjectGetComm((PetscObject)dm, &comm);
1405 CHKERR MatCreateShell(comm, nb_local, nb_local, nb_global, nb_global,
1406 (
void *)data.get(), &mat_raw);
1416 Mat mat,
Vec x,
Vec y, InsertMode iora,
1419 int(DiagBlockIndex::BlockIndex::nth_index<0>::type::iterator)>
1422 boost::shared_ptr<std::vector<double>> data_blocks_ptr,
1423 bool multiply_by_preconditioner) {
1426 CHKERR MatShellGetContext(mat, (
void **)&ctx);
1428 PetscLogEventBegin(SchurEvents::MOFEM_EVENT_BlockStructureMult, 0, 0, 0, 0);
1431 CHKERR VecGetLocalSize(x, &x_loc_size);
1433 CHKERR VecGetLocalSize(y, &y_loc_size);
1435 Vec ghost_x = ctx->ghostX;
1436 Vec ghost_y = ctx->ghostY;
1438 CHKERR VecCopy(x, ghost_x);
1442 CHKERR VecGhostGetLocalForm(ghost_y, &loc_ghost_y);
1444 CHKERR VecGetLocalSize(loc_ghost_y, &nb_y);
1445 CHKERR VecGetArray(loc_ghost_y, &y_array);
1446 for (
auto i = 0;
i != nb_y; ++
i)
1448 CHKERR VecRestoreArray(loc_ghost_y, &y_array);
1449 CHKERR VecGhostRestoreLocalForm(ghost_y, &loc_ghost_y);
1451 auto mult = [&](
int low_x,
int hi_x,
int low_y,
int hi_y) {
1456 CHKERR VecGhostGetLocalForm(ghost_x, &loc_ghost_x);
1457 CHKERR VecGetArray(loc_ghost_x, &x_array);
1461 CHKERR VecGhostGetLocalForm(ghost_y, &loc_ghost_y);
1463 CHKERR VecGetLocalSize(loc_ghost_y, &nb_y);
1464 CHKERR VecGetArray(loc_ghost_y, &y_array);
1466 double *block_ptr = &*data_blocks_ptr->begin();
1467 auto it = ctx->blockIndex.get<0>().begin();
1468 auto hi = ctx->blockIndex.get<0>().end();
1471 if (it->getLocRow() < low_y || it->getLocRow() >= hi_y ||
1472 it->getLocCol() < low_x || it->getLocCol() >= hi_x) {
1477 auto nb_rows = it->getNbRows();
1478 auto nb_cols = it->getNbCols();
1479 auto x_ptr = &x_array[it->getLocCol()];
1480 auto y_ptr = &y_array[it->getLocRow()];
1481 auto ptr = &block_ptr[shift_extractor(it)];
1484 cblas_dgemv(CblasRowMajor, CblasNoTrans, nb_rows, nb_cols, 1.0, ptr,
1485 nb_cols, x_ptr, 1, 1.0, y_ptr, 1);
1487 for (
auto r = 0;
r != nb_rows; ++
r) {
1488 for (
auto c = 0;
c != nb_cols; ++
c) {
1489 y_ptr[
r] += ptr[
r * nb_cols +
c] * x_ptr[
c];
1496 if (multiply_by_preconditioner && ctx->multiplyByPreconditioner) {
1498 if (!ctx->preconditionerBlocksPtr)
1500 "No parentBlockStructurePtr");
1502 auto preconditioner_ptr = &*ctx->preconditionerBlocksPtr->begin();
1504 auto it = ctx->blockIndex.get<0>().begin();
1505 auto hi = ctx->blockIndex.get<0>().end();
1508 if (it->getLocRow() < low_y || it->getLocRow() >= hi_y ||
1509 it->getLocCol() < low_x || it->getLocCol() >= hi_x) {
1514 if (it->getMatShift() != -1) {
1515 auto nb_rows = it->getNbRows();
1516 auto nb_cols = it->getNbCols();
1517 auto x_ptr = &x_array[it->getLocCol()];
1518 auto y_ptr = &y_array[it->getLocRow()];
1519 auto ptr = &preconditioner_ptr[it->getMatShift()];
1521 cblas_dgemv(CblasRowMajor, CblasNoTrans, nb_rows, nb_cols, 1.0, ptr,
1522 nb_cols, x_ptr, 1, 1.0, y_ptr, 1);
1524 for (
auto r = 0;
r != nb_rows; ++
r) {
1525 for (
auto c = 0;
c != nb_cols; ++
c) {
1526 y_ptr[
r] += ptr[
r * nb_cols +
c] * x_ptr[
c];
1536 CHKERR VecRestoreArray(loc_ghost_x, &x_array);
1537 CHKERR VecRestoreArray(loc_ghost_y, &y_array);
1538 CHKERR VecGhostRestoreLocalForm(ghost_x, &loc_ghost_x);
1539 CHKERR VecGhostRestoreLocalForm(ghost_y, &loc_ghost_y);
1543 constexpr
auto max_int = std::numeric_limits<int>::max();
1544 CHKERR VecGhostUpdateBegin(ghost_x, INSERT_VALUES, SCATTER_FORWARD);
1546 CHKERR VecGhostUpdateEnd(ghost_x, INSERT_VALUES, SCATTER_FORWARD);
1547 CHKERR mult(x_loc_size, max_int, 0, max_int);
1549 CHKERR VecGhostUpdateBegin(ghost_y, ADD_VALUES, SCATTER_REVERSE);
1550 CHKERR VecGhostUpdateEnd(ghost_y, ADD_VALUES, SCATTER_REVERSE);
1554 CHKERR VecCopy(ghost_y, y);
1557 CHKERR VecAXPY(y, 1., ghost_y);
1565 auto print_norm = [&](
auto msg,
auto y) {
1568 CHKERR VecNorm(y, NORM_2, &norm);
1570 CHKERR VecGetLocalSize(y, &nb_loc_y);
1572 CHKERR VecGetSize(y, &nb_y);
1574 << msg <<
" " << nb_y <<
" " << nb_loc_y <<
" norm " << norm;
1580 print_norm(
"mult_schur_block_shell insert x", x);
1581 print_norm(
"mult_schur_block_shell insert y", y);
1584 print_norm(
"mult_schur_block_shell add x", x);
1585 print_norm(
"mult_schur_block_shell add y", y);
1594 PetscLogEventEnd(SchurEvents::MOFEM_EVENT_BlockStructureMult, 0, 0, 0, 0);
1601 using matrix_range = ublas::matrix_range<MatrixDouble>;
1602 using range = ublas::range;
1605 CHKERR MatShellGetContext(mat, (
void **)&ctx);
1607 PetscLogEventBegin(SchurEvents::MOFEM_EVENT_BlockStructureSolve, 0, 0, 0, 0);
1609 if (ctx->multiplyByPreconditioner) {
1610 if (!ctx->preconditionerBlocksPtr)
1612 "No preconditionerBlocksPtr");
1615 if (iora == INSERT_VALUES) {
1616 CHKERR VecZeroEntries(x);
1620 CHKERR VecGetArray(x, &x_array);
1622 CHKERR VecGetArray(y, &y_array);
1624 std::vector<const DiagBlockIndex::Indexes *> blocks;
1629 auto &block_index = ctx->blockIndex.get<1>();
1630 for (
auto it = block_index.begin(); it != block_index.end();) {
1634 auto last_uid = it->getFEUId();
1635 while (it != block_index.end() && it->getFEUId() == last_uid) {
1636 blocks.push_back(&*it);
1641 std::map<UId, std::tuple<int, int, int>> block_indexing;
1642 for (
auto b : blocks) {
1643 if (block_indexing.find(b->getRowUId()) == block_indexing.end()) {
1644 block_indexing[b->getRowUId()] =
1645 std::make_tuple(b->getNbRows(), b->getNbRows(), b->getLocRow());
1648 std::sort(blocks.begin(), blocks.end(), [](
auto a,
auto b) {
1649 if (a->getRowUId() == b->getRowUId())
1650 return a->getColUId() < b->getColUId();
1652 return a->getRowUId() < b->getRowUId();
1656 int mat_block_size = 0;
1657 for (
auto &b : block_indexing) {
1658 auto &[index, size, loc] = b.second;
1659 index = mat_block_size;
1660 mat_block_size += size;
1663 auto get_range = [](
auto &b) {
1664 auto [index, size, loc] = b;
1665 return range(index, index + size);
1668 std::vector<std::tuple<int, int, int, int, int>> block_data;
1669 block_data.reserve(blocks.size());
1670 for (
auto s : blocks) {
1671 auto ruid = s->getRowUId();
1672 auto cuid = s->getColUId();
1673 auto &rbi = block_indexing.at(ruid);
1674 auto &cbi = block_indexing.at(cuid);
1675 if (
auto shift = s->getMatShift(); shift != -1) {
1676 block_data.push_back(std::make_tuple(
1680 s->getNbRows(), s->getNbCols(),
1682 get<0>(rbi), get<0>(cbi))
1687 block_mat.resize(mat_block_size, mat_block_size,
false);
1689 for (
auto &bd : block_data) {
1690 auto &[shift, nb_rows, nb_cols, ridx, cidx] = bd;
1691 auto ptr = &(*(ctx->dataBlocksPtr))[shift];
1692 for (
auto i = 0;
i != nb_rows; ++
i, ptr += nb_cols) {
1694 cblas_dcopy(nb_cols, ptr, 1, sub_ptr, 1);
1697 if (ctx->multiplyByPreconditioner) {
1698 for (
auto &bd : block_data) {
1699 auto &[shift, nb_rows, nb_cols, ridx, cidx] = bd;
1700 auto ptr = &(*(ctx->preconditionerBlocksPtr))[shift];
1701 for (
auto i = 0;
i != nb_rows; ++
i, ptr += nb_cols) {
1703 cblas_daxpy(nb_cols, 1., ptr, 1, sub_ptr, 1);
1709 block_y.resize(mat_block_size,
false);
1712 for (
auto &b : block_indexing) {
1713 auto [index, size, loc] = b.second;
1714 auto ptr = &y_array[loc];
1715 cblas_dcopy(size, ptr, 1, &block_y[index], 1);
1719 constexpr
int nrhs = 1;
1720 ipiv.resize(mat_block_size,
false);
1722 mat_block_size, &*ipiv.data().begin(),
1723 &*block_y.data().begin(), mat_block_size);
1726 "error lapack solve dgesv info = %d", info);
1729 for (
auto &b : block_indexing) {
1730 auto [index, size, loc] = b.second;
1731 auto ptr = &x_array[loc];
1732 cblas_daxpy(size, 1.0, &block_y[index], 1, ptr, 1);
1736 CHKERR VecRestoreArray(x, &x_array);
1737 CHKERR VecRestoreArray(y, &y_array);
1740 PetscLogEventEnd(SchurEvents::MOFEM_EVENT_BlockStructureSolve, 0, 0, 0, 0);
1750 boost::shared_ptr<std::vector<double>> data_blocks_ptr) {
1761 PetscLogEventBegin(SchurEvents::MOFEM_EVENT_BlockStructureSetValues, 0, 0, 0,
1774 auto get_row_data = [&]() -> std::pair<bool, VectorInt> {
1776 if (
auto stored_data_ptr =
1778 MOFEM_LOG(
"SELF", Sev::warning) <<
"Can lead to unhandled behaviour";
1779 return std::make_pair(
true, stored_data_ptr->entityIndices);
1782 return std::make_pair(
false, row_data.
getIndices());
1785 auto row_indices = get_row_data();
1787 std::vector<int> ent_row_indices;
1788 std::vector<int> ent_col_indices;
1791 if (
auto r_cache = rent->entityCacheRowDofs.lock()) {
1793 auto &row_uid = rent->getLocalUniqueId();
1794 auto &row_ind = row_indices.second;
1797 if (
auto c_cache = cent->entityCacheColDofs.lock()) {
1799 auto &col_uid = cent->getLocalUniqueId();
1804 boost::make_tuple(row_uid, col_uid)
1813 <<
"missing block: row "
1817 "Block not allocated");
1822 auto ri = row_ind.begin();
1823 auto rie = row_ind.end();
1825 auto shift = shift_extractor(&*it);
1826 auto s_mat = &(*data_blocks_ptr)[shift];
1828 auto get_ent_indices = [](
auto &cache,
auto &
ind) {
1830 ind.reserve(std::distance(cache->loHi[0], cache->loHi[1]));
1831 for (
auto e = cache->loHi[0]; e != cache->loHi[1]; ++e) {
1832 auto glob = (*e)->getPetscGlobalDofIdx();
1834 ind.push_back(glob);
1838 get_ent_indices(r_cache, ent_row_indices);
1839 if (ent_row_indices.empty())
1841 get_ent_indices(c_cache, ent_col_indices);
1842 if (ent_col_indices.empty())
1845 if (mat.size1() == ent_row_indices.size() &&
1846 mat.size2() == ent_col_indices.size()) {
1848 if (iora == ADD_VALUES) {
1849 cblas_daxpy(mat.data().size(), 1.0, mat.data().data(), 1, s_mat,
1852 cblas_dcopy(mat.data().size(), mat.data().data(), 1, s_mat, 1);
1858 for (
auto re : ent_row_indices) {
1859 ri = std::find(ri, rie, re);
1860 if (!(ri == rie && *ri != -1)) {
1862 auto ci = col_ind.begin();
1863 auto cie = col_ind.end();
1864 auto ce = c_cache->loHi[0];
1867 for (
auto ce : ent_col_indices) {
1868 ci = std::find(ci, cie, ce);
1869 if (!(ci == cie && *ci != -1)) {
1870 auto &
m = s_mat[row * ent_col_indices.size() + col];
1871 if (iora == ADD_VALUES) {
1872 m += mat(std::distance(row_ind.begin(), ri),
1873 std::distance(col_ind.begin(), ci));
1875 m = mat(std::distance(row_ind.begin(), ri),
1876 std::distance(col_ind.begin(), ci));
1892 PetscLogEventEnd(SchurEvents::MOFEM_EVENT_BlockStructureSetValues, 0, 0, 0,
1904 PetscBool is_mat_shell = PETSC_FALSE;
1905 PetscObjectTypeCompare((PetscObject)
M, MATSHELL, &is_mat_shell);
1908 CHKERR MatShellGetContext(
M, (
void **)&ctx);
1910 ctx, row_data, col_data, mat, iora,
1912 ctx->dataBlocksPtr);
1914 CHKERR MatSetValues<AssemblyTypeSelector<PETSC>>(
M, row_data, col_data, mat,
1925 PetscBool is_mat_shell = PETSC_FALSE;
1926 PetscObjectTypeCompare((PetscObject)
M, MATSHELL, &is_mat_shell);
1929 CHKERR MatShellGetContext(
M, (
void **)&ctx);
1930 if (!ctx->preconditionerBlocksPtr)
1932 "No preconditionerBlocksPtr");
1934 ctx, row_data, col_data, mat, iora,
1936 ctx->preconditionerBlocksPtr);
1938 CHKERR MatSetValues<AssemblyTypeSelector<PETSC>>(
M, row_data, col_data, mat,
1947 boost::shared_ptr<BlockStructure> block_mat_data_ptr,
1949 std::vector<std::string> fields_names,
1950 std::vector<boost::shared_ptr<Range>>
1952 bool add_preconditioner_block) {
1954 if (!block_mat_data_ptr) {
1958 if (fields_names.size() != field_ents.size())
1960 "fields_names.size() != field_ents.size()");
1962 auto [schur_dm, block_dm] = dms;
1967 auto schur_dofs_row = schur_prb->getNumeredRowDofsPtr();
1968 auto schur_dofs_col = schur_prb->getNumeredColDofsPtr();
1969 auto block_dofs_row = block_prb->getNumeredRowDofsPtr();
1970 auto block_dofs_col = block_prb->getNumeredColDofsPtr();
1972 auto ao_schur_row = schur_prb->getSubData()->getSmartRowMap();
1973 auto ao_schur_col = schur_prb->getSubData()->getSmartColMap();
1974 auto ao_block_row = block_prb->getSubData()->getSmartRowMap();
1975 auto ao_block_col = block_prb->getSubData()->getSmartColMap();
1981 CHKERR VecSetDM(schur_vec_x, PETSC_NULL);
1982 CHKERR VecSetDM(block_vec_x, PETSC_NULL);
1983 CHKERR VecSetDM(schur_vec_y, PETSC_NULL);
1984 CHKERR VecSetDM(block_vec_y, PETSC_NULL);
1986 auto find_field_ent = [&](
auto uid,
auto prb,
auto rc) {
1987 boost::shared_ptr<NumeredDofEntity_multiIndex> dofs;
1991 dofs = prb->getNumeredRowDofsPtr();
1994 dofs = prb->getNumeredColDofsPtr();
2003 return boost::shared_ptr<NumeredDofEntity>();
2009 return boost::shared_ptr<NumeredDofEntity>();
2012 std::array<boost::shared_ptr<BlockStructure>, 4> data_ptrs;
2014 for (
auto r = 0;
r != 3; ++
r) {
2015 data_ptrs[
r] = boost::make_shared<BlockStructure>();
2016 data_ptrs[
r]->dataBlocksPtr = block_mat_data_ptr->dataBlocksPtr;
2018 data_ptrs[3] = boost::make_shared<BlockStructure>();
2019 data_ptrs[3]->dataBlocksPtr = block_mat_data_ptr->dataBlocksPtr;
2021 data_ptrs[0]->ghostX = schur_vec_x;
2022 data_ptrs[0]->ghostY = schur_vec_y;
2023 data_ptrs[1]->ghostX = block_vec_x;
2024 data_ptrs[1]->ghostY = schur_vec_y;
2025 data_ptrs[2]->ghostX = schur_vec_x;
2026 data_ptrs[2]->ghostY = block_vec_y;
2027 data_ptrs[3]->ghostX = block_vec_x;
2028 data_ptrs[3]->ghostY = block_vec_y;
2031 for (
auto &
d : block_mat_data_ptr->blockIndex.get<0>()) {
2033 auto insert = [&](
auto &
m,
auto &dof_r,
auto &dof_c,
auto &
d) {
2037 d.getRowUId(),
d.getColUId(),
d.getFEUId(),
2039 dof_r->getPetscGlobalDofIdx(), dof_c->getPetscGlobalDofIdx(),
2041 d.getNbRows(),
d.getNbCols(),
2043 dof_r->getPetscLocalDofIdx(), dof_c->getPetscLocalDofIdx(),
2050 auto dof_schur_row = find_field_ent(
d.getRowUId(), schur_prb,
ROW);
2051 auto dof_schur_col = find_field_ent(
d.getColUId(), schur_prb,
COL);
2052 auto dof_block_row = find_field_ent(
d.getRowUId(), block_prb,
ROW);
2053 auto dof_block_col = find_field_ent(
d.getColUId(), block_prb,
COL);
2055 if (dof_schur_row && dof_schur_col) {
2056 insert(data_ptrs[0]->blockIndex, dof_schur_row, dof_schur_col,
d);
2059 if (dof_schur_row && dof_block_col) {
2060 insert(data_ptrs[1]->blockIndex, dof_schur_row, dof_block_col,
d);
2063 if (dof_block_row && dof_schur_col) {
2064 insert(data_ptrs[2]->blockIndex, dof_block_row, dof_schur_col,
d);
2067 if (dof_block_row && dof_block_col) {
2068 insert(data_ptrs[3]->blockIndex, dof_block_row, dof_block_col,
d);
2075 auto set_up_a00_data = [&](
auto inv_block_data) {
2078 if (add_preconditioner_block) {
2079 auto preconditioned_block = boost::make_shared<std::vector<double>>(
2080 inv_block_data->dataBlocksPtr->size(), 0);
2081 inv_block_data->preconditionerBlocksPtr = preconditioned_block;
2082 inv_block_data->multiplyByPreconditioner =
true;
2083 block_mat_data_ptr->preconditionerBlocksPtr =
2084 inv_block_data->preconditionerBlocksPtr;
2085 block_mat_data_ptr->multiplyByPreconditioner =
false;
2091 CHKERR set_up_a00_data(data_ptrs[3]);
2094 CHKERR PetscObjectGetComm((PetscObject)schur_dm, &comm);
2096 auto create_shell_mat = [&](
auto nb_r_loc,
auto nb_c_loc,
auto nb_r_glob,
2097 auto nb_c_glob,
auto data_ptr) {
2099 CHKERR MatCreateShell(comm, nb_r_loc, nb_c_loc, nb_r_glob, nb_c_glob,
2100 (
void *)data_ptr.get(), &mat_raw);
2105 auto schur_nb_global = schur_prb->getNbDofsRow();
2106 auto block_nb_global = block_prb->getNbDofsRow();
2107 auto schur_nb_local = schur_prb->getNbLocalDofsRow();
2108 auto block_nb_local = block_prb->getNbLocalDofsRow();
2110 std::array<SmartPetscObj<Mat>, 4> mats_array;
2112 create_shell_mat(schur_nb_local, schur_nb_local, schur_nb_global,
2113 schur_nb_global, data_ptrs[0]);
2115 create_shell_mat(schur_nb_local, block_nb_local, schur_nb_global,
2116 block_nb_global, data_ptrs[1]);
2118 create_shell_mat(block_nb_local, schur_nb_local, block_nb_global,
2119 schur_nb_global, data_ptrs[2]);
2121 create_shell_mat(block_nb_local, block_nb_local, block_nb_global,
2122 block_nb_global, data_ptrs[3]);
2125 <<
"(0, 0) " << schur_nb_local <<
" " << schur_nb_global <<
" "
2126 << data_ptrs[0]->blockIndex.size();
2128 <<
"(0, 1) " << schur_nb_local <<
" " << block_nb_local <<
" "
2129 << schur_nb_global <<
" " << block_nb_global <<
" "
2130 << data_ptrs[1]->blockIndex.size();
2132 <<
"(1, 0) " << block_nb_local <<
" " << schur_nb_local <<
" "
2133 << block_nb_global <<
" " << schur_nb_global <<
" "
2134 << data_ptrs[2]->blockIndex.size();
2136 <<
"(1, 1) " << block_nb_local <<
" " << block_nb_global <<
" "
2137 << data_ptrs[3]->blockIndex.size();
2141 auto schur_is = schur_prb->getSubData()->getSmartRowIs();
2142 auto block_is = block_prb->getSubData()->getSmartRowIs();
2144 return boost::make_shared<NestSchurData>(
2146 mats_array, data_ptrs, block_mat_data_ptr,
2147 std::make_pair(schur_is, block_is)
2152 std::pair<SmartPetscObj<Mat>, boost::shared_ptr<NestSchurData>>
2155 if (!schur_net_data_ptr)
2158 auto [mat_arrays, data_ptrs, block_mat_data_ptr, iss] = *schur_net_data_ptr;
2159 auto [schur_is, block_is] = iss;
2161 std::array<IS, 2> is_a = {schur_is, block_is};
2162 std::array<Mat, 4> mats_a = {
2164 mat_arrays[0], mat_arrays[1], mat_arrays[2], mat_arrays[3]
2169 CHKERR PetscObjectGetComm((PetscObject)mat_arrays[0], &comm);
2174 comm, 2, is_a.data(), 2, is_a.data(), mats_a.data(), &mat_raw
2185 OpSchurAssembleBase *
2187 std::vector<boost::shared_ptr<Range>> field_ents,
2189 bool sym_schur,
bool symm_op) {
2192 schur, sym_schur, symm_op);
2195 schur, sym_schur, symm_op);
2198 OpSchurAssembleBase *
2200 std::vector<boost::shared_ptr<Range>> field_ents,
2203 std::vector<bool> sym_schur,
bool symm_op,
2204 boost::shared_ptr<BlockStructure> diag_blocks) {
2206 fields_name, field_ents, sequence_of_aos.back(), sequence_of_mats.back(),
2207 sym_schur.back(), symm_op);
2210 OpSchurAssembleBase *
2212 std::vector<boost::shared_ptr<Range>> field_ents,
2215 std::vector<bool> sym_schur,
2216 std::vector<double> diag_eps,
bool symm_op,
2217 boost::shared_ptr<BlockStructure> diag_blocks) {
2219 fields_name, field_ents, sequence_of_aos.back(), sequence_of_mats.back(),
2220 sym_schur.back(), symm_op);
2226 auto apply = [](PC pc,
Vec f,
Vec x) {
2234 CHKERR PCSetType(pc, PCSHELL);
2235 CHKERR PCShellSetApply(pc, apply);
2236 CHKERR PCShellSetName(pc,
"MoFEMSchurBlockPC");
2259 return MatSetValues<AssemblyTypeSelector<PETSC>>(
M, row_data, col_data, mat,
2264 SchurBackendMatSetValuesPtr::MatSetValuesPtr
2274 CHKERR assembleStorage(row_data, col_data, mat, iora);
2275 CHKERR SchurBackendMatSetValuesPtr::matSetValuesPtr(
M, row_data, col_data,
2308 SchurBackendMatSetValuesPtr::matSetValuesBlockPtr =
2317 CHKERR assembleStorage(row_data, col_data, mat, iora);
2318 CHKERR SchurBackendMatSetValuesPtr::matSetValuesBlockPtr(
M, row_data,
2319 col_data, mat, iora);
2341 SchurBackendMatSetValuesPtr::matSetValuesPreconditionedBlockPtr =
2349 CHKERR assembleStorage(row_data, col_data, mat, iora);
2350 CHKERR SchurBackendMatSetValuesPtr::matSetValuesPreconditionedBlockPtr(
2351 M, row_data, col_data, mat, iora);
2367 if (block_mat_data->multiplyByPreconditioner) {
2368 block_mat_data->multiplyByPreconditioner =
false;
2370 if (!block_mat_data->preconditionerBlocksPtr) {
2372 "preconditionerBlocksPtr not set");
2374 block_mat_data->multiplyByPreconditioner =
true;
2381 std::string filename) {
2387 ReadUtilIface *iface;
2388 CHKERR moab.query_interface(iface);
2390 auto size = block_mat_data->blockIndex.size();
2393 vector<double *> arrays_coord;
2394 CHKERR iface->get_node_coords(3, 4 * size, 0, starting_vertex, arrays_coord);
2397 CHKERR iface->get_element_connect(size, 4, MBQUAD, 0, starting_handle, array);
2399 double def_val_nrm2 = 0;
2401 CHKERR moab.tag_get_handle(
"nrm2", 1, MB_TYPE_DOUBLE, th_nrm2,
2402 MB_TAG_CREAT | MB_TAG_DENSE, &def_val_nrm2);
2404 int def_val_mat_shift = 0;
2406 CHKERR moab.tag_get_handle(
"mat_shift", 1, MB_TYPE_INTEGER, th_mat_shift,
2407 MB_TAG_CREAT | MB_TAG_DENSE, &def_val_mat_shift);
2410 for (
auto &
d : block_mat_data->blockIndex) {
2411 auto row =
d.getRow();
2412 auto col =
d.getCol();
2413 auto nb_rows =
d.getNbRows();
2414 auto nb_cols =
d.getNbCols();
2415 auto mat_shift =
d.getMatShift();
2418 arrays_coord[0][4 *
i + 0] = row;
2419 arrays_coord[1][4 *
i + 0] = col;
2420 arrays_coord[2][4 *
i + 0] = 0;
2423 arrays_coord[0][4 *
i + 1] = row + nb_rows;
2424 arrays_coord[1][4 *
i + 1] = col;
2425 arrays_coord[2][4 *
i + 1] = 0;
2428 arrays_coord[0][4 *
i + 2] = row + nb_rows;
2429 arrays_coord[1][4 *
i + 2] = col + nb_cols;
2430 arrays_coord[2][4 *
i + 2] = 0;
2433 arrays_coord[0][4 *
i + 3] = row;
2434 arrays_coord[1][4 *
i + 3] = col + nb_cols;
2435 arrays_coord[2][4 *
i + 3] = 0;
2438 array[4 *
i + 0] = starting_vertex + 4 *
i + 0;
2439 array[4 *
i + 1] = starting_vertex + 4 *
i + 1;
2440 array[4 *
i + 2] = starting_vertex + 4 *
i + 2;
2441 array[4 *
i + 3] = starting_vertex + 4 *
i + 3;
2443 auto prt = &(*block_mat_data->dataBlocksPtr)[
d.getMatShift()];
2444 auto nrm2 = cblas_dnrm2(nb_rows * nb_cols, prt, 1);
2446 CHKERR moab.tag_set_data(th_nrm2, &ele, 1, &nrm2);
2447 CHKERR moab.tag_set_data(th_mat_shift, &ele, 1, &mat_shift);
2452 CHKERR iface->update_adjacencies(starting_handle, size, 4, array);
2453 CHKERR moab.write_file(filename.c_str(),
"VTK",
"");