Test block matrix and Schur complement matrix.
Test block matrix and Schur complement matrix.
static char help[] =
"...\n\n";
};
using DomainEle = VolumeElementForcesAndSourcesCore;
};
AssemblyType::BLOCK_MAT;
IntegrationType::GAUSS;
template <>
[](ForcesAndSourcesCore::UserDataOperator *op_ptr,
return MatSetValues<AssemblyTypeSelector<PETSC>>(
};
template <>
[](ForcesAndSourcesCore::UserDataOperator *op_ptr,
return MatSetValues<AssemblyTypeSelector<BLOCK_MAT>>(
};
template <>
[](ForcesAndSourcesCore::UserDataOperator *op_ptr,
return MatSetValues<AssemblyTypeSelector<BLOCK_SCHUR>>(
};
template <>
[](ForcesAndSourcesCore::UserDataOperator *op_ptr,
return MatSetValues<AssemblyTypeSelector<BLOCK_PRECONDITIONER_SCHUR>>(
};
constexpr bool debug =
false;
int main(
int argc,
char *argv[]) {
try {
moab::Core moab_core;
moab::Interface &moab = moab_core;
DMType dm_name = "DMMOFEM";
auto core_log = logging::core::get();
core_log->add_sink(
LogManager::createSink(LogManager::getStrmWorld(), "Timeline"));
LogManager::setLog("Timeline");
"T", 0, 1);
auto shell_data =
{{simple->getDomainFEName(),
{{"V", "V"},
{"T", "T"},
{"S", "S"},
{"O", "O"},
{"V", "T"},
{"T", "V"},
{"S", "T"},
{"T", "S"},
{"T", "O"},
{"O", "T"},
{"S", "O"},
{"O", "S"}
}}}
)
);
auto [mat, block_data_ptr] = shell_data;
std::vector<std::string> fields{"T", "S", "O"};
{schur_dm, block_dm}, block_data_ptr,
fields, {nullptr, nullptr, nullptr}, true
)
);
using OpMassBlockPreconditionerAssemble =
[](int, int, int o) { return 2 * o; });
auto &pip_lhs = pip_mng->getOpDomainLhsPipeline();
pip_lhs.push_back(new OpMassPETSCAssemble("V", "V"));
pip_lhs.push_back(new OpMassPETSCAssemble("V", "T"));
pip_lhs.push_back(new OpMassPETSCAssemble("T", "V"));
pip_lhs.push_back(new OpMassPETSCAssemble("S", "S", close_zero));
pip_lhs.push_back(new OpMassPETSCAssemble("S", "T", beta));
pip_lhs.push_back(new OpMassPETSCAssemble("T", "S", beta));
pip_lhs.push_back(new OpMassPETSCAssemble("O", "O", close_zero));
pip_lhs.push_back(new OpMassPETSCAssemble("T", "O", beta));
pip_lhs.push_back(new OpMassPETSCAssemble("O", "T", beta));
pip_lhs.push_back(new OpMassPETSCAssemble("S", "O", gamma));
pip_lhs.push_back(new OpMassPETSCAssemble("O", "S", gamma));
pip_lhs.push_back(new OpMassBlockAssemble("V", "V"));
pip_lhs.push_back(new OpMassBlockAssemble("V", "T"));
pip_lhs.push_back(new OpMassBlockAssemble("T", "V"));
pip_lhs.push_back(new OpMassBlockAssemble("S", "S", close_zero));
pip_lhs.push_back(new OpMassBlockAssemble("S", "T", beta));
pip_lhs.push_back(new OpMassBlockAssemble("T", "S", beta));
pip_lhs.push_back(new OpMassBlockAssemble("O", "O", close_zero));
pip_lhs.push_back(new OpMassBlockAssemble("T", "O", beta));
pip_lhs.push_back(new OpMassBlockAssemble("O", "T", beta));
pip_lhs.push_back(new OpMassBlockAssemble("S", "O", gamma));
pip_lhs.push_back(new OpMassBlockAssemble("O", "S", gamma));
pip_lhs.push_back(new OpMassBlockPreconditionerAssemble("T", "T"));
fields, {nullptr, nullptr, nullptr}, ao_up, S, true, true)
);
{
BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
MOFEM_LOG(
"Timeline", Sev::inform) <<
"Assemble start";
pip_mng->getDomainLhsFE());
MOFEM_LOG(
"Timeline", Sev::inform) <<
"Assemble end";
}
{
BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
MOFEM_LOG(
"Timeline", Sev::inform) <<
"Mat assemble start";
MOFEM_LOG(
"Timeline", Sev::inform) <<
"Mat assemble end";
}
auto get_random_vector = [&](auto dm) {
PetscRandom rctx;
PetscRandomCreate(PETSC_COMM_WORLD, &rctx);
PetscRandomDestroy(&rctx);
};
auto v = get_random_vector(
simple->getDM());
auto test = [](auto msg, auto y, double norm0) {
PetscReal norm;
CHKERR VecNorm(y, NORM_2, &norm);
norm = norm / norm0;
<< msg << ": norm of difference: " << norm;
if (norm >
eps || std::isnan(norm) || std::isinf(norm)) {
SETERRQ(PETSC_COMM_WORLD, 1, "norm of difference is too big");
}
};
std::vector<int> zero_rows_and_cols = {
0, 1, 10, 20,
500};
&*zero_rows_and_cols.begin(), 1, PETSC_NULL,
PETSC_NULL);
&*zero_rows_and_cols.begin(), 1, PETSC_NULL,
PETSC_NULL);
{
BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
<< "MatMult(petsc_mat, v, y_petsc) star";
<< "MatMult(petsc_mat, v, y_petsc) end";
}
double nrm0;
CHKERR VecNorm(y_petsc, NORM_2, &nrm0);
{
BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
<< "MatMult(block_mat, v, y_block) star";
<< "MatMult(block_mat, v, y_block) end";
}
CHKERR VecAXPY(y_petsc, -1.0, y_block);
CHKERR test(
"mult", y_petsc, nrm0);
CHKERR VecAXPY(y_petsc, -1.0, y_block);
CHKERR test(
"mult add", y_petsc, nrm0);
CHKERR MatMult(nested_mat,
v, y_nested);
CHKERR VecAXPY(y_petsc, -1.0, y_nested);
CHKERR test(
"mult nested", y_petsc, nrm0);
auto diag_mat = std::get<0>(*nested_data_ptr)[3];
auto diag_block_x = get_random_vector(block_dm);
CHKERR MatMult(diag_mat, diag_block_x, diag_block_f);
CHKERR DMSetMatType(block_dm, MATSHELL);
CHKERR DMKSPSetComputeOperators(
block_dm,
[](KSP, Mat, Mat, void *) {
MOFEM_LOG(
"WORLD", Sev::inform) <<
"empty operator";
return 0;
},
nullptr);
CHKERR KSPSetDM(ksp, block_dm);
CHKERR KSPSetFromOptions(ksp);
auto get_pc = [](auto ksp) {
PC pc_raw;
CHKERR KSPGetPC(ksp, &pc_raw);
};
CHKERR VecZeroEntries(block_solved_x);
CHKERR KSPSolve(ksp, diag_block_f, block_solved_x);
CHKERR MatMult(diag_mat, block_solved_x, diag_block_f_test);
CHKERR VecAXPY(diag_block_f_test, -1.0, diag_block_f);
CHKERR test(
"diag solve", diag_block_f_test, nrm0);
}
}
return 0;
}
#define MOFEM_TAG_AND_LOG(channel, severity, tag)
Tag and log in channel.
void simple(double P1[], double P2[], double P3[], double c[], const int N)
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
[Define dimension]
#define CATCH_ERRORS
Catch errors.
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base nme:nme847.
@ L2
field with C-1 continuity
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
PetscErrorCode DMMoFEMCreateSubDM(DM subdm, DM dm, const char problem_name[])
Must be called by user to set Sub DM MoFEM data structures.
PetscErrorCode DMMoFEMAddElement(DM dm, std::string fe_name)
add element to dm
PetscErrorCode DMMoFEMSetSquareProblem(DM dm, PetscBool square_problem)
set squared problem
PetscErrorCode DMMoFEMAddSubFieldRow(DM dm, const char field_name[])
PetscErrorCode DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
auto createDMVector(DM dm)
Get smart vector from DM.
PetscErrorCode DMMoFEMAddSubFieldCol(DM dm, const char field_name[])
auto createDMMatrix(DM dm)
Get smart matrix from DM.
#define MOFEM_LOG(channel, severity)
Log.
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
const double v
phase velocity of light in medium (cm/ns)
implementation of Data Operators for Forces and Sources
auto createKSP(MPI_Comm comm)
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.
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
MoFEMErrorCode schurSwitchPreconditioner(boost::shared_ptr< BlockStructure > block_mat_data)
Switch preconditioner.
MoFEMErrorCode setSchurA00MatSolvePC(SmartPetscObj< PC > pc)
Set PC for A00 block.
std::pair< SmartPetscObj< Mat >, boost::shared_ptr< NestSchurData > > createSchurNestedMatrix(boost::shared_ptr< NestSchurData > schur_net_data_ptr)
Create a Mat Diag Blocks object.
PetscErrorCode PetscOptionsGetScalar(PetscOptions *, const char pre[], const char name[], PetscScalar *dval, PetscBool *set)
auto getDMSubData(DM dm)
Get sub problem data structure.
MoFEMErrorCode DMMoFEMSetBlocMatData(DM dm, boost::shared_ptr< BlockStructure >)
Set data for block mat.
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.
auto createAOMappingIS(IS isapp, IS ispetsc)
Creates an application mapping using two index sets.
MoFEMErrorCode schurSaveBlockMesh(boost::shared_ptr< BlockStructure > block_mat_data, std::string filename)
Save block matrix as a mesh.
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
SchurShellMatData createBlockMat(DM dm, boost::shared_ptr< BlockStructure > data)
Create a Schur Mat object.
OpSchurAssembleBase * createOpSchurAssembleBegin()
constexpr IntegrationType I
SmartPetscObj< Mat > block_mat
SmartPetscObj< Mat > petsc_mat
FTensor::Index< 'm', 3 > m
Simple interface for fast problem set-up.
MoFEMErrorCode removeBlockDOFsOnEntities(const std::string problem_name, const std::string block_name, const std::string field_name, int lo, int hi, bool get_low_dim_ents=true, bool is_distributed_mesh=true)
Remove DOFs from problem.
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)
boost::function< MoFEMErrorCode( ForcesAndSourcesCore::UserDataOperator *op_ptr, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, MatrixDouble &m)> MatSetValuesHook
PipelineManager interface.
MoFEMErrorCode setDomainLhsIntegrationRule(RuleHookFun rule)
Simple interface for fast problem set-up.
intrusive_ptr for managing petsc objects
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.