49 return ::MatSetValues(
51 S, row_ind.size(), &*row_ind.begin(), col_ind.size(), &*col_ind.begin(),
52 &*
m.data().begin(), iora
72 boost::shared_ptr<std::vector<unsigned char>> marker_ptr,
79 boost::shared_ptr<std::vector<unsigned char>>
markerPtr;
87template <
typename OP_SCHUR_ASSEMBLE_BASE>
105 std::vector<std::string> fields_name,
106 std::vector<boost::shared_ptr<Range>> field_ents,
110 bool sym_schur,
bool symm_op);
113 template <
typename I>
161struct SchurElemMats :
public boost::enable_shared_from_this<SchurElemMats> {
187 template <
typename OP_SCHUR_ASSEMBLE_BASE>
202 member<SchurElemMats, const UId, &SchurElemMats::uidRow>,
203 member<SchurElemMats, const UId, &SchurElemMats::uidCol>
212 static boost::ptr_vector<MatrixDouble>
locMats;
279 const_mem_fun<Indexes, UId, &Indexes::getRowUId>,
280 const_mem_fun<Indexes, UId, &Indexes::getColUId>>
286 const_mem_fun<Indexes, UId, &Indexes::getFEUId>
292 const_mem_fun<Indexes, UId, &Indexes::getRowUId>
298 const_mem_fun<Indexes, UId, &Indexes::getColUId>
344 : iDX(idx), uidRow(uid_row), uidCol(uid_col) {}
358 auto get_row_indices = [&]() ->
const VectorInt & {
360 if (
auto stored_data_ptr =
362 return stored_data_ptr->entityIndices;
368 const auto &row_ind = get_row_indices();
371 const auto nb_rows = row_ind.size();
372 const auto nb_cols = col_ind.size();
375 if (mat.size1() != nb_rows) {
377 "Wrong mat size %ld != %ld", mat.size1(), nb_rows);
379 if (mat.size2() != nb_cols) {
381 "Wrong mat size %ld != %ld", mat.size2(), nb_cols);
386 auto get_uid = [](
auto &data) {
387 if (data.getFieldEntities().size() == 1) {
389 return data.getFieldEntities()[0]->getLocalUniqueId();
398 auto &uid0 = data.getFieldEntities()[0]->getLocalUniqueId();
404 for (
auto i = 1;
i < data.getFieldEntities().size(); ++
i) {
411 data.getFieldEntities()[
i]->getLocalUniqueId())
425 auto uid_row = get_uid(row_data);
426 auto uid_col = get_uid(col_data);
430 .find(boost::make_tuple(uid_row, uid_col));
462 auto asmb = [&](
auto &sm) {
463 sm.resize(nb_rows, nb_cols,
false);
467 asmb((*p.first)->getMat());
469 auto add_indices = [](
auto &storage,
auto &ind) {
470 storage.resize(ind.size(),
false);
471 noalias(storage) = ind;
474 add_indices((*p.first)->getRowInd(), row_ind);
475 add_indices((*p.first)->getColInd(), col_ind);
480 auto asmb = [&](
auto &sm) {
484 if (sm.size1() != nb_rows) {
486 "Wrong mat or storage size %ld != %ld", sm.size1(), nb_rows);
488 if (sm.size2() != nb_cols) {
490 "Wrong mat or storage size %ld != %ld", sm.size2(), nb_cols);
503 "Assembly type not implemented");
508 CHKERR asmb((*it)->getMat());
528 MOFEM_LOG(
"SELF", Sev::noisy) <<
"Schur assemble begin";
537 boost::shared_ptr<std::vector<unsigned char>> marker_ptr,
double diag_val)
547 auto prb_ptr = fe_ptr->problemPtr;
550 auto find_loc_dof_index = [&](
auto glob) {
551 auto it = dof.find(glob);
552 if (it != dof.end()) {
553 return (*it)->getPetscLocalDofIdx();
555 MOFEM_LOG(
"SELF", Sev::error) <<
"Global dof " << glob;
558 "Global dof index not found in local numered dofs storage");
564 auto zero_ind = [&](
auto &ind) {
565 for (
auto i = 0;
i < ind.size(); ++
i) {
567 if ((*
markerPtr)[find_loc_dof_index(ind[
i])]) {
574 zero_ind(s->getRowInd());
575 zero_ind(s->getColInd());
582template <
typename OP_SCHUR_ASSEMBLE_BASE>
584 std::vector<std::string> fields_name,
585 std::vector<boost::shared_ptr<Range>> field_ents,
588 :
OP(
NOSPACE,
OP::OPSPACE, symm_op), fieldsName(fields_name),
589 fieldEnts(field_ents), schurAO(schur_ao), schurMat(schur_mat),
590 symSchur(sym_schur) {}
592template <
typename OP_SCHUR_ASSEMBLE_BASE>
605 MOFEM_LOG(
"SELF", Sev::noisy) <<
"Schur assemble begin -> end";
608 auto get_a00_uids = [&]() {
609 auto get_field_bit = [&](
auto &name) {
610 return OP::getPtrFE()->mField.get_field_bit_number(name);
613 std::vector<std::pair<UId, UId>> a00_uids;
614 a00_uids.reserve(fieldsName.size());
615 for (
auto ss = 0; ss != fieldsName.size(); ++ss) {
616 auto field_bit = get_field_bit(fieldsName[ss]);
617 auto row_ents = fieldEnts[ss];
619 for (
auto p = row_ents->pair_begin(); p != row_ents->pair_end(); ++p) {
624 a00_uids.push_back(std::make_pair(lo_uid, hi_uid));
628 field_bit, get_id_for_min_type<MBVERTEX>());
630 field_bit, get_id_for_max_type<MBENTITYSET>());
631 a00_uids.push_back(std::make_pair(lo_uid, hi_uid));
638 auto get_field_name = [&](
auto uid) {
642 auto list_storage = [&](
auto &storage) {
645 for (
auto &p : storage) {
647 <<
"List schur storage: " <<
i <<
" " << p->iDX <<
": "
648 << get_field_name(p->uidRow) <<
" " << get_field_name(p->uidCol)
649 <<
" : " << p->getMat().size1() <<
" " << p->getMat().size2();
656 auto assemble_dense_blocks = [&]() {
657 using matrix_range = ublas::matrix_range<MatrixDouble>;
658 using range = ublas::range;
662 auto assemble_schur = [
this](
auto &
m,
auto &uid_row,
auto &uid_col,
663 auto *row_ind_ptr,
auto *col_ind_ptr) {
668 if (
auto ierr = this->assembleSchurMat(
670 schurMat, uid_row, *row_ind_ptr, uid_col, *col_ind_ptr,
m,
675 auto field_ents = OP::getPtrFE()->mField.get_field_ents();
676 auto row_ent_it = field_ents->find(uid_row);
677 auto col_ent_it = field_ents->find(uid_col);
679 if (row_ent_it != field_ents->end())
681 <<
"Assemble row entity: " << (*row_ent_it)->getName() <<
" "
682 << (*col_ent_it)->getEntTypeName() <<
" side "
683 << (*row_ent_it)->getSideNumber();
684 if (col_ent_it != field_ents->end())
686 <<
"Assemble col entity: " << (*col_ent_it)->getName() <<
" "
687 << (*col_ent_it)->getEntTypeName() <<
" side "
688 << (*col_ent_it)->getSideNumber();
697 auto a00_uids = get_a00_uids();
699 auto get_block_indexing = [&](
auto &a00_uids) {
701 std::vector<const SchurElemMats *> block_list;
702 block_list.reserve(storage.size());
703 for (
auto &rp_uid : a00_uids) {
704 auto [rlo_uid, rhi_uid] = rp_uid;
705 for (
auto &cp_uid : a00_uids) {
706 auto [clo_uid, chi_uid] = cp_uid;
709 storage.template get<SchurElemMats::uid_mi_tag>().lower_bound(
710 boost::make_tuple(rlo_uid, clo_uid));
712 storage.template get<SchurElemMats::uid_mi_tag>().upper_bound(
713 boost::make_tuple(rhi_uid, chi_uid));
715 for (; it != hi_it; ++it) {
716 if ((*it)->uidRow >= rlo_uid && (*it)->uidRow < rhi_uid &&
717 (*it)->uidCol >= clo_uid && (*it)->uidCol < chi_uid) {
718 block_list.push_back(*it);
725 std::map<UId, std::pair<size_t, const VectorInt *>>
727 for (
auto d : block_list) {
728 if (block_indexing.find(d->uidRow) == block_indexing.end()) {
729 block_indexing[d->uidRow] =
730 std::make_pair(d->getRowInd().size(), &(d->getRowInd()));
735 int mat_block_size = 0;
736 for (
auto &p_uid : a00_uids) {
737 auto [lo_uid, hi_uid] = p_uid;
738 auto lo = block_indexing.lower_bound(lo_uid);
739 auto up = block_indexing.upper_bound(hi_uid);
740 for (; lo != up; ++lo) {
741 lo->second.first = mat_block_size;
742 mat_block_size += lo->second.second->size();
746 return std::make_tuple(block_list, block_indexing, mat_block_size);
749 auto get_schur_block_list = [&](
auto &block_indexing) {
750 std::vector<const SchurElemMats *> block_list;
751 block_list.reserve(storage.size());
752 for (
auto &s : storage) {
753 if (block_indexing.find(s->uidRow) == block_indexing.end() &&
754 block_indexing.find(s->uidCol) == block_indexing.end()) {
755 block_list.push_back(s);
761 auto bi = get_block_indexing(a00_uids);
762 auto &[block_list, block_indexing, block_mat_size] = bi;
764 if (block_mat_size == 0) {
767 for (
auto &s : storage) {
768 CHKERR AOApplicationToPetsc(schurAO, s->getRowInd().size(),
769 &*s->getRowInd().begin());
770 CHKERR AOApplicationToPetsc(schurAO, s->getColInd().size(),
771 &*s->getColInd().begin());
775 for (
auto &s : storage) {
776 auto &
m = s->getMat();
777 CHKERR assemble_schur(
m, s->uidRow, s->uidCol, &(s->getRowInd()),
783 blockMat.resize(block_mat_size, block_mat_size,
false);
786 auto get_range = [](
auto &bi) {
787 return range(bi.first, bi.first + bi.second->size());
790 for (
auto &s : block_list) {
791 auto &
m = s->getMat();
793 if (block_indexing.find(s->uidRow) == block_indexing.end())
795 if (block_indexing.find(s->uidCol) == block_indexing.end())
799 auto &rbi = block_indexing.at(s->uidRow);
800 auto &cbi = block_indexing.at(s->uidCol);
802 auto sub_mat = matrix_range(blockMat, get_range(rbi), get_range(cbi));
806 auto get_zeroed_indices = [&](
auto extractor_uid,
auto extractor_ind) {
807 auto &[block_list, block_indexing, block_mat_size] = bi;
808 std::vector<int> zeroed_indices;
809 zeroed_indices.reserve(block_mat_size);
810 for (
auto &s : block_list) {
811 auto &bi = block_indexing.at(extractor_uid(s));
812 auto &ind = extractor_ind(s);
813 for (
auto it = ind.begin(); it != ind.end(); ++it) {
815 auto idx = bi.first + std::distance(ind.begin(), it);
816 zeroed_indices.push_back(idx);
820 std::sort(zeroed_indices.begin(), zeroed_indices.end());
821 auto it = std::unique(zeroed_indices.begin(), zeroed_indices.end());
822 zeroed_indices.resize(std::distance(zeroed_indices.begin(), it));
823 return zeroed_indices;
825 auto zero_rows = get_zeroed_indices(
826 [](
auto &s) {
return s->uidRow; },
827 [](
auto &s) ->
VectorInt & {
return s->getRowInd(); });
828 auto zero_cols = get_zeroed_indices(
829 [](
auto &s) {
return s->uidCol; },
830 [](
auto &s) ->
VectorInt & {
return s->getColInd(); });
832 for (
auto i : zero_rows) {
833 for (
auto j = 0;
j != blockMat.size2(); ++
j) {
837 for (
auto j : zero_cols) {
838 for (
auto i = 0;
i != blockMat.size1(); ++
i) {
842 for (
auto i : zero_rows) {
846 CHKERR I::invertMat(blockMat, invMat);
849 for (
auto &s : block_list) {
850 auto it = storage.template get<SchurElemMats::uid_mi_tag>().find(
851 boost::make_tuple(s->uidRow, s->uidCol));
852 storage.template get<SchurElemMats::uid_mi_tag>().erase(it);
857 for (
auto &s : storage) {
858 if (block_indexing.find(s->uidRow) == block_indexing.end()) {
859 CHKERR AOApplicationToPetsc(schurAO, s->getRowInd().size(),
860 &*s->getRowInd().begin());
862 if (block_indexing.find(s->uidCol) == block_indexing.end()) {
863 CHKERR AOApplicationToPetsc(schurAO, s->getColInd().size(),
864 &*s->getColInd().begin());
869 auto schur_block_list = get_schur_block_list(block_indexing);
870 for (
auto &s : schur_block_list) {
871 auto &
m = s->getMat();
872 CHKERR assemble_schur(
m, s->uidRow, s->uidCol, &(s->getRowInd()),
875 for (
auto &s : schur_block_list) {
876 auto it = storage.template get<SchurElemMats::uid_mi_tag>().find(
877 boost::make_tuple(s->uidRow, s->uidCol));
878 storage.template get<SchurElemMats::uid_mi_tag>().erase(it);
880 schur_block_list.clear();
884 auto rp_uid_it = a00_uids.begin(); rp_uid_it != a00_uids.end();
888 auto [rlo_uid, rhi_uid] = *rp_uid_it;
889 for (
auto rm = block_indexing.lower_bound(rlo_uid);
890 rm != block_indexing.upper_bound(rhi_uid); ++rm) {
891 auto &rbi = rm->second;
894 storage.template get<SchurElemMats::col_mi_tag>().lower_bound(
897 storage.template get<SchurElemMats::col_mi_tag>().upper_bound(
902 auto cp_uid_it = (symSchur) ? rp_uid_it : a00_uids.begin();
903 cp_uid_it != a00_uids.end(); ++cp_uid_it
906 auto [clo_uid, chi_uid] = *cp_uid_it;
907 for (
auto cm = block_indexing.lower_bound(clo_uid);
908 cm != block_indexing.upper_bound(chi_uid); ++cm) {
909 auto &cbi = cm->second;
912 storage.template get<SchurElemMats::uid_mi_tag>().lower_bound(
913 boost::make_tuple(cm->first, 0));
915 storage.template get<SchurElemMats::uid_mi_tag>().upper_bound(
920 matrix_range(invMat, get_range(rbi), get_range(cbi));
921 bM.resize(sub_inv_mat.size1(), sub_inv_mat.size2());
922 noalias(bM) = sub_inv_mat;
924 for (
auto a_lo = a_lo_tmp; a_lo != a_hi; ++a_lo) {
926 if (block_indexing.find((*a_lo)->uidRow) != block_indexing.end())
928 "Wrong a_lo->uidRow");
931 auto &
a = (*a_lo)->getMat();
932 abM.resize(
a.size1(), bM.size2(),
false);
934 cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
936 a.size1(), bM.size2(),
a.size2(), 1.,
938 &*
a.data().begin(),
a.size2(),
940 &*bM.data().begin(), bM.size2(), 0.,
942 &*abM.data().begin(), abM.size2());
944 for (
auto c_lo = c_lo_tmp; c_lo != c_hi; ++c_lo) {
946 if (block_indexing.find((*c_lo)->uidCol) !=
947 block_indexing.end())
949 "Wrong a_lo->uidRow");
952 auto &
c = (*c_lo)->getMat();
954 abcM.resize(abM.size1(),
c.size2(),
false);
957 cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
958 abM.size1(),
c.size2(), abM.size2(), -1.,
960 &*abM.data().begin(), abM.size2(),
962 &*
c.data().begin(),
c.size2(), 0.,
964 &*abcM.data().begin(), abcM.size2());
966 CHKERR assemble_schur(abcM, (*a_lo)->uidRow, (*c_lo)->uidCol,
967 &((*a_lo)->getRowInd()),
968 &((*c_lo)->getColInd()));
970 if (symSchur && rp_uid_it != cp_uid_it) {
972 CHKERR assemble_schur(abcM, (*c_lo)->uidCol, (*a_lo)->uidRow,
973 &((*c_lo)->getColInd()),
974 &((*a_lo)->getRowInd()));
987 CHKERR assemble_dense_blocks();
991 MOFEM_LOG(
"SELF", Sev::noisy) <<
"Schur assemble done";
1006 const auto nb =
m.size1();
1008 if (nb !=
m.size2()) {
1010 "It should be square matrix %ld != %ld", nb,
m.size2());
1014 inv.resize(nb, nb,
false);
1016 m.resize(2 * nb, 2 * nb,
false);
1023 info =
lapack_dgetrf(nb, nb, &*inv.data().begin(), nb, &*ipiv.begin());
1026 "lapack error info = %d", info);
1027 info =
lapack_dgetri(nb, &*inv.data().begin(), nb, &*ipiv.begin(),
1028 &*
m.data().begin(),
m.data().size());
1031 "lapack error info = %d", info);
1042 const auto nb =
m.size1();
1044 if (nb !=
m.size2()) {
1046 "It should be square matrix %ld != %ld", nb,
m.size2());
1050 inv.resize(nb, nb,
false);
1056 info =
lapack_dgetrf(nb, nb, &*inv.data().begin(), nb, &*ipiv.begin());
1059 "lapack error info = %d", info);
1060 info =
lapack_dgetri(nb, &*inv.data().begin(), nb, &*ipiv.begin(),
1061 &*
m.data().begin(),
m.data().size());
1064 "lapack error info = %d", info);
1073 return doWorkImpl<SchurDSYSV>(side, type, data);
1079 return doWorkImpl<SchurDGESV>(side, type, data);
1089 auto cmp_uid_lo = [](
const boost::weak_ptr<FieldEntity> &
a,
const UId &b) {
1090 if (
auto a_ptr =
a.lock()) {
1091 if (a_ptr->getLocalUniqueId() < b)
1100 auto cmp_uid_hi = [](
const UId &b,
const boost::weak_ptr<FieldEntity> &
a) {
1101 if (
auto a_ptr =
a.lock()) {
1102 if (b < a_ptr->getLocalUniqueId())
1112 auto get_uid_pair = [](
const auto &field_id) {
1114 field_id, get_id_for_min_type<MBVERTEX>());
1116 field_id, get_id_for_max_type<MBENTITYSET>());
1117 return std::make_pair(lo_uid, hi_uid);
1122 auto lo = std::lower_bound(field_ents.begin(), field_ents.end(),
1124 auto hi = std::upper_bound(field_ents.begin(), field_ents.end(),
1126 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<UId, int, int, int>> data;
1136 data.reserve(std::distance(its.first, its.second));
1138 for (; its.first != its.second; ++its.first) {
1139 if (
auto e = its.first->lock()) {
1140 if (
auto cache = extractor(e).lock()) {
1142 for (
auto dof = cache->loHi[0]; dof != cache->loHi[1]; ++dof) {
1143 if ((*dof)->getPetscGlobalDofIdx() != -1)
1146 auto uid = e->getLocalUniqueId();
1149 auto glob = (*cache->loHi[0])->getPetscGlobalDofIdx();
1150 auto loc = (*cache->loHi[0])->getPetscLocalDofIdx();
1151 while (glob == -1 && cache->loHi[0] != cache->loHi[1]) {
1153 glob = (*cache->loHi[0])->getPetscGlobalDofIdx();
1154 loc = (*cache->loHi[0])->getPetscLocalDofIdx();
1156 data.emplace_back(uid, glob, nb_dofs, loc);
1160 for (
auto lo = cache->loHi[0]; lo != cache->loHi[1]; ++lo) {
1161 auto glob = (*lo)->getPetscGlobalDofIdx();
1164 "Wrong global index");
1170 data.emplace_back(uid, -1, 0, -1);
1178 auto data_ptr = boost::make_shared<BlockStructure>();
1182 auto fe_method = boost::shared_ptr<MoFEM::FEMethod>(
new MoFEM::FEMethod());
1184 for (
auto &d : schur_fe_op_vec) {
1187 auto get_bit_numbers = [&d](
auto op) {
1188 std::vector<FieldBitNumber> bit_numbers(d.second.size());
1189 std::transform(d.second.begin(), d.second.end(), bit_numbers.begin(), op);
1194 auto row_bit_numbers = get_bit_numbers(
1195 [&](
auto &p) {
return m_field_ptr->get_field_bit_number(p.first); });
1197 auto col_bit_numbers = get_bit_numbers(
1198 [&](
auto &p) {
return m_field_ptr->get_field_bit_number(p.second); });
1200 fe_method->preProcessHook = []() {
return 0; };
1201 fe_method->postProcessHook = []() {
return 0; };
1202 fe_method->operatorHook = [&]() {
1205 auto fe_uid = fe_method->numeredEntFiniteElementPtr->getLocalUniqueId();
1207 for (
auto f = 0; f != row_bit_numbers.size(); ++f) {
1210 extract_data(get_it_pair(fe_method->getRowFieldEnts(),
1211 get_uid_pair(row_bit_numbers[f])),
1214 extract_data(get_it_pair(fe_method->getColFieldEnts(),
1215 get_uid_pair(col_bit_numbers[f])),
1218 for (
auto &r : row_data) {
1219 auto [r_uid, r_glob, r_nb_dofs, r_loc] = r;
1220 for (
auto &
c : col_data) {
1221 auto [c_uid, c_glob, c_nb_dofs, c_loc] =
c;
1223 r_uid, c_uid, fe_uid, r_glob, c_glob, r_nb_dofs, c_nb_dofs,
1233 m_field_ptr->get_comm_size());
1238 for (
auto &
v : data_ptr->blockIndex.get<0>()) {
1239 v.getMatShift() = mem_size;
1240 mem_size +=
v.getNbCols() *
v.getNbRows();
1243 std::vector<double> tmp;
1244 if (mem_size > tmp.max_size())
1247 data_ptr->dataBlocksPtr =
1248 boost::make_shared<std::vector<double>>(mem_size, 0);
1252 CHKERR VecSetDM(ghost_x, PETSC_NULLPTR);
1253 CHKERR VecSetDM(ghost_y, PETSC_NULLPTR);
1255 data_ptr->ghostX = ghost_x;
1256 data_ptr->ghostY = ghost_y;
1262 Mat mat, Vec x, Vec y, InsertMode iora,
1264 int(DiagBlockIndex::BlockIndex::nth_index<0>::type::iterator)>
1266 boost::shared_ptr<std::vector<double>> data_blocks_ptr,
1267 bool multiply_by_preconditioner,
enum CBLAS_TRANSPOSE trans_A);
1271 enum CBLAS_TRANSPOSE trans_A);
1273static PetscErrorCode
mult(Mat mat, Vec x, Vec y) {
1275 CHKERR MatShellGetContext(mat, (
void **)&ctx);
1277 mat, x, y, INSERT_VALUES,
1279 [](DiagBlockIndex::BlockIndex::nth_index<0>::type::iterator it) {
1280 return it->getMatShift();
1287 CHKERR MatShellGetContext(mat, (
void **)&ctx);
1289 mat, x, y, ADD_VALUES,
1291 [](DiagBlockIndex::BlockIndex::nth_index<0>::type::iterator it) {
1292 return it->getMatShift();
1299 CHKERR MatShellGetContext(mat, (
void **)&ctx);
1301 mat, x, y, INSERT_VALUES,
1303 [](DiagBlockIndex::BlockIndex::nth_index<0>::type::iterator it) {
1304 return it->getMatShift();
1311 CHKERR MatShellGetContext(mat, (
void **)&ctx);
1313 mat, x, y, ADD_VALUES,
1315 [](DiagBlockIndex::BlockIndex::nth_index<0>::type::iterator it) {
1316 return it->getMatShift();
1322static PetscErrorCode
solve(Mat mat, Vec x, Vec y) {
1336 const PetscInt rows[], PetscScalar diag,
1341 CHKERR MatShellGetContext(
A, (
void **)&ctx);
1345 using BlockIndexView = multi_index_container<
1367 BlockIndexView view;
1368 auto hint = view.get<0>().end();
1370 hint = view.insert(hint, &
v);
1373 const int *ptr = &rows[0];
1378 CHKERR PetscObjectGetComm((PetscObject)
A, &comm);
1380 MPI_Comm_size(comm, &size);
1386 CHKERR ISGetSize(is_local, &is_nb_rows);
1389 CHKERR ISView(is_local, PETSC_VIEWER_STDOUT_WORLD);
1392 CHKERR ISGetIndices(is_local, &ptr);
1396 CHKERR MatGetLocalSize(
A, &loc_m, &loc_n);
1398 for (
auto n = 0;
n != is_nb_rows; ++
n) {
1400 auto rlo = view.get<0>().lower_bound(row);
1401 auto rhi = view.get<0>().end();
1402 for (; rlo != rhi; ++rlo) {
1403 auto r_shift = row - (*rlo)->getRow();
1404 if (r_shift >= 0 && r_shift < (*rlo)->getNbRows()) {
1406 for (
auto i = 0;
i != (*rlo)->getNbCols(); ++
i) {
1407 ptr[
i + r_shift * (*rlo)->getNbCols()] = 0;
1409 }
else if ((*rlo)->getRow() + (*rlo)->getNbRows() > row) {
1415 for (
auto n = 0;
n != is_nb_rows; ++
n) {
1417 auto clo = view.get<1>().lower_bound(col);
1418 auto chi = view.get<1>().end();
1419 for (; clo != chi; ++clo) {
1420 auto c_shift = col - (*clo)->getCol();
1421 if (c_shift >= 0 && c_shift < (*clo)->getNbCols()) {
1424 for (
auto i = 0;
i != (*clo)->getNbRows(); ++
i) {
1425 ptr[c_shift +
i * (*clo)->getNbCols()] = 0;
1431 (*clo)->getRow() == (*clo)->getCol() &&
1432 (*clo)->getLocRow() < loc_m && (*clo)->getLocCol() < loc_n
1435 auto r_shift = col - (*clo)->getCol();
1436 if (r_shift >= 0 && r_shift < (*clo)->getNbRows()) {
1437 ptr[c_shift + r_shift * (*clo)->getNbCols()] = diag;
1440 }
else if ((*clo)->getCol() + (*clo)->getNbCols() > col) {
1447 CHKERR ISRestoreIndices(is_local, &ptr);
1458 CHKERR MatShellGetContext(
m, (
void **)&ctx);
1469 CHKERR MatShellSetManageScalingShifts(mat_raw);
1470 CHKERR MatShellSetOperation(mat_raw, MATOP_MULT, (
void (*)(
void))
mult);
1471 CHKERR MatShellSetOperation(mat_raw, MATOP_MULT_ADD,
1473 CHKERR MatShellSetOperation(mat_raw, MATOP_MULT_TRANSPOSE,
1475 CHKERR MatShellSetOperation(mat_raw, MATOP_MULT_TRANSPOSE_ADD,
1477 CHKERR MatShellSetOperation(mat_raw, MATOP_SOLVE, (
void (*)(
void))
solve);
1478 CHKERR MatShellSetOperation(mat_raw, MATOP_SOLVE_ADD,
1480 CHKERR MatShellSetOperation(mat_raw, MATOP_SOLVE_TRANSPOSE,
1482 CHKERR MatShellSetOperation(mat_raw, MATOP_SOLVE_TRANSPOSE_ADD,
1484 CHKERR MatShellSetOperation(mat_raw, MATOP_ZERO_ENTRIES,
1486 CHKERR MatShellSetOperation(mat_raw, MATOP_ZERO_ROWS_COLUMNS,
1493 boost::shared_ptr<BlockStructure> data) {
1496 auto nb_local = problem_ptr->nbLocDofsRow;
1497 auto nb_global = problem_ptr->nbDofsRow;
1500 if (nb_local != problem_ptr->nbLocDofsCol) {
1502 <<
"Wrong size " << nb_local <<
" != " << problem_ptr->nbLocDofsCol;
1504 "nb. cols is inconsistent with nb. rows");
1506 if (nb_global != problem_ptr->nbDofsCol) {
1508 <<
"Wrong size " << nb_global <<
" != " << problem_ptr->nbDofsCol;
1510 "nb. cols is inconsistent with nb. rows");
1515 CHKERR PetscObjectGetComm((PetscObject)dm, &comm);
1518 CHKERR MatCreateShell(comm, nb_local, nb_local, nb_global, nb_global,
1519 (
void *)data.get(), &mat_raw);
1527 Mat mat, Vec x, Vec y, InsertMode iora,
1530 int(DiagBlockIndex::BlockIndex::nth_index<0>::type::iterator)>
1533 boost::shared_ptr<std::vector<double>> data_blocks_ptr,
1534 bool multiply_by_preconditioner,
enum CBLAS_TRANSPOSE trans_A) {
1537 CHKERR MatShellGetContext(mat, (
void **)&ctx);
1542 CHKERR VecGetLocalSize(x, &x_loc_size);
1544 CHKERR VecGetLocalSize(y, &y_loc_size);
1546 auto ghost_vecs = std::make_pair(ctx->
ghostX, ctx->
ghostY);
1551 case CblasConjTrans:
1552 std::swap(ghost_vecs.first, ghost_vecs.second);
1556 Vec ghost_x = ghost_vecs.first;
1557 Vec ghost_y = ghost_vecs.second;
1559 CHKERR VecCopy(x, ghost_x);
1563 CHKERR VecGhostGetLocalForm(ghost_y, &loc_ghost_y);
1565 CHKERR VecGetLocalSize(loc_ghost_y, &nb_y);
1566 CHKERR VecGetArray(loc_ghost_y, &y_array);
1567 for (
auto i = 0;
i != nb_y; ++
i)
1569 CHKERR VecRestoreArray(loc_ghost_y, &y_array);
1570 CHKERR VecGhostRestoreLocalForm(ghost_y, &loc_ghost_y);
1572 auto mult = [&](
int low_x,
int hi_x,
int low_y,
int hi_y) {
1575 const double *x_array;
1577 CHKERR VecGhostGetLocalForm(ghost_x, &loc_ghost_x);
1578 CHKERR VecGetArrayRead(loc_ghost_x, &x_array);
1582 CHKERR VecGhostGetLocalForm(ghost_y, &loc_ghost_y);
1584 CHKERR VecGetLocalSize(loc_ghost_y, &nb_y);
1585 CHKERR VecGetArray(loc_ghost_y, &y_array);
1587 double *block_ptr = &*data_blocks_ptr->begin();
1591 auto get_loc_row_no_trans = [](
auto it) {
return it->getLocRow(); };
1592 auto get_loc_col_no_trans = [](
auto it) {
return it->getLocCol(); };
1593 auto get_nb_rows_no_trans = [](
auto it) {
return it->getNbRows(); };
1594 auto get_nb_cols_no_trans = [](
auto it) {
return it->getNbCols(); };
1595 auto get_loc_row_trans = [](
auto it) {
return it->getLocCol(); };
1596 auto get_loc_col_trans = [](
auto it) {
return it->getLocRow(); };
1598 std::function<int(
decltype(it))> get_loc_row;
1599 std::function<int(
decltype(it))> get_loc_col;
1600 std::function<int(
decltype(it))> get_nb_rows;
1601 std::function<int(
decltype(it))> get_nb_cols;
1605 get_loc_row = get_loc_row_no_trans;
1606 get_loc_col = get_loc_col_no_trans;
1609 case CblasConjTrans:
1610 get_loc_row = get_loc_row_trans;
1611 get_loc_col = get_loc_col_trans;
1617 auto loc_row = get_loc_row(it);
1618 auto loc_col = get_loc_col(it);
1620 if (loc_row < low_y || loc_row >= hi_y ||
1621 loc_col < low_x || loc_col >= hi_x) {
1626 auto nb_rows = get_nb_rows_no_trans(it);
1627 auto nb_cols = get_nb_cols_no_trans(it);
1628 auto x_ptr = &x_array[loc_col];
1629 auto y_ptr = &y_array[loc_row];
1630 auto ptr = &block_ptr[shift_extractor(it)];
1631 cblas_dgemv(CblasRowMajor, trans_A, nb_rows, nb_cols, 1.0, ptr, nb_cols,
1632 x_ptr, 1, 1.0, y_ptr, 1);
1640 "No parentBlockStructurePtr");
1648 auto loc_row = get_loc_row(it);
1649 auto loc_col = get_loc_col(it);
1651 if (loc_row < low_y || loc_row >= hi_y ||
1652 loc_col < low_x || loc_col >= hi_x) {
1657 if (it->getMatShift() != -1) {
1658 auto nb_rows = get_nb_rows_no_trans(it);
1659 auto nb_cols = get_nb_cols_no_trans(it);
1660 auto x_ptr = &x_array[loc_col];
1661 auto y_ptr = &y_array[loc_row];
1662 auto ptr = &preconditioner_ptr[it->getMatShift()];
1663 cblas_dgemv(CblasRowMajor, trans_A, nb_rows, nb_cols, 1.0, ptr,
1664 nb_cols, x_ptr, 1, 1.0, y_ptr, 1);
1671 CHKERR VecRestoreArrayRead(loc_ghost_x, &x_array);
1672 CHKERR VecRestoreArray(loc_ghost_y, &y_array);
1673 CHKERR VecGhostRestoreLocalForm(ghost_x, &loc_ghost_x);
1674 CHKERR VecGhostRestoreLocalForm(ghost_y, &loc_ghost_y);
1678 constexpr auto max_int = std::numeric_limits<int>::max();
1679 CHKERR VecGhostUpdateBegin(ghost_x, INSERT_VALUES, SCATTER_FORWARD);
1681 CHKERR VecGhostUpdateEnd(ghost_x, INSERT_VALUES, SCATTER_FORWARD);
1682 CHKERR mult(x_loc_size, max_int, 0, max_int);
1684 CHKERR VecGhostUpdateBegin(ghost_y, ADD_VALUES, SCATTER_REVERSE);
1685 CHKERR VecGhostUpdateEnd(ghost_y, ADD_VALUES, SCATTER_REVERSE);
1689 CHKERR VecCopy(ghost_y, y);
1692 CHKERR VecAXPY(y, 1., ghost_y);
1700 auto print_norm = [&](
auto msg,
auto y) {
1703 CHKERR VecNorm(y, NORM_2, &norm);
1705 CHKERR VecGetLocalSize(y, &nb_loc_y);
1707 CHKERR VecGetSize(y, &nb_y);
1709 << msg <<
" " << nb_y <<
" " << nb_loc_y <<
" norm " << norm;
1715 print_norm(
"mult_schur_block_shell insert x", x);
1716 print_norm(
"mult_schur_block_shell insert y", y);
1719 print_norm(
"mult_schur_block_shell add x", x);
1720 print_norm(
"mult_schur_block_shell add y", y);
1736 enum CBLAS_TRANSPOSE trans_A) {
1737 using matrix_range = ublas::matrix_range<MatrixDouble>;
1738 using range = ublas::range;
1741 CHKERR MatShellGetContext(mat, (
void **)&ctx);
1748 "No preconditionerBlocksPtr");
1751 if (iora == INSERT_VALUES) {
1752 CHKERR VecZeroEntries(x);
1756 CHKERR VecGetArray(x, &x_array);
1757 const double *y_array;
1758 CHKERR VecGetArrayRead(y, &y_array);
1760 std::vector<const DiagBlockIndex::Indexes *> blocks;
1765 auto get_id = [](
auto bi) {
return bi->getRowUId(); };
1766 auto get_block_data = [](
auto bi) {
1767 return std::make_tuple(bi->getNbRows(), bi->getNbRows(), bi->getLocRow());
1769 auto block_sorter = [](
auto a,
auto b) {
1770 if (
a->getRowUId() == b->getRowUId())
1771 return a->getColUId() < b->getColUId();
1773 return (
a->getRowUId() < b->getRowUId());
1776 auto &block_index = ctx->
blockIndex.get<1>();
1777 for (
auto it = block_index.begin(); it != block_index.end();) {
1781 auto last_uid = it->getFEUId();
1782 while (it != block_index.end() && it->getFEUId() == last_uid) {
1783 blocks.push_back(&*it);
1788 std::map<
UId, std::tuple<
int ,
int ,
1791 for (
auto b : blocks) {
1793 if (block_indexing.find(get_id(b)) == block_indexing.end()) {
1794 block_indexing[get_id(b)] = get_block_data(b);
1797 std::sort(blocks.begin(), blocks.end(), block_sorter);
1800 int mat_block_size = 0;
1801 for (
auto &b : block_indexing) {
1802 auto &index = std::get<0>(b.second);
1803 auto block_row_size = index;
1804 index = mat_block_size;
1805 mat_block_size += block_row_size;
1808 std::vector<std::tuple<int, int, int, int, int>> block_data;
1809 block_data.reserve(blocks.size());
1810 for (
auto s : blocks) {
1811 auto ruid = s->getRowUId();
1812 auto cuid = s->getColUId();
1813 auto &rbi = block_indexing.at(ruid);
1814 auto &cbi = block_indexing.at(cuid);
1815 if (
auto shift = s->getMatShift(); shift != -1) {
1816 block_data.push_back(std::make_tuple(
1820 s->getNbRows(), s->getNbCols(),
1822 get<0>(rbi), get<0>(cbi))
1829 block_mat.resize(mat_block_size, mat_block_size,
false);
1831 for (
auto &bd : block_data) {
1832 auto &[shift, nb_rows, nb_cols, ridx, cidx] = bd;
1834 for (
auto i = 0;
i != nb_rows; ++
i, ptr += nb_cols) {
1836 cblas_dcopy(nb_cols, ptr, 1, sub_ptr, 1);
1840 for (
auto &bd : block_data) {
1841 auto &[shift, nb_rows, nb_cols, ridx, cidx] = bd;
1843 for (
auto i = 0;
i != nb_rows; ++
i, ptr += nb_cols) {
1845 cblas_daxpy(nb_cols, 1., ptr, 1, sub_ptr, 1);
1849 if (trans_A == CblasNoTrans)
1852 block_y.resize(mat_block_size,
false);
1855 for (
auto &b : block_indexing) {
1859 auto [index, size, loc] = b.second;
1860 auto ptr = &y_array[loc];
1861 cblas_dcopy(size, ptr, 1, &block_y[index], 1);
1865 constexpr int nrhs = 1;
1866 ipiv.resize(mat_block_size,
false);
1868 mat_block_size, &*ipiv.data().begin(),
1869 &*block_y.data().begin(), mat_block_size);
1872 <<
"error lapack solve dgesv info = " << info;
1875 "error lapack solve dgesv info = %d", info);
1878 for (
auto &b : block_indexing) {
1879 auto [index, size, loc] = b.second;
1880 auto ptr = &x_array[loc];
1881 cblas_daxpy(size, 1.0, &block_y[index], 1, ptr, 1);
1885 CHKERR VecRestoreArray(x, &x_array);
1886 CHKERR VecRestoreArrayRead(y, &y_array);
1896 std::vector<std::string> fields_name,
1897 std::vector<boost::shared_ptr<Range>> field_ents,
1899 using matrix_range = ublas::matrix_range<MatrixDouble>;
1900 using range = ublas::range;
1903 CHKERR MatShellGetContext(
B, (
void **)&ctx);
1905 constexpr bool debug =
false;
1916 "No preconditionerBlocksPtr");
1919 std::vector<std::pair<UId, UId>> a00_fields_uids;
1920 a00_fields_uids.reserve(fields_name.size());
1921 auto it_field_ents = field_ents.begin();
1922 if (fields_name.size() != field_ents.size()) {
1924 "fields_name.size() != field_ents.size()");
1926 for (
auto &f : fields_name) {
1928 if (*it_field_ents) {
1929 for (
auto p = (*it_field_ents)->pair_begin();
1930 p != (*it_field_ents)->pair_end(); ++p) {
1931 a00_fields_uids.emplace_back(
1942 std::vector<const DiagBlockIndex::Indexes *> fe_blocks;
1943 std::vector<const DiagBlockIndex::Indexes *> a00_blocks;
1944 std::vector<const DiagBlockIndex::Indexes *> a01_blocks;
1945 std::vector<const DiagBlockIndex::Indexes *> a10_blocks;
1946 std::vector<const DiagBlockIndex::Indexes *> a11_blocks;
1952 std::vector<int> glob_idx;
1953 std::vector<int> row_glob_idx, col_glob_idx;
1955 auto &block_index = ctx->
blockIndex.get<1>();
1956 for (
auto it = block_index.begin(); it != block_index.end();) {
1965 auto last_uid = it->getFEUId();
1966 while (it != block_index.end() && it->getFEUId() == last_uid) {
1967 fe_blocks.push_back(&*it);
1971 for (
auto b_ptr : fe_blocks) {
1972 auto check_id = [&](
auto uid) {
1973 for (
auto &uid_pair : a00_fields_uids) {
1974 if (uid >= uid_pair.first && uid < uid_pair.second) {
1980 auto r00 = check_id(b_ptr->getRowUId());
1981 auto c00 = check_id(b_ptr->getColUId());
1983 a00_blocks.push_back(b_ptr);
1984 }
else if (r00 && !c00) {
1985 a01_blocks.push_back(b_ptr);
1986 }
else if (!r00 && c00) {
1987 a10_blocks.push_back(b_ptr);
1989 a11_blocks.push_back(b_ptr);
1993 for (
auto b : a11_blocks) {
1995 row_glob_idx.resize(b->getNbRows());
1996 col_glob_idx.resize(b->getNbCols());
1998 std::iota(row_glob_idx.begin(), row_glob_idx.end(), b->getRow());
1999 std::iota(col_glob_idx.begin(), col_glob_idx.end(), b->getCol());
2000 CHKERR AOApplicationToPetsc(ao, col_glob_idx.size(), col_glob_idx.data());
2001 CHKERR AOApplicationToPetsc(ao, row_glob_idx.size(), row_glob_idx.data());
2003 auto shift = b->getMatShift();
2007 col_glob_idx.size(), col_glob_idx.data(), ptr,
2012 col_glob_idx.size(), col_glob_idx.data(), ptr,
2020 <<
"a00_blocks.size() " << a00_blocks.size();
2022 <<
"a01_blocks.size() " << a01_blocks.size();
2024 <<
"a10_blocks.size() " << a10_blocks.size();
2026 <<
"a11_blocks.size() " << a11_blocks.size();
2029 if(a00_blocks.size()) {
2031 for (
auto r : a00_blocks) {
2032 auto r_uid = r->getRowUId();
2033 auto range = ctx->
blockIndex.get<2>().equal_range(r_uid);
2034 for (
auto it = range.first; it != range.second; ++it) {
2035 if (it->getFEUId() != last_uid && it->getColUId() != r_uid) {
2036 a01_blocks.push_back(&*it);
2041 for (
auto c : a00_blocks) {
2042 auto c_uid =
c->getColUId();
2043 auto range = ctx->
blockIndex.get<3>().equal_range(c_uid);
2044 for (
auto it = range.first; it != range.second; ++it) {
2045 if (it->getFEUId() != last_uid && it->getRowUId() != c_uid) {
2046 a10_blocks.push_back(&*it);
2051 auto sort = [](
auto &blocks) {
2052 std::sort(blocks.begin(), blocks.end(), [](
auto a,
auto b) {
2053 if (a->getRowUId() == b->getRowUId())
2054 return a->getColUId() < b->getColUId();
2056 return a->getRowUId() < b->getRowUId();
2066 <<
"a01_blocks.size() " << a01_blocks.size();
2068 <<
"a10_blocks.size() " << a10_blocks.size();
2072 auto set_local_indices = [](
auto &row_blocks,
auto &col_blocks) {
2074 std::map<UId, std::tuple<int, int, int>>
2076 for (
auto b : row_blocks) {
2077 if (block_indexing.find(b->getRowUId()) == block_indexing.end()) {
2078 block_indexing[b->getRowUId()] =
2079 std::make_tuple(b->getNbRows(), b->getNbRows(), b->getRow());
2082 for (
auto b : col_blocks) {
2083 if (block_indexing.find(b->getColUId()) == block_indexing.end()) {
2084 block_indexing[b->getColUId()] =
2085 std::make_tuple(b->getNbCols(), b->getNbCols(), b->getCol());
2089 int mat_block_size = 0;
2090 for (
auto &b : block_indexing) {
2092 auto &[index, size, glob] = b.second;
2093 index = mat_block_size;
2094 mat_block_size += size;
2096 return std::make_pair(block_indexing, mat_block_size);
2099 auto set_block = [&](
auto &blocks,
auto &row_indexing,
auto &col_indexing,
2101 int col_block_size) {
2102 std::vector<std::tuple<int, int, int, int, int>> block_data;
2103 block_data.reserve(blocks.size());
2104 for (
auto s : blocks) {
2105 auto ruid = s->getRowUId();
2106 auto cuid = s->getColUId();
2107 auto &rbi = row_indexing.at(ruid);
2108 auto &cbi = col_indexing.at(cuid);
2109 if (
auto shift = s->getMatShift(); shift != -1) {
2110 block_data.push_back(std::make_tuple(
2114 s->getNbRows(), s->getNbCols(),
2116 get<0>(rbi), get<0>(cbi))
2121 block_mat.resize(row_block_size, col_block_size,
false);
2123 for (
auto &bd : block_data) {
2124 auto &[shift, nb_rows, nb_cols, ridx, cidx] = bd;
2126 for (
auto i = 0;
i != nb_rows; ++
i, ptr += nb_cols) {
2128 cblas_dcopy(nb_cols, ptr, 1, sub_ptr, 1);
2132 for (
auto &bd : block_data) {
2133 auto &[shift, nb_rows, nb_cols, ridx, cidx] = bd;
2135 for (
auto i = 0;
i != nb_rows; ++
i, ptr += nb_cols) {
2137 cblas_daxpy(nb_cols, 1., ptr, 1, sub_ptr, 1);
2143 auto [a00_indexing, a00_size] = set_local_indices(a00_blocks, a00_blocks);
2144 auto [a11_indexing, a11_size] = set_local_indices(a10_blocks, a01_blocks);
2148 <<
"a00_indexing.size() " << a00_indexing.size() <<
" a00_size "
2151 <<
"a11_indexing.size() " << a11_indexing.size() <<
" a11_size "
2155 set_block(a00_blocks, a00_indexing, a00_indexing, block_mat_a00, a00_size,
2157 set_block(a01_blocks, a00_indexing, a11_indexing, block_mat_a01, a00_size,
2159 set_block(a10_blocks, a11_indexing, a00_indexing, block_mat_a10, a11_size,
2161 block_mat_a11.resize(a11_size, a11_size,
false);
2162 block_mat_a11.clear();
2164 block_mat_a00 = trans(block_mat_a00);
2165 block_mat_a01 = trans(block_mat_a01);
2167 ipiv.resize(block_mat_a00.size1(),
false);
2169 lapack_dgesv(block_mat_a00.size1(), block_mat_a01.size1(),
2170 block_mat_a00.data().data(), block_mat_a00.size2(),
2171 &*ipiv.data().begin(), block_mat_a01.data().data(),
2172 block_mat_a01.size2());
2175 "lapack error info = %d", info);
2178 cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasTrans,
2179 block_mat_a11.size1(), block_mat_a11.size2(),
2180 block_mat_a00.size1(), -1.,
2182 block_mat_a10.data().data(), block_mat_a10.size2(),
2184 block_mat_a01.data().data(), block_mat_a01.size2(),
2186 0., block_mat_a11.data().data(), block_mat_a11.size2()
2191 std::vector<int> glob_idx(block_mat_a11.size1());
2192 for (
auto &r : a11_indexing) {
2193 auto [r_index, r_size, r_glob] = r.second;
2194 std::iota(&glob_idx[idx], &glob_idx[idx + r_size], r_glob);
2197 CHKERR AOApplicationToPetsc(ao, glob_idx.size(), glob_idx.data());
2199 glob_idx.data(), block_mat_a11.data().data(),
2212 CHKERR MatShellGetContext(
B, (
void **)&ctx);
2216boost::shared_ptr<std::vector<double>>
2219 CHKERR MatShellGetContext(
B, (
void **)&ctx);
2228 boost::shared_ptr<std::vector<double>> data_blocks_ptr) {
2252 auto get_row_data = [&]() -> std::pair<bool, VectorInt> {
2254 if (
auto stored_data_ptr =
2256 MOFEM_LOG(
"SELF", Sev::warning) <<
"Can lead to unhandled behaviour";
2257 return std::make_pair(
true, stored_data_ptr->entityIndices);
2260 return std::make_pair(
false, row_data.
getIndices());
2263 auto row_indices = get_row_data();
2265 std::vector<int> ent_row_indices;
2266 std::vector<int> ent_col_indices;
2269 if (
auto r_cache = rent->entityCacheRowDofs.lock()) {
2271 auto &row_uid = rent->getLocalUniqueId();
2272 auto &row_ind = row_indices.second;
2275 if (
auto c_cache = cent->entityCacheColDofs.lock()) {
2277 auto &col_uid = cent->getLocalUniqueId();
2282 boost::make_tuple(row_uid, col_uid)
2291 <<
"missing block: row "
2295 "Block not allocated");
2300 auto ri = row_ind.begin();
2301 auto rie = row_ind.end();
2303 auto shift = shift_extractor(&*it);
2304 auto s_mat = &(*data_blocks_ptr)[shift];
2306 auto get_ent_indices = [](
auto &cache,
auto &ind) {
2308 ind.reserve(std::distance(cache->loHi[0], cache->loHi[1]));
2309 for (
auto e = cache->loHi[0]; e != cache->loHi[1]; ++e) {
2310 auto glob = (*e)->getPetscGlobalDofIdx();
2312 ind.push_back(glob);
2316 get_ent_indices(r_cache, ent_row_indices);
2317 if (ent_row_indices.empty())
2319 get_ent_indices(c_cache, ent_col_indices);
2320 if (ent_col_indices.empty())
2323 if (mat.size1() == ent_row_indices.size() &&
2324 mat.size2() == ent_col_indices.size()) {
2326 if (iora == ADD_VALUES) {
2327 cblas_daxpy(mat.data().size(), 1.0, mat.data().data(), 1, s_mat,
2330 cblas_dcopy(mat.data().size(), mat.data().data(), 1, s_mat, 1);
2336 for (
auto re : ent_row_indices) {
2337 ri = std::find(ri, rie, re);
2338 if (!(ri == rie && *ri != -1)) {
2340 auto ci = col_ind.begin();
2341 auto cie = col_ind.end();
2344 for (
auto ce : ent_col_indices) {
2345 ci = std::find(ci, cie, ce);
2346 if (!(ci == cie && *ci != -1)) {
2347 auto &
m = s_mat[row * ent_col_indices.size() + col];
2348 if (iora == ADD_VALUES) {
2349 m += mat(std::distance(row_ind.begin(), ri),
2350 std::distance(col_ind.begin(), ci));
2352 m = mat(std::distance(row_ind.begin(), ri),
2353 std::distance(col_ind.begin(), ci));
2381 PetscBool is_mat_shell = PETSC_FALSE;
2382 PetscObjectTypeCompare((PetscObject)M, MATSHELL, &is_mat_shell);
2385 CHKERR MatShellGetContext(M, (
void **)&ctx);
2387 ctx, row_data, col_data, mat, iora,
2391 CHKERR MatSetValues<AssemblyTypeSelector<PETSC>>(M, row_data, col_data, mat,
2402 PetscBool is_mat_shell = PETSC_FALSE;
2403 PetscObjectTypeCompare((PetscObject)M, MATSHELL, &is_mat_shell);
2406 CHKERR MatShellGetContext(M, (
void **)&ctx);
2409 "No preconditionerBlocksPtr");
2411 ctx, row_data, col_data, mat, iora,
2415 CHKERR MatSetValues<AssemblyTypeSelector<PETSC>>(M, row_data, col_data, mat,
2424 boost::shared_ptr<BlockStructure> block_mat_data_ptr,
2426 std::vector<std::string> fields_names,
2427 std::vector<boost::shared_ptr<Range>>
2429 bool add_preconditioner_block) {
2431 if (!block_mat_data_ptr) {
2435 if (fields_names.size() != field_ents.size())
2437 "fields_names.size() != field_ents.size()");
2439 auto [schur_dm, block_dm] = dms;
2444 auto schur_dofs_row = schur_prb->getNumeredRowDofsPtr();
2445 auto schur_dofs_col = schur_prb->getNumeredColDofsPtr();
2446 auto block_dofs_row = block_prb->getNumeredRowDofsPtr();
2447 auto block_dofs_col = block_prb->getNumeredColDofsPtr();
2449 auto ao_schur_row = schur_prb->getSubData()->getSmartRowMap();
2450 auto ao_schur_col = schur_prb->getSubData()->getSmartColMap();
2451 auto ao_block_row = block_prb->getSubData()->getSmartRowMap();
2452 auto ao_block_col = block_prb->getSubData()->getSmartColMap();
2458 CHKERR VecSetDM(schur_vec_x, PETSC_NULLPTR);
2459 CHKERR VecSetDM(block_vec_x, PETSC_NULLPTR);
2460 CHKERR VecSetDM(schur_vec_y, PETSC_NULLPTR);
2461 CHKERR VecSetDM(block_vec_y, PETSC_NULLPTR);
2463 auto find_field_ent = [&](
auto uid,
auto prb,
auto rc) {
2464 boost::shared_ptr<NumeredDofEntity_multiIndex> dofs;
2468 dofs = prb->getNumeredRowDofsPtr();
2471 dofs = prb->getNumeredColDofsPtr();
2480 return boost::shared_ptr<NumeredDofEntity>();
2486 return boost::shared_ptr<NumeredDofEntity>();
2489 std::array<boost::shared_ptr<BlockStructure>, 4> data_ptrs;
2491 for (
auto r = 0; r != 3; ++r) {
2492 data_ptrs[r] = boost::make_shared<BlockStructure>();
2493 data_ptrs[r]->dataBlocksPtr = block_mat_data_ptr->dataBlocksPtr;
2495 data_ptrs[3] = boost::make_shared<BlockStructure>();
2496 data_ptrs[3]->dataBlocksPtr = block_mat_data_ptr->dataBlocksPtr;
2498 data_ptrs[0]->ghostX = schur_vec_x;
2499 data_ptrs[0]->ghostY = schur_vec_y;
2500 data_ptrs[1]->ghostX = block_vec_x;
2501 data_ptrs[1]->ghostY = schur_vec_y;
2502 data_ptrs[2]->ghostX = schur_vec_x;
2503 data_ptrs[2]->ghostY = block_vec_y;
2504 data_ptrs[3]->ghostX = block_vec_x;
2505 data_ptrs[3]->ghostY = block_vec_y;
2508 for (
auto &d : block_mat_data_ptr->blockIndex.get<0>()) {
2510 auto insert = [&](
auto &
m,
auto &dof_r,
auto &dof_c,
auto &d) {
2514 d.getRowUId(), d.getColUId(), d.getFEUId(),
2516 dof_r->getPetscGlobalDofIdx(), dof_c->getPetscGlobalDofIdx(),
2518 d.getNbRows(), d.getNbCols(),
2520 dof_r->getPetscLocalDofIdx(), dof_c->getPetscLocalDofIdx(),
2527 auto dof_schur_row = find_field_ent(d.getRowUId(), schur_prb,
ROW);
2528 auto dof_schur_col = find_field_ent(d.getColUId(), schur_prb,
COL);
2529 auto dof_block_row = find_field_ent(d.getRowUId(), block_prb,
ROW);
2530 auto dof_block_col = find_field_ent(d.getColUId(), block_prb,
COL);
2532 if (dof_schur_row && dof_schur_col) {
2533 insert(data_ptrs[0]->blockIndex, dof_schur_row, dof_schur_col, d);
2536 if (dof_schur_row && dof_block_col) {
2537 insert(data_ptrs[1]->blockIndex, dof_schur_row, dof_block_col, d);
2540 if (dof_block_row && dof_schur_col) {
2541 insert(data_ptrs[2]->blockIndex, dof_block_row, dof_schur_col, d);
2544 if (dof_block_row && dof_block_col) {
2545 insert(data_ptrs[3]->blockIndex, dof_block_row, dof_block_col, d);
2552 auto set_up_a00_data = [&](
auto inv_block_data) {
2555 if (add_preconditioner_block) {
2556 auto preconditioned_block = boost::make_shared<std::vector<double>>(
2557 inv_block_data->dataBlocksPtr->size(), 0);
2558 inv_block_data->preconditionerBlocksPtr = preconditioned_block;
2559 inv_block_data->multiplyByPreconditioner =
true;
2560 block_mat_data_ptr->preconditionerBlocksPtr =
2561 inv_block_data->preconditionerBlocksPtr;
2562 block_mat_data_ptr->multiplyByPreconditioner =
false;
2568 CHKERR set_up_a00_data(data_ptrs[3]);
2571 CHKERR PetscObjectGetComm((PetscObject)schur_dm, &comm);
2573 auto create_shell_mat = [&](
auto nb_r_loc,
auto nb_c_loc,
auto nb_r_glob,
2574 auto nb_c_glob,
auto data_ptr) {
2576 CHKERR MatCreateShell(comm, nb_r_loc, nb_c_loc, nb_r_glob, nb_c_glob,
2577 (
void *)data_ptr.get(), &mat_raw);
2582 auto schur_nb_global = schur_prb->getNbDofsRow();
2583 auto block_nb_global = block_prb->getNbDofsRow();
2584 auto schur_nb_local = schur_prb->getNbLocalDofsRow();
2585 auto block_nb_local = block_prb->getNbLocalDofsRow();
2587 std::array<SmartPetscObj<Mat>, 4> mats_array;
2589 create_shell_mat(schur_nb_local, schur_nb_local, schur_nb_global,
2590 schur_nb_global, data_ptrs[0]);
2592 create_shell_mat(schur_nb_local, block_nb_local, schur_nb_global,
2593 block_nb_global, data_ptrs[1]);
2595 create_shell_mat(block_nb_local, schur_nb_local, block_nb_global,
2596 schur_nb_global, data_ptrs[2]);
2598 create_shell_mat(block_nb_local, block_nb_local, block_nb_global,
2599 block_nb_global, data_ptrs[3]);
2602 <<
"(0, 0) " << schur_nb_local <<
" " << schur_nb_global <<
" "
2603 << data_ptrs[0]->blockIndex.size();
2605 <<
"(0, 1) " << schur_nb_local <<
" " << block_nb_local <<
" "
2606 << schur_nb_global <<
" " << block_nb_global <<
" "
2607 << data_ptrs[1]->blockIndex.size();
2609 <<
"(1, 0) " << block_nb_local <<
" " << schur_nb_local <<
" "
2610 << block_nb_global <<
" " << schur_nb_global <<
" "
2611 << data_ptrs[2]->blockIndex.size();
2613 <<
"(1, 1) " << block_nb_local <<
" " << block_nb_global <<
" "
2614 << data_ptrs[3]->blockIndex.size();
2618 auto schur_is = schur_prb->getSubData()->getSmartRowIs();
2619 auto block_is = block_prb->getSubData()->getSmartRowIs();
2621 return boost::make_shared<NestSchurData>(
2623 mats_array, data_ptrs, block_mat_data_ptr,
2624 std::make_pair(schur_is, block_is)
2629std::pair<SmartPetscObj<Mat>, boost::shared_ptr<NestSchurData>>
2632 if (!schur_net_data_ptr)
2635 auto [mat_arrays, data_ptrs, block_mat_data_ptr, iss] = *schur_net_data_ptr;
2636 auto [schur_is, block_is] = iss;
2638 std::array<IS, 2> is_a = {schur_is, block_is};
2639 std::array<Mat, 4> mats_a = {
2641 mat_arrays[0], mat_arrays[1], mat_arrays[2], mat_arrays[3]
2646 CHKERR PetscObjectGetComm((PetscObject)mat_arrays[0], &comm);
2651 comm, 2, is_a.data(), 2, is_a.data(), mats_a.data(), &mat_raw
2662OpSchurAssembleBase *
2664 std::vector<boost::shared_ptr<Range>> field_ents,
2666 bool sym_schur,
bool symm_op) {
2669 schur, sym_schur, symm_op);
2672 schur, sym_schur, symm_op);
2676 boost::shared_ptr<std::vector<unsigned char>> marker_ptr,
double diag_val) {
2680OpSchurAssembleBase *
2682 std::vector<boost::shared_ptr<Range>> field_ents,
2685 std::vector<bool> sym_schur,
bool symm_op,
2686 boost::shared_ptr<BlockStructure> diag_blocks) {
2688 fields_name, field_ents, sequence_of_aos.back(), sequence_of_mats.back(),
2689 sym_schur.back(), symm_op);
2692OpSchurAssembleBase *
2694 std::vector<boost::shared_ptr<Range>> field_ents,
2697 std::vector<bool> sym_schur,
2698 std::vector<double> diag_eps,
bool symm_op,
2699 boost::shared_ptr<BlockStructure> diag_blocks) {
2701 fields_name, field_ents, sequence_of_aos.back(), sequence_of_mats.back(),
2702 sym_schur.back(), symm_op);
2708 auto apply = [](PC pc, Vec f, Vec x) {
2711 CHKERR PCGetOperators(pc, &
A, &P);
2712 CHKERR MatSolve(P, f, x);
2716 auto apply_transpose = [](PC pc, Vec f, Vec x) {
2719 CHKERR PCGetOperators(pc, &
A, &P);
2720 CHKERR MatSolveTranspose(P, f, x);
2724 CHKERR PCSetType(pc, PCSHELL);
2725 CHKERR PCShellSetApply(pc, apply);
2726 CHKERR PCShellSetApplyTranspose(pc, apply_transpose);
2727 CHKERR PCShellSetName(pc,
"MoFEMSchurBlockPC");
2746 return MatSetValues<AssemblyTypeSelector<PETSC>>(M, row_data, col_data, mat,
2806 col_data, mat, iora);
2838 M, row_data, col_data, mat, iora);
2854 if (block_mat_data->multiplyByPreconditioner) {
2855 block_mat_data->multiplyByPreconditioner =
false;
2857 if (!block_mat_data->preconditionerBlocksPtr) {
2859 "preconditionerBlocksPtr not set");
2861 block_mat_data->multiplyByPreconditioner =
true;
2868 std::string filename) {
2872 moab::Interface &moab = core;
2874 ReadUtilIface *iface;
2875 CHKERR moab.query_interface(iface);
2877 auto size = block_mat_data->blockIndex.size();
2880 vector<double *> arrays_coord;
2881 CHKERR iface->get_node_coords(3, 4 * size, 0, starting_vertex, arrays_coord);
2884 CHKERR iface->get_element_connect(size, 4, MBQUAD, 0, starting_handle, array);
2886 double def_val_nrm2 = 0;
2888 CHKERR moab.tag_get_handle(
"nrm2", 1, MB_TYPE_DOUBLE, th_nrm2,
2889 MB_TAG_CREAT | MB_TAG_DENSE, &def_val_nrm2);
2891 int def_val_mat_shift = 0;
2893 CHKERR moab.tag_get_handle(
"mat_shift", 1, MB_TYPE_INTEGER, th_mat_shift,
2894 MB_TAG_CREAT | MB_TAG_DENSE, &def_val_mat_shift);
2897 for (
auto &d : block_mat_data->blockIndex) {
2898 auto row = d.getRow();
2899 auto col = d.getCol();
2900 auto nb_rows = d.getNbRows();
2901 auto nb_cols = d.getNbCols();
2902 auto mat_shift = d.getMatShift();
2905 arrays_coord[0][4 *
i + 0] = row;
2906 arrays_coord[1][4 *
i + 0] = col;
2907 arrays_coord[2][4 *
i + 0] = 0;
2910 arrays_coord[0][4 *
i + 1] = row + nb_rows;
2911 arrays_coord[1][4 *
i + 1] = col;
2912 arrays_coord[2][4 *
i + 1] = 0;
2915 arrays_coord[0][4 *
i + 2] = row + nb_rows;
2916 arrays_coord[1][4 *
i + 2] = col + nb_cols;
2917 arrays_coord[2][4 *
i + 2] = 0;
2920 arrays_coord[0][4 *
i + 3] = row;
2921 arrays_coord[1][4 *
i + 3] = col + nb_cols;
2922 arrays_coord[2][4 *
i + 3] = 0;
2925 array[4 *
i + 0] = starting_vertex + 4 *
i + 0;
2926 array[4 *
i + 1] = starting_vertex + 4 *
i + 1;
2927 array[4 *
i + 2] = starting_vertex + 4 *
i + 2;
2928 array[4 *
i + 3] = starting_vertex + 4 *
i + 3;
2930 auto prt = &(*block_mat_data->dataBlocksPtr)[d.getMatShift()];
2931 auto nrm2 = cblas_dnrm2(nb_rows * nb_cols, prt, 1);
2933 CHKERR moab.tag_set_data(th_nrm2, &ele, 1, &nrm2);
2934 CHKERR moab.tag_set_data(th_mat_shift, &ele, 1, &mat_shift);
2939 CHKERR iface->update_adjacencies(starting_handle, size, 4, array);
2940 CHKERR moab.write_file(filename.c_str(),
"VTK",
"");
#define MOFEM_LOG_SEVERITY_SYNC(comm, severity)
Synchronise "SYNC" on curtain severity level.
#define MOFEM_TAG_AND_LOG(channel, severity, tag)
Tag and log in channel.
#define MAX_DOFS_ON_ENTITY
Maximal number of DOFs on entity.
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define BITFIELDID_SIZE
max number of fields
@ MOFEM_OPERATION_UNSUCCESSFUL
@ MOFEM_DATA_INCONSISTENCY
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
auto createDMVector(DM dm)
Get smart vector from DM.
PetscErrorCode DMoFEMLoopFiniteElementsUpAndLowRank(DM dm, const char fe_name[], MoFEM::FEMethod *method, int low_rank, int up_rank, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
#define MOFEM_LOG(channel, severity)
Log.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
FTensor::Index< 'i', SPACE_DIM > i
const double c
speed of light (cm/ns)
const double v
phase velocity of light in medium (cm/ns)
const double n
refractive index of diffusive medium
static __CLPK_integer lapack_dgesv(__CLPK_integer n, __CLPK_integer nrhs, __CLPK_doublereal *a, __CLPK_integer lda, __CLPK_integer *ipiv, __CLPK_doublereal *b, __CLPK_integer ldb)
static __CLPK_integer lapack_dgetrf(__CLPK_integer m, __CLPK_integer n, __CLPK_doublereal *a, __CLPK_integer lda, __CLPK_integer *ipiv)
static __CLPK_integer lapack_dgetri(__CLPK_integer n, __CLPK_doublereal *a, __CLPK_integer lda, __CLPK_integer *ipiv, __CLPK_doublereal *work, __CLPK_integer lwork)
FTensor::Index< 'j', 3 > j
static MoFEMErrorCodeGeneric< PetscErrorCode > ierr
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
UBlasMatrix< double > MatrixDouble
UBlasVector< double > VectorDouble
UBlasVector< int > VectorInt
implementation of Data Operators for Forces and Sources
auto type_from_handle(const EntityHandle h)
get type from entity handle
MoFEMErrorCode MatSetValues< SchurElemMats >(Mat M, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, const MatrixDouble &mat, InsertMode iora)
MoFEMErrorCode schur_mat_set_values_wrap(Mat M, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, const MatrixDouble &mat, InsertMode iora)
static auto cmp_uid_lo(const boost::weak_ptr< FieldEntity > &a, const UId &b)
static PetscErrorCode solve_add(Mat mat, Vec x, Vec y)
OpSchurAssembleBase * createOpSchurAssembleEnd(std::vector< std::string > fields_name, std::vector< boost::shared_ptr< Range > > field_ents, SmartPetscObj< AO > ao, SmartPetscObj< Mat > schur, bool sym_schur, bool symm_op)
Construct a new Op Schur Assemble End object.
static auto cmp_uid_hi(const UId &b, const boost::weak_ptr< FieldEntity > &a)
MoFEMErrorCode MatSetValues< SchurElemMatsBlock >(Mat M, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, const MatrixDouble &mat, InsertMode iora)
auto isAllGather(IS is)
IS All gather.
static MoFEMErrorCode mult_schur_block_shell(Mat mat, Vec x, Vec y, InsertMode iora, boost::function< int(DiagBlockIndex::BlockIndex::nth_index< 0 >::type::iterator)> shift_extractor, boost::shared_ptr< std::vector< double > > data_blocks_ptr, bool multiply_by_preconditioner, enum CBLAS_TRANSPOSE trans_A)
MoFEMErrorCode schurSwitchPreconditioner(boost::shared_ptr< BlockStructure > block_mat_data)
Switch preconditioner.
MoFEMErrorCode setSchurA00MatSolvePC(SmartPetscObj< PC > pc)
Set PC for A00 block.
constexpr bool debug_schur
static PetscErrorCode solve_transpose_add(Mat mat, Vec x, Vec y)
auto id_from_handle(const EntityHandle h)
MoFEMErrorCode MatSetValues< SchurElemMatsPreconditionedBlock >(Mat M, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, const MatrixDouble &mat, InsertMode iora)
std::pair< SmartPetscObj< Mat >, boost::shared_ptr< BlockStructure > > SchurShellMatData
std::pair< SmartPetscObj< Mat >, boost::shared_ptr< NestSchurData > > createSchurNestedMatrix(boost::shared_ptr< NestSchurData > schur_net_data_ptr)
Create a Mat Diag Blocks object.
static PetscErrorCode mult_transpose_add(Mat mat, Vec x, Vec y)
MoFEMErrorCode MatSetValues< BlockStructure >(Mat M, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, const MatrixDouble &mat, InsertMode iora)
MoFEMErrorCode shell_block_mat_asmb_wrap(Mat M, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, const MatrixDouble &mat, InsertMode iora)
auto createISGeneral(MPI_Comm comm, PetscInt n, const PetscInt idx[], PetscCopyMode mode)
Creates a data structure for an index set containing a list of integers.
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
static PetscErrorCode solve(Mat mat, Vec x, Vec y)
boost::shared_ptr< std::vector< double > > getBlockMatPrconditionerStorageMat(Mat B)
Get the Block Storage object.
static PetscErrorCode zero_rows_columns(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
boost::shared_ptr< BlockStructure > createBlockMatStructure(DM dm, SchurFEOpsFEandFields schur_fe_op_vec)
Create a Mat Diag Blocks object.
boost::shared_ptr< NestSchurData > createSchurNestedMatrixStruture(std::pair< SmartPetscObj< DM >, SmartPetscObj< DM > > dms, boost::shared_ptr< BlockStructure > block_mat_data_ptr, std::vector< std::string > fields_names, std::vector< boost::shared_ptr< Range > > field_ents, bool add_preconditioner_block)
Get the Schur Nest Mat Array object.
static PetscErrorCode mult_add(Mat mat, Vec x, Vec y)
MoFEMErrorCode shell_block_mat_asmb_wrap_impl(BlockStructure *ctx, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, const MatrixDouble &mat, InsertMode iora, boost::function< int(const DiagBlockIndex::Indexes *)> shift_extractor, boost::shared_ptr< std::vector< double > > data_blocks_ptr)
MoFEMErrorCode MatSetValues(Mat M, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, const double *ptr, InsertMode iora)
Assemble PETSc matrix.
static PetscErrorCode mult_transpose(Mat mat, Vec x, Vec y)
auto field_bit_from_bit_number(const int bit_number)
get field bit id from bit number
OpSchurAssembleBase * createOpSchurZeroRowsAndCols(boost::shared_ptr< std::vector< unsigned char > > marker_ptr, double diag_val)
Create a Op Schur Zero Rows And Cols object.
static PetscErrorCode mat_zero(Mat m)
MoFEMErrorCode schurSaveBlockMesh(boost::shared_ptr< BlockStructure > block_mat_data, std::string filename)
Save block matrix as a mesh.
auto getInterfacePtr(DM dm)
Get the Interface Ptr object.
static PetscErrorCode mult(Mat mat, Vec x, Vec y)
static PetscErrorCode solve_transpose(Mat mat, Vec x, Vec y)
static MoFEMErrorCode solve_schur_block_shell(Mat mat, Vec y, Vec x, InsertMode iora, enum CBLAS_TRANSPOSE trans_A)
std::vector< std::pair< std::string, std::vector< SchurFieldPair > > > SchurFEOpsFEandFields
static MoFEMErrorCode setSchurBlockMatOps(Mat mat_raw)
MoFEMErrorCode shell_block_preconditioner_mat_asmb_wrap(Mat M, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, const MatrixDouble &mat, InsertMode iora)
auto getProblemPtr(DM dm)
get problem pointer from DM
SchurShellMatData createBlockMat(DM dm, boost::shared_ptr< BlockStructure > data)
Create a Schur Mat object.
MoFEMErrorCode assembleBlockMatSchur(MoFEM::Interface &m_field, Mat B, Mat S, std::vector< std::string > fields_name, std::vector< boost::shared_ptr< Range > > field_ents, SmartPetscObj< AO > ao)
Assemble Schur matrix.
OpSchurAssembleBase * createOpSchurAssembleBegin()
auto ent_form_type_and_id(const EntityType type, const EntityID id)
get entity handle from type and id
boost::shared_ptr< std::vector< double > > getBlockMatStorageMat(Mat B)
Get the Block Storage object.
SmartPetscObj< Mat > block_mat
FTensor::Index< 'm', 3 > m
bool multiplyByPreconditioner
boost::shared_ptr< std::vector< double > > preconditionerBlocksPtr
boost::shared_ptr< std::vector< double > > parentBlockStructurePtr
boost::shared_ptr< std::vector< double > > dataBlocksPtr
SmartPetscObj< Vec > ghostX
SmartPetscObj< Vec > ghostY
virtual FieldBitNumber get_field_bit_number(const std::string name) const =0
get field bit number
Deprecated interface functions.
Indexes(UId uid_row, UId uid_col, UId uid_fe, int row, int col, int nb_rows, int nb_cols, int loc_row, int loc_col, int mat_shift)
int & getMatShift() const
multi_index_container< Indexes, indexed_by< ordered_unique< composite_key< Indexes, const_mem_fun< Indexes, UId, &Indexes::getRowUId >, const_mem_fun< Indexes, UId, &Indexes::getColUId > > >, ordered_non_unique< const_mem_fun< Indexes, UId, &Indexes::getFEUId > >, ordered_non_unique< const_mem_fun< Indexes, UId, &Indexes::getRowUId > >, ordered_non_unique< const_mem_fun< Indexes, UId, &Indexes::getColUId > > > > BlockIndex
virtual ~DiagBlockIndex()=default
BlockIndex blockIndex
blocks indexes storage
static UId getLoFieldEntityUId(const FieldBitNumber bit, const EntityHandle ent)
static UId getHiFieldEntityUId(const FieldBitNumber bit, const EntityHandle ent)
static UId getUniqueIdCalculate(const DofIdx dof, UId ent_uid)
Data on single entity (This is passed as argument to DataOperator::doWork)
const VectorFieldEntities & getFieldEntities() const
Get field entities (const version)
const VectorDofs & getFieldDofs() const
Get DOF data structures (const version)
const VectorInt & getIndices() const
Get global indices of degrees of freedom on entity.
[Storage and set boundary conditions]
Structure for user loop methods on finite elements.
static UId getHiBitNumberUId(const FieldBitNumber bit_number)
static auto getHandleFromUniqueId(const UId uid)
Get the Handle From Unique Id.
static auto getFieldBitNumberFromUniqueId(const UId uid)
Get the Field Bit Number From Unique Id.
UId getLocalUniqueIdCalculate()
Get the Local Unique Id Calculate object.
static UId getLoBitNumberUId(const FieldBitNumber bit_number)
static UId getLoLocalEntityBitNumber(const char bit_number, const EntityHandle ent)
static UId getHiLocalEntityBitNumber(const char bit_number, const EntityHandle ent)
const FEMethod * getFEMethod() const
Return raw pointer to Finite Element Method object.
OpSchurAssembleBaseImpl()=delete
MoFEMErrorCode assembleSchurMat(Mat S, const UId &uid_row, VectorInt &row_ind, const UId &uid_col, VectorInt &col_ind, MatrixDouble &m, InsertMode iora)
Assemble Schur complement.
OpSchurAssembleBase()=delete
Clear Schur complement internal data.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
Assemble Schur complement (Implementation)
SmartPetscObj< AO > schurAO
MoFEMErrorCode doWorkImpl(int side, EntityType type, EntitiesFieldData::EntData &data)
SmartPetscObj< Mat > schurMat
std::vector< boost::shared_ptr< Range > > fieldEnts
OpSchurAssembleEndImpl(std::vector< std::string > fields_name, std::vector< boost::shared_ptr< Range > > field_ents, SmartPetscObj< AO > schur_ao, SmartPetscObj< Mat > schur_mat, bool sym_schur, bool symm_op)
Construct a new Op Schur Assemble End object.
std::vector< std::string > fieldsName
Assemble Schur complement.
OpSchurZeroRowsAndCols(boost::shared_ptr< std::vector< unsigned char > > marker_ptr, double diag_val)
boost::shared_ptr< std::vector< unsigned char > > markerPtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
static MatSetValuesPtr matSetValuesPreconditionedBlockPtr
static MatSetValuesPtr matSetValuesPtr
backend assembly function
static MatSetValuesPtr matSetValuesBlockPtr
backend assembly block mat function
boost::function< MoFEMErrorCode(Mat M, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, const MatrixDouble &mat, InsertMode iora)> MatSetValuesPtr
static auto invertMat(MatrixDouble &m, MatrixDouble &inv)
static auto invertMat(MatrixDouble &m, MatrixDouble &inv)
static MoFEMErrorCode MatSetValues(Mat M, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, const MatrixDouble &mat, InsertMode iora)
static MoFEMErrorCode MatSetValues(Mat M, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, const MatrixDouble &mat, InsertMode iora)
Schur complement data storage.
static MoFEMErrorCode assembleStorage(const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, const MatrixDouble &mat, InsertMode iora)
static boost::ptr_vector< VectorInt > colIndices
static boost::ptr_vector< MatrixDouble > locMats
SchurElemMats(const size_t idx, const UId uid_row, const UId uid_col)
virtual ~SchurElemMats()=default
static size_t maxIndexCounter
static boost::ptr_vector< VectorInt > rowIndices
static MoFEMErrorCode MatSetValues(Mat M, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, const MatrixDouble &mat, InsertMode iora)
static boost::ptr_vector< SchurElemMats > schurElemMats
static SchurElemStorage schurL2Storage
multi_index_container< const SchurElemMats *, indexed_by< ordered_unique< tag< uid_mi_tag >, composite_key< SchurElemMats, member< SchurElemMats, const UId, &SchurElemMats::uidRow >, member< SchurElemMats, const UId, &SchurElemMats::uidCol > > >, ordered_non_unique< tag< col_mi_tag >, member< SchurElemMats, const UId, &SchurElemMats::uidCol > > > > SchurElemStorage
static PetscLogEvent MOFEM_EVENT_BlockStructureSetValues
static PetscLogEvent MOFEM_EVENT_BlockStructureMult
static PetscLogEvent MOFEM_EVENT_zeroRowsAndCols
static PetscLogEvent MOFEM_EVENT_opSchurAssembleEnd
static PetscLogEvent MOFEM_EVENT_BlockStructureSolve
static PetscLogEvent MOFEM_EVENT_schurMatSetValues
static PetscLogEvent MOFEM_EVENT_AssembleSchurMat
intrusive_ptr for managing petsc objects