v0.15.0
Loading...
Searching...
No Matches
Classes | Public Types | Public Member Functions | Protected Attributes | Friends | List of all members
MoFEM::SnesCtx Struct Reference

Interface for nonlinear (SNES) solver. More...

#include "src/petsc/SnesCtx.hpp"

Collaboration diagram for MoFEM::SnesCtx:
[legend]

Classes

struct  SnesCtxImpl
 

Public Types

using PairNameFEMethodPtr = MoFEM::PairNameFEMethodPtr
 
using FEMethodsSequence = MoFEM::FEMethodsSequence
 
using BasicMethodsSequence = MoFEM::BasicMethodsSequence
 
using HookFunction = boost::function< MoFEMErrorCode(SNES snes, Vec x, Vec F, boost::shared_ptr< CacheTuple > cache_ptr, void *ctx)>
 

Public Member Functions

 SnesCtx (Interface &m_field, std::string problem_name)
 
virtual ~SnesCtx ()
 
FEMethodsSequencegetSetOperators ()
 
FEMethodsSequencegetComputeRhs ()
 
BasicMethodsSequencegetPreProcComputeRhs ()
 
BasicMethodsSequencegetPostProcComputeRhs ()
 
BasicMethodsSequencegetPreProcSetOperators ()
 
BasicMethodsSequencegetPostProcSetOperators ()
 
FEMethodsSequencegetLoadTangent ()
 Get the finite element pipeline for FunctionFn, that calculate tangent of function load for arc length control.
 
BasicMethodsSequencegetPreProcLoadTangent ()
 Get the BasicMethod sequence for preprocessing of FunctionFn.
 
BasicMethodsSequencegetPostProcLoadTangent ()
 Get the BasicMethod sequence for postprocessing of FunctionFn.
 
HookFunctiongetLoadTangentHook ()
 Get the Load Tangent Hook function.
 
HookFunctiongetRhsHook ()
 Get the Right Hand Side Hook function.
 
MoFEMErrorCode copyLoops (const SnesCtx &snes_ctx)
 Copy sequences from other SNES context.
 
MoFEMErrorCode clearLoops ()
 Clear loops.
 

Protected Attributes

boost::movelib::unique_ptr< SnesCtxImplsnesCtxImpl
 

Friends

PetscErrorCode SnesRhs (SNES snes, Vec x, Vec f, void *ctx)
 This is MoFEM implementation for the right hand side (residual vector) evaluation in SNES solver.
 
PetscErrorCode SnesMat (SNES snes, Vec x, Mat A, Mat B, void *ctx)
 This is MoFEM implementation for the left hand side (tangent matrix) evaluation in SNES solver.
 
MoFEMErrorCode SNESMoFEMSetAssmblyType (SNES snes, MatAssemblyType type)
 
MoFEMErrorCode SnesMoFEMSetBehavior (SNES snes, MoFEMTypes bh)
 Set behavior if finite element in sequence does not exist.
 
MoFEMErrorCode SnesMoFEMSetAssemblyType (SNES snes, MatAssemblyType type)
 Set assembly type at the end of SnesMat.
 
MoFEMErrorCode MoFEMSNESMonitorFields (SNES snes, PetscInt its, PetscReal fgnorm, SnesCtx *snes_ctx)
 Sens monitor printing residual field by field.
 
MoFEMErrorCode MoFEMSNESMonitorEnergy (SNES snes, PetscInt its, PetscReal fgnorm, SnesCtx *snes_ctx)
 Sens monitor printing residual field by field.
 
PetscErrorCode SnesLoadTangent (SNES snes, Vec u, Vec F, void *ctx)
 This function calls finite element pipeline to compute tangent of of load vector in arc length control.
 

Detailed Description

Interface for nonlinear (SNES) solver.

Examples
mofem/tutorials/cor-10/navier_stokes.cpp, mofem/users_modules/basic_finite_elements/atom_tests/testing_jacobian_of_hook_element.cpp, mofem/users_modules/basic_finite_elements/atom_tests/testing_jacobian_of_hook_scaled_with_density_element.cpp, mofem/users_modules/basic_finite_elements/nonlinear_elasticity/nonlinear_dynamics.cpp, and mofem/users_modules/minimal_surface_equation/minimal_surface_area.cpp.

Definition at line 15 of file SnesCtx.hpp.

Member Typedef Documentation

◆ BasicMethodsSequence

Definition at line 19 of file SnesCtx.hpp.

◆ FEMethodsSequence

Definition at line 18 of file SnesCtx.hpp.

◆ HookFunction

using MoFEM::SnesCtx::HookFunction = boost::function<MoFEMErrorCode( SNES snes, Vec x, Vec F, boost::shared_ptr<CacheTuple> cache_ptr, void *ctx)>

