532 MOFEM_LOG(
"SELF", Sev::noisy) <<
"Schur assemble begin -> end";
535 auto get_field_name = [&](
auto 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;
547 for (
auto ss = 0; ss !=
fieldsName.size(); ++ss) {
548 auto field_bit = get_field_bit(
fieldsName[ss]);
551 for (
auto p = row_ents->pair_begin(); p != row_ents->pair_end(); ++p) {
556 a00_uids.push_back(std::make_pair(lo_uid, hi_uid));
560 field_bit, get_id_for_min_type<MBVERTEX>());
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;
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) {
697 &*s->getRowInd().begin());
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) {
764 for (
auto j : zero_cols) {
769 for (
auto i : zero_rows) {
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()) {
787 &*s->getRowInd().begin());
789 if (block_indexing.find(s->uidCol) == block_indexing.end()) {
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(
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";