18 : iDX(idx), uidRow(uid_row), uidCol(uid_col) {}
27 return MatSetValues<AssemblyTypeSelector<PETSC>>(
M, row_data, col_data, mat,
42 auto get_row_indices = [&]() ->
const VectorInt & {
44 if (
auto stored_data_ptr =
46 return stored_data_ptr->entityIndices;
52 const auto &row_ind = get_row_indices();
55 const auto nb_rows = row_ind.size();
56 const auto nb_cols = col_ind.size();
59 if (mat.size1() != nb_rows) {
61 "Wrong mat size %d != %d", mat.size1(), nb_rows);
63 if (mat.size2() != nb_cols) {
65 "Wrong mat size %d != %d", mat.size2(), nb_cols);
79 auto get_uid = [](
auto &data) {
80 if (data.getFieldEntities().size() == 1) {
82 return data.getFieldEntities()[0]->getLocalUniqueId();
91 auto &uid0 = data.getFieldEntities()[0]->getLocalUniqueId();
97 for (
auto i = 1;
i < data.getFieldEntities().size(); ++
i) {
104 data.getFieldEntities()[
i]->getLocalUniqueId())
120 auto uid_row = get_uid(row_data);
121 auto uid_col = get_uid(col_data);
124 auto get_storage = [&
p]() {
return const_cast<SchurL2Mats &
>(*
p.first); };
128 auto asmb = [&](
auto &sm) {
129 sm.resize(nb_rows, nb_cols,
false);
133 asmb(get_storage().
getMat());
135 auto add_indices = [](
auto &storage,
auto &ind) {
136 storage.resize(ind.size(),
false);
137 noalias(storage) = ind;
140 add_indices(get_storage().
getRowInd(), row_ind);
141 add_indices(get_storage().
getColInd(), col_ind);
145 auto asmb = [&](
auto &sm) {
149 if (sm.size1() != nb_rows) {
151 "Wrong mat or storage size %d != %d", sm.size1(), nb_rows);
153 if (sm.size2() != nb_cols) {
155 "Wrong mat or storage size %d != %d", sm.size2(), nb_cols);
168 "Assembly type not implemented");
184 MOFEM_LOG(
"SELF", Sev::noisy) <<
"Schur assemble begin";
188 auto zero_mats = [&](
auto &mats) {
189 for (
auto &
m : mats) {
190 m.resize(0, 0,
false);
200 std::vector<std::string> fields_name,
201 std::vector<boost::shared_ptr<Range>> field_ents,
204 std::vector<bool> sym_schur, std::vector<double> diag_eps,
bool symm_op)
206 fieldsName(fields_name), fieldEnts(field_ents),
207 sequenceOfAOs(sequence_of_aos), sequenceOfMats(sequence_of_mats),
208 symSchur(sym_schur), diagEps(diag_eps) {}
211 std::vector<std::string> fields_name,
212 std::vector<boost::shared_ptr<Range>> field_ents,
215 std::vector<bool> sym_schur,
bool symm_op)
217 fieldsName(fields_name), fieldEnts(field_ents),
218 sequenceOfAOs(sequence_of_aos), sequenceOfMats(sequence_of_mats),
219 symSchur(sym_schur), diagEps(fields_name.size(), 0) {}
228 MOFEM_LOG(
"SELF", Sev::noisy) <<
"Schur assemble begin -> end";
235 for (
auto &s : storage) {
236 auto &
m = s.getMat();
238 auto &row_ind = s.getRowInd();
239 auto &col_ind = s.getColInd();
241 if (mat_set_values(
M, row_ind.size(), &*row_ind.begin(),
242 col_ind.size(), &*col_ind.begin(),
243 &*
m.data().begin(), ADD_VALUES)) {
245 auto row_ent_it = field_ents->find(s.uidRow);
246 auto col_ent_it = field_ents->find(s.uidCol);
248 if (row_ent_it != field_ents->end())
250 <<
"Assemble row entity: " << (*row_ent_it)->getName() <<
" "
251 << (*col_ent_it)->getEntTypeName() <<
" side "
252 << (*row_ent_it)->getSideNumber();
253 if (col_ent_it != field_ents->end())
255 <<
"Assemble col entity: " << (*col_ent_it)->getName() <<
" "
256 << (*col_ent_it)->getEntTypeName() <<
" side "
257 << (*col_ent_it)->getSideNumber();
266 auto apply_schur = [&](
auto &storage,
270 auto lo_uid,
auto hi_uid,
double eps) {
273 auto add_off_mat = [&](
auto row_uid,
auto col_uid,
auto &row_ind,
276 auto it = storage.template get<SchurL2Mats::uid_mi_tag>().find(
277 boost::make_tuple(row_uid, col_uid));
278 if (it == storage.template get<SchurL2Mats::uid_mi_tag>().end()) {
293 auto &mat =
p.first->getMat();
294 auto &set_row_ind =
p.first->getRowInd();
295 auto &set_col_ind =
p.first->getColInd();
297 if (mat.size1() != set_row_ind.size()) {
299 "Wrong size %d != %d", mat.size1(), set_row_ind.size());
301 if (mat.size2() != set_col_ind.size()) {
303 "Wrong size %d != %d", mat.size2(), set_col_ind.size());
307 noalias(set_row_ind) = row_ind;
308 noalias(set_col_ind) = col_ind;
310 auto &mat = it->getMat();
314 "Wrong size %d != %d", mat.size1(),
319 "Wrong size %d != %d", mat.size2(),
328 auto get_row_view = [&]() {
330 storage.template get<SchurL2Mats::row_mi_tag>().lower_bound(lo_uid);
332 storage.template get<SchurL2Mats::row_mi_tag>().upper_bound(hi_uid);
333 std::vector<const SchurL2Mats *> schur_row_ptr_view;
334 schur_row_ptr_view.reserve(std::distance(row_it, hi_row_it));
335 for (; row_it != hi_row_it; ++row_it) {
336 schur_row_ptr_view.push_back(&*row_it);
338 return schur_row_ptr_view;
341 auto get_col_view = [&]() {
343 storage.template get<SchurL2Mats::col_mi_tag>().lower_bound(lo_uid);
345 storage.template get<SchurL2Mats::col_mi_tag>().upper_bound(hi_uid);
346 std::vector<const SchurL2Mats *> schur_col_ptr_view;
347 schur_col_ptr_view.reserve(std::distance(col_it, hi_col_it));
348 for (; col_it != hi_col_it; ++col_it) {
349 schur_col_ptr_view.push_back(&*col_it);
351 return schur_col_ptr_view;
354 auto schur_row_ptr_view = get_row_view();
355 auto schur_col_ptr_view = get_col_view();
357 for (
auto row_it : schur_row_ptr_view) {
358 if (row_it->uidRow == row_it->uidCol) {
362 for (
auto c_lo : schur_col_ptr_view) {
364 auto &row_uid = c_lo->uidRow;
365 if (row_uid == row_it->uidRow)
368 auto &cc_off_mat = c_lo->getMat();
371 if (
invMat.size1() != cc_off_mat.size2()) {
373 "Wrong size %d != %d",
invMat.size1(), cc_off_mat.size2());
378 for (
auto r_lo : schur_row_ptr_view) {
379 auto &col_uid = r_lo->uidCol;
382 if (col_uid == row_it->uidRow)
386 if (
symSchur[ss] && row_uid > col_uid)
389 auto &rr_off_mat = r_lo->getMat();
391 rr_off_mat.size2(),
false);
395 "Wrong size %d != %d", rr_off_mat.size1(),
401 CHKERR add_off_mat(row_uid, col_uid, c_lo->getRowInd(),
404 if (
symSchur[ss] && row_uid != col_uid) {
409 CHKERR add_off_mat(col_uid, row_uid, r_lo->getColInd(),
420 auto erase_factored = [&](
auto &storage,
422 const auto ss,
auto lo_uid,
auto hi_uid) {
426 storage.template get<SchurL2Mats::row_mi_tag>().lower_bound(lo_uid);
428 storage.template get<SchurL2Mats::row_mi_tag>().upper_bound(hi_uid);
429 storage.template get<SchurL2Mats::row_mi_tag>().erase(r_lo, r_hi);
432 storage.template get<SchurL2Mats::col_mi_tag>().lower_bound(lo_uid);
434 storage.template get<SchurL2Mats::col_mi_tag>().upper_bound(hi_uid);
435 storage.template get<SchurL2Mats::col_mi_tag>().erase(c_lo, c_hi);
440 auto assemble_off_diagonal = [&](
auto &storage,
const auto ss) {
444 for (
auto &
m : storage) {
446 auto &ind_row =
m.getRowInd();
447 CHKERR AOApplicationToPetsc(ao, ind_row.size(), &*ind_row.begin());
448 auto &ind_col =
m.getColInd();
449 CHKERR AOApplicationToPetsc(ao, ind_col.size(), &*ind_col.begin());
466 for (
auto ss = 0; ss !=
fieldsName.size(); ++ss) {
468 auto assemble = [&](
auto &storage,
auto ss,
auto lo_uid,
auto hi_uid) {
471 CHKERR apply_schur(storage, ss, lo_uid, hi_uid,
diagEps[ss]);
472 CHKERR erase_factored(storage, ss, lo_uid, hi_uid);
473 CHKERR assemble_off_diagonal(storage, ss);
481 for (
auto p = row_ents->pair_begin();
p != row_ents->pair_end(); ++
p) {
486 CHKERR assemble(storage, ss, lo_uid, hi_uid);
491 field_bit, get_id_for_min_type<MBVERTEX>());
493 field_bit, get_id_for_max_type<MBENTITYSET>());
494 CHKERR assemble(storage, ss, lo_uid, hi_uid);
499 MOFEM_LOG(
"SELF", Sev::noisy) <<
"Schur assemble done";
510 const int nb =
m.size1();
513 for (
int cc = 0; cc != nb; ++cc) {
518 inv.resize(nb, nb,
false);
520 for (
int cc = 0; cc != nb; ++cc)
522 ipiv.resize(nb,
false);
523 lapack_work.resize(nb * nb,
false);
525 lapack_dsysv(
'L', nb, nb, &*
m.data().begin(), nb, &*ipiv.begin(),
526 &*inv.data().begin(), nb, &*lapack_work.begin(), nb * nb);
529 "Can not invert matrix info = %d", info);
538 const auto nb =
m.size1();
540 if (nb !=
m.size2()) {
542 "It should be square matrix");
547 for (
int cc = 0; cc != nb; ++cc) {
552 inv.resize(nb, nb,
false);
554 for (
int c = 0;
c != nb; ++
c)
556 ipiv.resize(nb,
false);
557 const auto info =
lapack_dgesv(nb, nb, &*
m.data().begin(), nb,
558 &*ipiv.begin(), &*inv.data().begin(), nb);
561 "Can not invert matrix info = %d", info);
569 return doWorkImpl<SCHUR_DSYSV>(side, type, data);
575 return doWorkImpl<SCHUR_DGESV>(side, type, data);
ForcesAndSourcesCore::UserDataOperator UserDataOperator
#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 ...
@ 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 ...
FTensor::Index< 'm', SPACE_DIM > m
virtual const FieldEntity_multiIndex * get_field_ents() const =0
Get the field ents object.
#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)
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_dsysv(char uplo, __CLPK_integer n, __CLPK_integer nrhs, __CLPK_doublereal *a, __CLPK_integer lda, __CLPK_integer *ipiv, __CLPK_doublereal *b, __CLPK_integer ldb, __CLPK_doublereal *work, __CLPK_integer lwork)
static MoFEMErrorCodeGeneric< PetscErrorCode > ierr
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
UBlasMatrix< double > MatrixDouble
UBlasVector< int > VectorInt
implementation of Data Operators for Forces and Sources
auto type_from_handle(const EntityHandle h)
get type from entity handle
MoFEMErrorCode schur_mat_set_values_wrap(Mat M, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, const MatrixDouble &mat, InsertMode iora)
auto id_from_handle(const EntityHandle h)
MoFEMErrorCode MatSetValues(Mat M, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, const double *ptr, InsertMode iora)
Assemble PETSc matrix.
auto ent_form_type_and_id(const EntityType type, const EntityID id)
get entity handle from type and id
virtual FieldBitNumber get_field_bit_number(const std::string name) const =0
get field bit number
Data on single entity (This is passed as argument to DataOperator::doWork)
const VectorFieldEntities & getFieldEntities() const
get field entities
const VectorInt & getIndices() const
Get global indices of dofs on entity.
[Storage and set boundary conditions]
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 getLoLocalEntityBitNumber(const char bit_number, const EntityHandle ent)
static UId getHiLocalEntityBitNumber(const char bit_number, const EntityHandle ent)
ForcesAndSourcesCore * getPtrFE() const
structure to get information form mofem into EntitiesFieldData
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
Assemble Schur complement.
MatrixDouble offMatInvDiagOffMat
std::vector< boost::shared_ptr< Range > > fieldEnts
boost::function< MoFEMErrorCode(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)> MatSetValuesRaw
static MatSetValuesRaw matSetValuesSchurRaw
MoFEMErrorCode doWorkImpl(int side, EntityType type, EntitiesFieldData::EntData &data)
OpSchurAssembleEndImpl(std::vector< std::string > fields_name, std::vector< boost::shared_ptr< Range > > field_ents, std::vector< SmartPetscObj< AO > > sequence_of_aos, std::vector< SmartPetscObj< Mat > > sequence_of_mats, std::vector< bool > sym_schur, bool symm_op=true)
Construct a new Op Schur Assemble End object.
std::vector< bool > symSchur
std::vector< std::string > fieldsName
MatrixDouble invDiagOffMat
std::vector< SmartPetscObj< Mat > > sequenceOfMats
std::vector< SmartPetscObj< AO > > sequenceOfAOs
MatrixDouble transOffMatInvDiagOffMat
std::vector< double > diagEps
static auto invertMat(MatrixDouble &m, MatrixDouble &inv, double eps)
static auto invertMat(MatrixDouble &m, MatrixDouble &inv, double eps)
SchurL2Mats(const size_t idx, const UId uid_row, const UId uid_col)
static MatSetValuesPtr matSetValuesPtr
backend assembly function
static boost::ptr_vector< VectorInt > rowIndices
static SchurL2Storage schurL2Storage
multi_index_container< SchurL2Mats, indexed_by< ordered_unique< tag< uid_mi_tag >, composite_key< SchurL2Mats, member< SchurL2Mats, const UId, &SchurL2Mats::uidRow >, member< SchurL2Mats, const UId, &SchurL2Mats::uidCol > > >, ordered_non_unique< tag< row_mi_tag >, member< SchurL2Mats, const UId, &SchurL2Mats::uidRow > >, ordered_non_unique< tag< col_mi_tag >, member< SchurL2Mats, const UId, &SchurL2Mats::uidCol > > > > SchurL2Storage
static boost::ptr_vector< VectorInt > colIndices
boost::function< MoFEMErrorCode(Mat M, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, const MatrixDouble &mat, InsertMode iora)> MatSetValuesPtr
static MoFEMErrorCode MatSetValues(Mat M, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, const MatrixDouble &mat, InsertMode iora)
static boost::ptr_vector< MatrixDouble > locMats
intrusive_ptr for managing petsc objects