Definition at line 20 of file SnesCtx.hpp.

◆ PairNameFEMethodPtr

Definition at line 17 of file SnesCtx.hpp.

Constructor & Destructor Documentation

◆ SnesCtx()

MoFEM::SnesCtx::SnesCtx ( Interface m_field,
std::string  problem_name 
)

Definition at line 125 of file SnesCtx.cpp.

126 : snesCtxImpl(boost::movelib::make_unique<SnesCtx::SnesCtxImpl>(
127 m_field, problem_name)) {}
boost::movelib::unique_ptr< SnesCtxImpl > snesCtxImpl
Definition SnesCtx.hpp:150

◆ ~SnesCtx()

MoFEM::SnesCtx::~SnesCtx ( )
virtualdefault

Member Function Documentation

◆ clearLoops()

MoFEMErrorCode MoFEM::SnesCtx::clearLoops ( )

Clear loops.

Returns
MoFEMErrorCode

Definition at line 171 of file SnesCtx.cpp.

171{ return snesCtxImpl->clearLoops(); }

◆ copyLoops()

MoFEMErrorCode MoFEM::SnesCtx::copyLoops ( const SnesCtx snes_ctx)

Copy sequences from other SNES context.

Parameters
snes_ctxSNES context from which Sequence is copied from
Returns
error code

Definition at line 167 of file SnesCtx.cpp.

167 {
168 return snesCtxImpl->copyLoops(*snes_ctx.snesCtxImpl);
169}

◆ getComputeRhs()

FEMethodsSequence & MoFEM::SnesCtx::getComputeRhs ( )
Returns
return vector to vector with FEMethod to calculate residual

Definition at line 135 of file SnesCtx.cpp.

135 {
136 return snesCtxImpl->getComputeRhs();
137}

◆ getLoadTangent()

FEMethodsSequence & MoFEM::SnesCtx::getLoadTangent ( )

Get the finite element pipeline for FunctionFn, that calculate tangent of function load for arc length control.

Returns
FEMethodsSequence&

Definition at line 155 of file SnesCtx.cpp.

155 {
156 return snesCtxImpl->getLoadTangent();
157}

◆ getLoadTangentHook()

SnesCtx::HookFunction & MoFEM::SnesCtx::getLoadTangentHook ( )

Get the Load Tangent Hook function.

Using hook you can debug or post-process while load vector tangent is evaluated

Returns
HookFunction&

Definition at line 173 of file SnesCtx.cpp.

173 {
174 return snesCtxImpl->getLoadTangentHook();
175}

◆ getPostProcComputeRhs()

BasicMethodsSequence & MoFEM::SnesCtx::getPostProcComputeRhs ( )

The sequence of BasicMethod is executed after residual is calculated. It can be used to setup data structures, e.g. aggregate data from processors or to apply essential boundary conditions.

Returns
reference to BasicMethod for postprocessing

Definition at line 143 of file SnesCtx.cpp.

143 {
144 return snesCtxImpl->getPostProcComputeRhs();
145}

◆ getPostProcLoadTangent()

BasicMethodsSequence & MoFEM::SnesCtx::getPostProcLoadTangent ( )

Get the BasicMethod sequence for postprocessing of FunctionFn.

Returns
BasicMethodsSequence&

Definition at line 163 of file SnesCtx.cpp.

163 {
164 return snesCtxImpl->getPostProcLoadTangent();
165}

◆ getPostProcSetOperators()

BasicMethodsSequence & MoFEM::SnesCtx::getPostProcSetOperators ( )

The sequence of BasicMethod is executed after tangent matrix is calculated. It can be used to setup data structures, e.g. aggregate data from processors or to apply essential boundary conditions.

Returns
reference to BasicMethod for postprocessing

Definition at line 151 of file SnesCtx.cpp.

151 {
152 return snesCtxImpl->getPostProcSetOperators();
153}

◆ getPreProcComputeRhs()

BasicMethodsSequence & MoFEM::SnesCtx::getPreProcComputeRhs ( )

The sequence of BasicMethod is executed before residual is calculated. It can be used to setup data structures, e.g. zero global variable which is integrated in domain, e.g. for calculation of strain energy.

Returns
reference to BasicMethod for preprocessing

Definition at line 139 of file SnesCtx.cpp.

139 {
140 return snesCtxImpl->getPreProcComputeRhs();
141}

◆ getPreProcLoadTangent()

BasicMethodsSequence & MoFEM::SnesCtx::getPreProcLoadTangent ( )

Get the BasicMethod sequence for preprocessing of FunctionFn.

Returns
BasicMethodsSequence&

Definition at line 159 of file SnesCtx.cpp.

159 {
160 return snesCtxImpl->getPreProcLoadTangent();
161}

◆ getPreProcSetOperators()

