13static char help[] =
"...\n\n";
30 AssemblyType::BLOCK_MAT;
32 IntegrationType::GAUSS;
47 return MatSetValues<AssemblyTypeSelector<PETSC>>(
57 return MatSetValues<AssemblyTypeSelector<BLOCK_MAT>>(
67 return MatSetValues<AssemblyTypeSelector<BLOCK_SCHUR>>(
79 return MatSetValues<AssemblyTypeSelector<BLOCK_PRECONDITIONER_SCHUR>>(
85int main(
int argc,
char *argv[]) {
94 moab::Interface &moab = moab_core;
101 DMType dm_name =
"DMMOFEM";
105 auto core_log = logging::core::get();
169 {{simple->getDomainFEName(),
190 auto [mat, block_data_ptr] = shell_data;
193 std::vector<std::string> fields{
"T",
"S",
"O"};
199 {schur_dm, block_dm}, block_data_ptr,
201 fields, {
nullptr,
nullptr,
nullptr}, true
211 using OpMassBlockPreconditionerAssemble =
213 BiLinearForm<GAUSS>::OpMass<1,
FIELD_DIM>;
224 [](
int,
int,
int o) {
return 2 * o; });
225 auto &pip_lhs = pip_mng->getOpDomainLhsPipeline();
227 pip_lhs.push_back(
new OpMassPETSCAssemble(
"V",
"V"));
229 pip_lhs.push_back(
new OpMassPETSCAssemble(
"V",
"T"));
230 pip_lhs.push_back(
new OpMassPETSCAssemble(
"T",
"V"));
231 pip_lhs.push_back(
new OpMassPETSCAssemble(
"S",
"S", close_zero));
232 pip_lhs.push_back(
new OpMassPETSCAssemble(
"S",
"T", beta));
233 pip_lhs.push_back(
new OpMassPETSCAssemble(
"T",
"S", beta));
234 pip_lhs.push_back(
new OpMassPETSCAssemble(
"O",
"O", close_zero));
235 pip_lhs.push_back(
new OpMassPETSCAssemble(
"T",
"O", beta));
236 pip_lhs.push_back(
new OpMassPETSCAssemble(
"O",
"T", beta));
237 pip_lhs.push_back(
new OpMassPETSCAssemble(
"S",
"O", gamma));
238 pip_lhs.push_back(
new OpMassPETSCAssemble(
"O",
"S", beta));
241 pip_lhs.push_back(
new OpMassBlockAssemble(
"V",
"V"));
243 pip_lhs.push_back(
new OpMassBlockAssemble(
"V",
"T"));
244 pip_lhs.push_back(
new OpMassBlockAssemble(
"T",
"V"));
245 pip_lhs.push_back(
new OpMassBlockAssemble(
"S",
"S", close_zero));
246 pip_lhs.push_back(
new OpMassBlockAssemble(
"S",
"T", beta));
247 pip_lhs.push_back(
new OpMassBlockAssemble(
"T",
"S", beta));
248 pip_lhs.push_back(
new OpMassBlockAssemble(
"O",
"O", close_zero));
249 pip_lhs.push_back(
new OpMassBlockAssemble(
"T",
"O", beta));
250 pip_lhs.push_back(
new OpMassBlockAssemble(
"O",
"T", beta));
251 pip_lhs.push_back(
new OpMassBlockAssemble(
"S",
"O", gamma));
252 pip_lhs.push_back(
new OpMassBlockAssemble(
"O",
"S", beta));
253 pip_lhs.push_back(
new OpMassBlockPreconditionerAssemble(
"T",
"T"));
255 auto schur_is =
getDMSubData(schur_dm)->getSmartRowIs();
260 fields, {
nullptr,
nullptr,
nullptr}, ao_up, S,
true,
true)
267 BOOST_LOG_SCOPED_THREAD_ATTR(
"Timeline", attrs::timer());
268 MOFEM_LOG(
"Timeline", Sev::inform) <<
"Assemble start";
270 simple->getDomainFEName(),
271 pip_mng->getDomainLhsFE());
272 MOFEM_LOG(
"Timeline", Sev::inform) <<
"Assemble end";
277 BOOST_LOG_SCOPED_THREAD_ATTR(
"Timeline", attrs::timer());
278 MOFEM_LOG(
"Timeline", Sev::inform) <<
"Mat assemble start";
281 MOFEM_LOG(
"Timeline", Sev::inform) <<
"Mat assemble end";
284 auto get_random_vector = [&](
auto dm) {
287 PetscRandomCreate(PETSC_COMM_WORLD, &rctx);
289 PetscRandomDestroy(&rctx);
292 auto v = get_random_vector(
simple->getDM());
297 auto test = [](
auto msg,
auto y,
double norm0) {
304 CHKERR VecNorm(y, NORM_2, &norm);
308 << msg <<
": norm of difference: " << norm;
309 if (norm >
eps || std::isnan(norm) || std::isinf(norm)) {
310 SETERRQ(PETSC_COMM_WORLD, 1,
"norm of difference is too big");
315 std::vector<int> zero_rows_and_cols = {
319 &*zero_rows_and_cols.begin(), 1, PETSC_NULLPTR,
322 &*zero_rows_and_cols.begin(), 1, PETSC_NULLPTR,
329 BOOST_LOG_SCOPED_THREAD_ATTR(
"Timeline", attrs::timer());
331 <<
"MatMult(petsc_mat, v, y_petsc) star";
334 <<
"MatMult(petsc_mat, v, y_petsc) end";
337 CHKERR VecNorm(y_petsc, NORM_2, &nrm0);
342 BOOST_LOG_SCOPED_THREAD_ATTR(
"Timeline", attrs::timer());
344 <<
"MatMult(block_mat, v, y_block) star";
347 <<
"MatMult(block_mat, v, y_block) end";
349 CHKERR VecAXPY(y_petsc, -1.0, y_block);
350 CHKERR test(
"mult", y_petsc, nrm0);
361 CHKERR VecAXPY(y_petsc, -1.0, y_block);
362 CHKERR test(
"mult add", y_petsc, nrm0);
367 CHKERR VecAXPY(y_petsc, -1.0, y_block);
368 CHKERR test(
"mult transpose", y_petsc, nrm0);
375 CHKERR VecAXPY(y_petsc, -1.0, y_block);
376 CHKERR test(
"mult add transpose", y_petsc, nrm0);
382 CHKERR MatMult(nested_mat,
v, y_nested);
383 CHKERR VecAXPY(y_petsc, -1.0, y_nested);
384 CHKERR test(
"mult nested", y_petsc, nrm0);
387 auto diag_mat = std::get<0>(*nested_data_ptr)[3];
388 auto diag_block_x = get_random_vector(block_dm);
391 CHKERR MatMult(diag_mat, diag_block_x, diag_block_f);
395 CHKERR MatSolve(diag_mat, diag_block_f, block_solved_x);
397 CHKERR MatMult(diag_mat, block_solved_x, diag_block_f_test);
398 CHKERR VecAXPY(diag_block_f_test, -1.0, diag_block_f);
399 CHKERR test(
"diag solve", diag_block_f_test, nrm0);
401 CHKERR MatSolveTranspose(diag_mat, diag_block_f, block_solved_x);
402 CHKERR MatMultTranspose(diag_mat, block_solved_x, diag_block_f_test);
403 CHKERR VecAXPY(diag_block_f_test, -1.0, diag_block_f);
404 CHKERR test(
"diag transpose solve", diag_block_f_test, nrm0);
407 CHKERR DMSetMatType(block_dm, MATSHELL);
410 CHKERR DMKSPSetComputeOperators(
412 [](KSP, Mat, Mat,
void *) {
413 MOFEM_LOG(
"WORLD", Sev::inform) <<
"empty operator";
418 auto ksp =
createKSP(m_field.get_comm());
419 CHKERR KSPSetDM(ksp, block_dm);
420 CHKERR KSPSetFromOptions(ksp);
423 auto get_pc = [](
auto ksp) {
425 CHKERR KSPGetPC(ksp, &pc_raw);
431 CHKERR VecZeroEntries(block_solved_x);
432 CHKERR KSPSolve(ksp, diag_block_f, block_solved_x);
434 CHKERR MatMult(diag_mat, block_solved_x, diag_block_f_test);
435 CHKERR VecAXPY(diag_block_f_test, -1.0, diag_block_f);
436 CHKERR test(
"diag solve", diag_block_f_test, nrm0);
439 CHKERR VecZeroEntries(block_solved_x);
440 CHKERR KSPSolveTranspose(ksp, diag_block_f, block_solved_x);
441 CHKERR MatMultTranspose(diag_mat, block_solved_x, diag_block_f_test);
442 CHKERR VecAXPY(diag_block_f_test, -1.0, diag_block_f);
443 CHKERR test(
"diag transpose solve", diag_block_f_test, nrm0);
445 if (m_field.get_comm_rank() == 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 CATCH_ERRORS
Catch errors.
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
@ 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.
static LoggerType & setLog(const std::string channel)
Set ans resset chanel logger.
#define MOFEM_LOG(channel, severity)
Log.
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
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 based on block entities.
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()
SmartPetscObj< Mat > block_mat
constexpr int SPACE_DIM
[Define dimension]
constexpr IntegrationType I
SmartPetscObj< Mat > petsc_mat
FTensor::Index< 'm', 3 > m
Boundary condition manager for finite element problem setup.
virtual MPI_Comm & get_comm() 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)
static boost::shared_ptr< SinkType > createSink(boost::shared_ptr< std::ostream > stream_ptr, std::string comm_filter)
Create a sink object.
static boost::shared_ptr< std::ostream > getStrmWorld()
Get the strm world object.
boost::function< MoFEMErrorCode(ForcesAndSourcesCore::UserDataOperator *op_ptr, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, MatrixDouble &m)> MatSetValuesHook
PipelineManager interface.
MoFEM::FaceElementForcesAndSourcesCore FaceEle
MoFEMErrorCode setDomainLhsIntegrationRule(RuleHookFun rule)
Set integration rule for domain left-hand side finite element.
Simple interface for fast problem set-up.
MoFEMErrorCode getOptions()
get options
intrusive_ptr for managing petsc objects
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
Volume finite element base.