BasicMethodsSequence & MoFEM::SnesCtx::getPreProcSetOperators ( )
Returns
reference to BasicMethod for preprocessing

Definition at line 147 of file SnesCtx.cpp.

147 {
148 return snesCtxImpl->getPreProcSetOperators();
149}

◆ getRhsHook()

SnesCtx::HookFunction & MoFEM::SnesCtx::getRhsHook ( )

Get the Right Hand Side Hook function.

Using hook you can debug or post-process while right hand side vector is evaluated

Returns
HookFunction&

Definition at line 177 of file SnesCtx.cpp.

177 {
178 return snesCtxImpl->getRhsHook();
179}

◆ getSetOperators()

FEMethodsSequence & MoFEM::SnesCtx::getSetOperators ( )
Returns
return reference to vector with FEMethod to calculate tangent matrix

Definition at line 131 of file SnesCtx.cpp.

131 {
132 return snesCtxImpl->getSetOperators();
133}

Friends And Related Symbol Documentation

◆ MoFEMSNESMonitorEnergy

MoFEMErrorCode MoFEMSNESMonitorEnergy ( SNES  snes,
PetscInt  its,
PetscReal  fgnorm,
SnesCtx snes_ctx 
)
friend

Sens monitor printing residual field by field.

Definition at line 652 of file SnesCtx.cpp.

653 {
655 auto snes_ctx = ctx->snesCtxImpl.get();
656 auto &m_field = snes_ctx->mField;
657 auto problem_ptr = m_field.get_problem(snes_ctx->problemName);
658 auto fields_ptr = m_field.get_fields();
659 auto dofs = problem_ptr->numeredRowDofsPtr;
660
661 std::vector<double> lnorms(3 * fields_ptr->size(), 0),
662 norms(3 * fields_ptr->size(), 0);
663
664 Vec x_update, res;
665 if (its == 0)
666 CHKERR SNESGetSolution(snes, &x_update);
667 else
668 CHKERR SNESGetSolutionUpdate(snes, &x_update);
669 CHKERR SNESGetFunction(snes, &res, PETSC_NULLPTR, PETSC_NULLPTR);
670
671 const double *x, *r;
672 ;
673 CHKERR VecGetArrayRead(res, &r);
674 CHKERR VecGetArrayRead(x_update, &x);
675
676 {
677 int f = 0;
678 for (auto fi : *fields_ptr) {
679 const auto lo_uid = FieldEntity::getLoBitNumberUId(fi->bitNumber);
680 const auto hi_uid = FieldEntity::getHiBitNumberUId(fi->bitNumber);
681 const auto hi = dofs->get<Unique_mi_tag>().upper_bound(hi_uid);
682 for (auto lo = dofs->get<Unique_mi_tag>().lower_bound(lo_uid); lo != hi;
683 ++lo) {
684 const DofIdx loc_idx = (*lo)->getPetscLocalDofIdx();
685 if (loc_idx >= 0 && loc_idx < problem_ptr->nbLocDofsRow) {
686 lnorms[3 * f] += std::abs(x[loc_idx] * r[loc_idx]);
687 lnorms[3 * f + 1] += r[loc_idx] * r[loc_idx];
688 lnorms[3 * f + 2] += x[loc_idx] * x[loc_idx];
689 }
690 }
691 ++f;
692 }
693 }
694 CHKERR VecRestoreArrayRead(res, &r);
695 CHKERR VecRestoreArrayRead(x_update, &x);
696
697 MPIU_Allreduce(&*lnorms.begin(), &*norms.begin(), lnorms.size(), MPIU_REAL,
698 MPIU_SUM, PetscObjectComm((PetscObject)snes));
699
700 double energy_norm = 0, residual_norm = 0, increment_norm = 0;
701 for (int f = 0; f != fields_ptr->size(); ++f) {
702 energy_norm += norms[3 * f];
703 residual_norm += norms[3 * f + 1];
704 increment_norm += norms[3 * f + 2];
705 }
706 energy_norm = std::sqrt(energy_norm);
707 residual_norm = std::sqrt(residual_norm);
708 increment_norm = std::sqrt(increment_norm);
709
710 {
711 MOFEM_LOG("SNES_WORLD", Sev::inform)
712 << its << " Function norm Enrgy/Residual/Increment"
713 << boost::format(" %14.12e ") % energy_norm
714 << boost::format(" %14.12e ") % residual_norm
715 << boost::format(" %14.12e ") % increment_norm << "[";
716 int f = 0;
717 for (auto fi : *fields_ptr) {
718 MOFEM_LOG("SNES_WORLD", Sev::inform)
719 << its << "\t Energy/Residual/Increment norm "
720 << boost::format("%14.12e") % std::sqrt(norms[3 * f]) << "\t"
721 << boost::format("%14.12e") % std::sqrt(norms[3 * f + 1]) << " "
722 << boost::format("%14.12e") % std::sqrt(norms[3 * f + 2]) << "\t "
723 << fi->getName();
724 ++f;
725 }
726 MOFEM_LOG("SNES_WORLD", Sev::inform) << its << " ]";
727 }
728
730}
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MOFEM_LOG(channel, severity)
Log.
const FTensor::Tensor2< T, Dim, Dim > Vec
int DofIdx
Index of DOF.
Definition Types.hpp:18
int r
Definition sdf.py:8
static UId getHiBitNumberUId(const FieldBitNumber bit_number)
static UId getLoBitNumberUId(const FieldBitNumber bit_number)

◆ MoFEMSNESMonitorFields

MoFEMErrorCode MoFEMSNESMonitorFields ( SNES  snes,
PetscInt  its,
PetscReal  fgnorm,
SnesCtx snes_ctx 
)
friend

Sens monitor printing residual field by field.

Definition at line 596 of file SnesCtx.cpp.

597 {
599 auto snes_ctx = ctx->snesCtxImpl.get();
600 auto &m_field = snes_ctx->mField;
601 auto problem_ptr = m_field.get_problem(snes_ctx->problemName);
602 auto fields_ptr = m_field.get_fields();
603 auto dofs = problem_ptr->numeredRowDofsPtr;
604
605 std::vector<double> lnorms(fields_ptr->size(), 0),
606 norms(fields_ptr->size(), 0);
607
608 Vec res;
609 CHKERR SNESGetFunction(snes, &res, NULL, NULL);
610
611 const double *r;
612 CHKERR VecGetArrayRead(res, &r);
613 {
614 int f = 0;
615 for (auto fi : *fields_ptr) {
616 const auto lo_uid = FieldEntity::getLoBitNumberUId(fi->bitNumber);
617 const auto hi_uid = FieldEntity::getHiBitNumberUId(fi->bitNumber);
618 const auto hi = dofs->get<Unique_mi_tag>().upper_bound(hi_uid);
619 for (auto lo = dofs->get<Unique_mi_tag>().lower_bound(lo_uid); lo != hi;
620 ++lo) {
621 const DofIdx loc_idx = (*lo)->getPetscLocalDofIdx();
622 if (loc_idx >= 0 && loc_idx < problem_ptr->nbLocDofsRow) {
623 lnorms[f] += PetscRealPart(PetscSqr(r[loc_idx]));
624 }
625 }
626 ++f;
627 }
628 }
629 CHKERR VecRestoreArrayRead(res, &r);
630
631 MPIU_Allreduce(&*lnorms.begin(), &*norms.begin(), lnorms.size(), MPIU_REAL,
632 MPIU_SUM, PetscObjectComm((PetscObject)snes));
633
634 {
635 MOFEM_LOG("SNES_WORLD", Sev::inform)
636 << its << " Function norm " << boost::format("%14.12e") % (double)fgnorm
637 << " [";
638 int f = 0;
639 for (auto fi : *fields_ptr) {
640 MOFEM_LOG("SNES_WORLD", Sev::inform)
641 << its << "\t Field norm "
642 << boost::format("%14.12e") % (double)PetscSqrtReal(norms[f]) << " "
643 << fi->getName();
644 ++f;
645 }
646 MOFEM_LOG("SNES_WORLD", Sev::inform) << its << "]";
647 }
648
650}

◆ SnesLoadTangent

PetscErrorCode SnesLoadTangent ( SNES  snes,
Vec  u,
Vec  F,
void *  ctx 
)
friend

This function calls finite element pipeline to compute tangent of of load vector in arc length control.

For more information pleas look to PETSc manual, i.e. SNESSetFunction https://petsc.org/main/manualpages/SNES/SNESSetFunction/

Parameters
snesSNES solver
uSolution vector at current iteration
FThe right hand side vector
ctxPointer to context i.e. SnesCtx
Returns
Error code

Definition at line 355 of file SnesCtx.cpp.

355 {
356 auto *snes_ctx = static_cast<SnesCtx *>(ctx)->snesCtxImpl.get();
358 PetscLogEventBegin(snes_ctx->MOFEM_EVENT_SnesLoadTangent, 0, 0, 0, 0);
359 Vec dx;
360 CHKERR SNESGetSolutionUpdate(snes, &dx);
361 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
362 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
363 if (snes_ctx->vErify) {
364 // Verify finite elements, check for not a number
365 CHKERR VecAssemblyBegin(f);
366 CHKERR VecAssemblyEnd(f);
367 MPI_Comm comm = PetscObjectComm((PetscObject)f);
368 PetscSynchronizedPrintf(comm, "SNES Verify x\n");
369 const Problem *prb_ptr;
370 CHKERR snes_ctx->mField.get_problem(snes_ctx->problemName, &prb_ptr);
371 CHKERR snes_ctx->mField.getInterface<Tools>()->checkVectorForNotANumber(
372 prb_ptr, COL, x);
373 }
374 CHKERR snes_ctx->mField.getInterface<VecManager>()->setLocalGhostVector(
375 snes_ctx->problemName, COL, x, INSERT_VALUES, SCATTER_REVERSE);
376
377 auto zero_ghost_vec = [](Vec g) {
379 Vec l;
380 CHKERR VecGhostGetLocalForm(g, &l);
381 double *a;
382 CHKERR VecGetArray(l, &a);
383 int s;
384 CHKERR VecGetLocalSize(l, &s);
385 for (int i = 0; i != s; ++i)
386 a[i] = 0;
387 CHKERR VecRestoreArray(l, &a);
388 CHKERR VecGhostRestoreLocalForm(g, &l);
390 };
391 CHKERR zero_ghost_vec(f);
392
393 auto vec_assemble_switch = boost::movelib::make_unique<bool>(true);
394 auto cache_ptr = boost::make_shared<CacheTuple>();
395 CHKERR snes_ctx->mField.cache_problem_entities(snes_ctx->problemName,
396 cache_ptr);
397
398 auto set = [&](auto &fe) {
400 fe.snes = snes;
401 fe.snes_x = x;
402 fe.snes_dx = dx;
403 fe.snes_f = f;
405 fe.ksp_ctx = KspMethod::CTX_SETFUNCTION;
407
408 CHKERR SNESGetKSP(snes, &fe.ksp);
409
410 // If SNES is of type SNESNEWTONAL then get load parameter, will act as a
411 // pseudo time
412#if PETSC_VERSION_GE(3, 22, 0)
413 PetscBool same;
414 CHKERR PetscObjectTypeCompare((PetscObject)snes, SNESNEWTONAL, &same);
415 if (same) {
416 CHKERR SNESNewtonALGetLoadParameter(snes, &fe.ts_t);
417 fe.data_ctx |= PetscData::CtxSetTime;
418 }
419#endif
420
421 fe.cacheWeakPtr = cache_ptr;
423 };
424
425 auto unset = [&](auto &fe) {
426 fe.snes_ctx = SnesMethod::CTX_SNESNONE;
427 fe.ksp_ctx = KspMethod::CTX_KSPNONE;
428 fe.data_ctx = PetscData::CtxSetNone;
429 };
430
431 for (auto &bit : snes_ctx->preProcessLoadTangent) {
432 bit->vecAssembleSwitch = boost::move(vec_assemble_switch);
433 CHKERR set(*bit);
434 CHKERR snes_ctx->mField.problem_basic_method_preProcess(
435 snes_ctx->problemName, *bit);
436 unset(*bit);
437 vec_assemble_switch = boost::move(bit->vecAssembleSwitch);
438 }
439
440 for (auto &lit : snes_ctx->loopsLoadTangent) {
441 lit.second->vecAssembleSwitch = boost::move(vec_assemble_switch);
442 CHKERR set(*lit.second);
443 CHKERR snes_ctx->mField.loop_finite_elements(
444 snes_ctx->problemName, lit.first, *lit.second, nullptr, snes_ctx->bH,
445 cache_ptr);
446 unset(*lit.second);
447 if (snes_ctx->vErify) {
448 // Verify finite elements, check for not a number
449 CHKERR VecAssemblyBegin(f);
450 CHKERR VecAssemblyEnd(f);
451 MPI_Comm comm = PetscObjectComm((PetscObject)f);
452 PetscSynchronizedPrintf(comm, "SNES Verify f FE < %s >\n",
453 lit.first.c_str());
454 const Problem *prb_ptr;
455 CHKERR snes_ctx->mField.get_problem(snes_ctx->problemName, &prb_ptr);
456 CHKERR snes_ctx->mField.getInterface<Tools>()->checkVectorForNotANumber(
457 prb_ptr, ROW, f);
458 }
459
460 vec_assemble_switch = boost::move(lit.second->vecAssembleSwitch);
461 }
462
463 for (auto &bit : snes_ctx->postProcessLoadTangent) {
464 bit->vecAssembleSwitch = boost::move(vec_assemble_switch);
465 CHKERR set(*bit);
466 CHKERR snes_ctx->mField.problem_basic_method_postProcess(
467 snes_ctx->problemName, *bit);
468 unset(*bit);
469 vec_assemble_switch = boost::move(bit->vecAssembleSwitch);
470 }
471
472 if (*(vec_assemble_switch)) {
473 CHKERR VecGhostUpdateBegin(f, ADD_VALUES, SCATTER_REVERSE);
474 CHKERR VecGhostUpdateEnd(f, ADD_VALUES, SCATTER_REVERSE);
475 CHKERR VecAssemblyBegin(f);
476 CHKERR VecAssemblyEnd(f);
477 }
478
479 if (snes_ctx->loadTangentHook) {
480 CHKERR snes_ctx->loadTangentHook(snes, x, f, cache_ptr, ctx);
481 }
482
483 PetscLogEventEnd(snes_ctx->MOFEM_EVENT_SnesLoadTangent, 0, 0, 0, 0);
485}
constexpr double a
@ COL
@ ROW
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
auto bit
set bit
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'l', 3 > l
constexpr double g
@ CTX_KSPNONE
No specific KSP context.
@ CTX_SETFUNCTION
Setting up the linear system function.
static constexpr Switches CtxSetX
Solution vector switch.
static constexpr Switches CtxSetNone
No data switch.
static constexpr Switches CtxSetF
Residual vector switch.
static constexpr Switches CtxSetDX
Solution increment switch.
static constexpr Switches CtxSetTime
Time value switch.
SnesCtx(Interface &m_field, std::string problem_name)
Definition SnesCtx.cpp:125
@ CTX_SNESSETFUNCTION
Setting up nonlinear function evaluation.
@ CTX_SNESNONE
No specific SNES context.

◆ SnesMat

PetscErrorCode SnesMat ( SNES  snes,
Vec  x,
Mat  A,
Mat  B,
void *  ctx 
)
friend

This is MoFEM implementation for the left hand side (tangent matrix) evaluation in SNES solver.

For more information pleas look to PETSc manual, i.e. SNESSetJacobian http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/SNES/SNESSetJacobian.html#SNESSetJacobian

Parameters
snesSNES solver
xSolution vector at current iteration
ATangent matrix
BPreconditioner tangent matrix
ctxPointer to context i.e. SnesCtx
Returns
Error code

Definition at line 487 of file SnesCtx.cpp.

487 {
488 auto *snes_ctx = static_cast<SnesCtx *>(ctx)->snesCtxImpl.get();
490 PetscLogEventBegin(snes_ctx->MOFEM_EVENT_SnesMat, 0, 0, 0, 0);
491
492 auto mat_assemble_switch = boost::movelib::make_unique<bool>(true);
493 auto cache_ptr = boost::make_shared<CacheTuple>();
494 CHKERR snes_ctx->mField.cache_problem_entities(snes_ctx->problemName,
495 cache_ptr);
496 Vec dx;
497 CHKERR SNESGetSolutionUpdate(snes, &dx);
498
499 auto set = [&](auto &fe) {
501 fe.snes = snes;
502 fe.snes_x = x;
503 fe.snes_dx = dx;
504 fe.snes_A = A;
505 fe.snes_B = B;
507 fe.ksp_ctx = KspMethod::CTX_OPERATORS;
510
511 CHKERR SNESGetKSP(snes, &fe.ksp);
512
513 fe.cacheWeakPtr = cache_ptr;
515 };
516
517 auto unset = [&](auto &fe) {
518 fe.snes_ctx = SnesMethod::CTX_SNESNONE;
519 fe.ksp_ctx = KspMethod::CTX_KSPNONE;
520 fe.data_ctx = PetscData::CtxSetNone;
521 };
522
523 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
524 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
525 CHKERR snes_ctx->mField.getInterface<VecManager>()->setLocalGhostVector(
526 snes_ctx->problemName, COL, x, INSERT_VALUES, SCATTER_REVERSE);
527
528 if (*mat_assemble_switch) {
529 if (snes_ctx->zeroPreCondMatrixB)
530 CHKERR MatZeroEntries(B);
531 }
532 for (auto &bit : snes_ctx->preProcessOperator) {
533 bit->matAssembleSwitch = boost::move(mat_assemble_switch);
534 CHKERR set(*bit);
535 CHKERR snes_ctx->mField.problem_basic_method_preProcess(
536 snes_ctx->problemName, *bit);
537 unset(*bit);
538 mat_assemble_switch = boost::move(bit->matAssembleSwitch);
539 }
540
541 for (auto &lit : snes_ctx->loopsOperator) {
542 lit.second->matAssembleSwitch = boost::move(mat_assemble_switch);
543 CHKERR set(*lit.second);
544 CHKERR snes_ctx->mField.loop_finite_elements(
545 snes_ctx->problemName, lit.first, *(lit.second), nullptr, snes_ctx->bH,
546 cache_ptr);
547 unset(*lit.second);
548 mat_assemble_switch = boost::move(lit.second->matAssembleSwitch);
549 }
550
551 for (auto &bit : snes_ctx->postProcessOperator) {
552 bit->matAssembleSwitch = boost::move(mat_assemble_switch);
553 CHKERR set(*bit);
554 CHKERR snes_ctx->mField.problem_basic_method_postProcess(
555 snes_ctx->problemName, *bit);
556 unset(*bit);
557 mat_assemble_switch = boost::move(bit->matAssembleSwitch);
558 }
559
560 if (*mat_assemble_switch) {
561 CHKERR MatAssemblyBegin(B, snes_ctx->typeOfAssembly);
562 CHKERR MatAssemblyEnd(B, snes_ctx->typeOfAssembly);
563 }
564 PetscLogEventEnd(snes_ctx->MOFEM_EVENT_SnesMat, 0, 0, 0, 0);
566}
constexpr AssemblyType A
[Define dimension]
@ CTX_OPERATORS
Setting up linear operators.
static constexpr Switches CtxSetA
Jacobian matrix switch.
static constexpr Switches CtxSetB
Preconditioner matrix switch.
@ CTX_SNESSETJACOBIAN
Setting up Jacobian matrix computation.

◆ SnesMoFEMSetAssemblyType

MoFEMErrorCode SnesMoFEMSetAssemblyType ( SNES  snes,
MatAssemblyType  type 
)
friend

Set assembly type at the end of SnesMat.

Note
Note that tangent matrix need have to have final assembly, you would use flush assembly in special case that you call SnesMat form other function set to SNESSetJacobian
Parameters
snes
typetype of assembly, either MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY
Returns
error code

Definition at line 568 of file SnesCtx.cpp.

568 {
569
570 auto get_snes_ctx = [](SNES snes) {
571 SnesCtx *snes_ctx;
572 CHK_THROW_MESSAGE(SNESGetApplicationContext(snes, &snes_ctx),
573 "Cannot get SNES context");
574 return snes_ctx->snesCtxImpl.get();
575 };
576
578 get_snes_ctx(snes)->typeOfAssembly = type;
580}
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.

◆ SNESMoFEMSetAssmblyType

MoFEMErrorCode SNESMoFEMSetAssmblyType ( SNES  snes,
MatAssemblyType  type 
)
friend

◆ SnesMoFEMSetBehavior

MoFEMErrorCode SnesMoFEMSetBehavior ( SNES  snes,
MoFEMTypes  bh 
)
friend

Set behavior if finite element in sequence does not exist.

Parameters
snes
bhIf set to MF_EXIST check if element exist, default MF_EXIST. Otherwise set MF_ZERO
Returns
error code

Definition at line 582 of file SnesCtx.cpp.

582 {
583
584 auto get_snes_ctx = [](SNES snes) {
585 SnesCtx *snes_ctx;
586 CHK_THROW_MESSAGE(SNESGetApplicationContext(snes, &snes_ctx),
587 "Cannot get SNES context");
588 return snes_ctx->snesCtxImpl.get();
589 };
590
592 get_snes_ctx(snes)->bH = bh;
594}

◆ SnesRhs

PetscErrorCode SnesRhs ( SNES  snes,
Vec  x,
Vec  f,
void *  ctx 
)
friend

This is MoFEM implementation for the right hand side (residual vector) evaluation in SNES solver.

For more information pleas look to PETSc manual, i.e. SNESSetFunction http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/SNES/SNESSetFunction.html

Parameters
snesSNES solver
xSolution vector at current iteration
fThe right hand side vector
ctxPointer to context i.e. SnesCtx
Returns
Error code

Definition at line 223 of file SnesCtx.cpp.

223 {
224 auto *snes_ctx = static_cast<SnesCtx *>(ctx)->snesCtxImpl.get();
226 PetscLogEventBegin(snes_ctx->MOFEM_EVENT_SnesRhs, 0, 0, 0, 0);
227 Vec dx;
228 CHKERR SNESGetSolutionUpdate(snes, &dx);
229 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
230 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
231 if (snes_ctx->vErify) {
232 // Verify finite elements, check for not a number
233 CHKERR VecAssemblyBegin(f);
234 CHKERR VecAssemblyEnd(f);
235 MPI_Comm comm = PetscObjectComm((PetscObject)f);
236 PetscSynchronizedPrintf(comm, "SNES Verify x\n");
237 const Problem *prb_ptr;
238 CHKERR snes_ctx->mField.get_problem(snes_ctx->problemName, &prb_ptr);
239 CHKERR snes_ctx->mField.getInterface<Tools>()->checkVectorForNotANumber(
240 prb_ptr, COL, x);
241 }
242 CHKERR snes_ctx->mField.getInterface<VecManager>()->setLocalGhostVector(
243 snes_ctx->problemName, COL, x, INSERT_VALUES, SCATTER_REVERSE);
244
245 auto zero_ghost_vec = [](Vec g) {
247 Vec l;
248 CHKERR VecGhostGetLocalForm(g, &l);
249 double *a;
250 CHKERR VecGetArray(l, &a);
251 int s;
252 CHKERR VecGetLocalSize(l, &s);
253 for (int i = 0; i != s; ++i)
254 a[i] = 0;
255 CHKERR VecRestoreArray(l, &a);
256 CHKERR VecGhostRestoreLocalForm(g, &l);
258 };
259 CHKERR zero_ghost_vec(f);
260
261 auto vec_assemble_switch = boost::movelib::make_unique<bool>(true);
262 auto cache_ptr = boost::make_shared<CacheTuple>();
263 CHKERR snes_ctx->mField.cache_problem_entities(snes_ctx->problemName,
264 cache_ptr);
265
266 auto set = [&](auto &fe) {
268 fe.snes = snes;
269 fe.snes_x = x;
270 fe.snes_dx = dx;
271 fe.snes_f = f;
273 fe.ksp_ctx = KspMethod::CTX_SETFUNCTION;
275
276 CHKERR SNESGetKSP(snes, &fe.ksp);
277
278 // If SNES is of type SNESNEWTONAL then get load parameter, will act as a
279 // psuo time
280#if PETSC_VERSION_GE(3, 22, 0)
281 PetscBool same;
282 CHKERR PetscObjectTypeCompare((PetscObject)snes, SNESNEWTONAL, &same);
283 if (same) {
284 CHKERR SNESNewtonALGetLoadParameter(snes, &fe.ts_t);
285 fe.data_ctx |= PetscData::CtxSetTime;
286 }
287#endif
288
289 fe.cacheWeakPtr = cache_ptr;
291 };
292
293 auto unset = [&](auto &fe) {
294 fe.snes_ctx = SnesMethod::CTX_SNESNONE;
295 fe.ksp_ctx = KspMethod::CTX_KSPNONE;
296 fe.data_ctx = PetscData::CtxSetNone;
297 };
298
299 for (auto &bit : snes_ctx->preProcessRhs) {
300 bit->vecAssembleSwitch = boost::move(vec_assemble_switch);
301 CHKERR set(*bit);
302 CHKERR snes_ctx->mField.problem_basic_method_preProcess(
303 snes_ctx->problemName, *bit);
304 unset(*bit);
305 vec_assemble_switch = boost::move(bit->vecAssembleSwitch);
306 }
307
308 for (auto &lit : snes_ctx->loopsRhs) {
309 lit.second->vecAssembleSwitch = boost::move(vec_assemble_switch);
310 CHKERR set(*lit.second);
311 CHKERR snes_ctx->mField.loop_finite_elements(
312 snes_ctx->problemName, lit.first, *lit.second, nullptr, snes_ctx->bH,
313 cache_ptr);
314 unset(*lit.second);
315 if (snes_ctx->vErify) {
316 // Verify finite elements, check for not a number
317 CHKERR VecAssemblyBegin(f);
318 CHKERR VecAssemblyEnd(f);
319 MPI_Comm comm = PetscObjectComm((PetscObject)f);
320 PetscSynchronizedPrintf(comm, "SNES Verify f FE < %s >\n",
321 lit.first.c_str());
322 const Problem *prb_ptr;
323 CHKERR snes_ctx->mField.get_problem(snes_ctx->problemName, &prb_ptr);
324 CHKERR snes_ctx->mField.getInterface<Tools>()->checkVectorForNotANumber(
325 prb_ptr, ROW, f);
326 }
327
328 vec_assemble_switch = boost::move(lit.second->vecAssembleSwitch);
329 }
330
331 for (auto &bit : snes_ctx->postProcessRhs) {
332 bit->vecAssembleSwitch = boost::move(vec_assemble_switch);
333 CHKERR set(*bit);
334 CHKERR snes_ctx->mField.problem_basic_method_postProcess(
335 snes_ctx->problemName, *bit);
336 unset(*bit);
337 vec_assemble_switch = boost::move(bit->vecAssembleSwitch);
338 }
339
340 if (*(vec_assemble_switch)) {
341 CHKERR VecGhostUpdateBegin(f, ADD_VALUES, SCATTER_REVERSE);
342 CHKERR VecGhostUpdateEnd(f, ADD_VALUES, SCATTER_REVERSE);
343 CHKERR VecAssemblyBegin(f);
344 CHKERR VecAssemblyEnd(f);
345 }
346
347 if (snes_ctx->rhsHook) {
348 CHKERR snes_ctx->rhsHook(snes, x, f, cache_ptr, ctx);
349 }
350
351 PetscLogEventEnd(snes_ctx->MOFEM_EVENT_SnesRhs, 0, 0, 0, 0);
353}

Member Data Documentation

◆ snesCtxImpl

boost::movelib::unique_ptr<SnesCtxImpl> MoFEM::SnesCtx::snesCtxImpl
protected

Definition at line 150 of file SnesCtx.hpp.


The documentation for this struct was generated from the following files: