54 friend PetscErrorCode
SnesRhs(SNES snes, Vec x, Vec f,
void *ctx);
56 friend PetscErrorCode
SnesMat(SNES snes, Vec x, Mat
A, Mat
B,
void *ctx);
59 MatAssemblyType type);
63 MatAssemblyType type);
129 m_field, problem_name)) {}
186 : mField(m_field), moab(m_field.get_moab()), problemName(problem_name) {
191 auto core_log = logging::core::get();
215 loopsOperator.clear();
217 preProcessOperator.clear();
218 postProcessOperator.clear();
219 preProcessRhs.clear();
220 postProcessRhs.clear();
221 loopsLoadTangent.clear();
222 preProcessLoadTangent.clear();
223 postProcessLoadTangent.clear();
227PetscErrorCode
SnesRhs(SNES snes, Vec x, Vec f,
void *ctx) {
230 PetscLogEventBegin(snes_ctx->MOFEM_EVENT_SnesRhs, 0, 0, 0, 0);
232 CHKERR SNESGetSolutionUpdate(snes, &dx);
233 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
234 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
235 if (snes_ctx->vErify) {
237 CHKERR VecAssemblyBegin(f);
239 MPI_Comm comm = PetscObjectComm((PetscObject)f);
240 PetscSynchronizedPrintf(comm,
"SNES Verify x\n");
242 CHKERR snes_ctx->mField.get_problem(snes_ctx->problemName, &prb_ptr);
243 CHKERR snes_ctx->mField.getInterface<
Tools>()->checkVectorForNotANumber(
247 snes_ctx->problemName,
COL, x, INSERT_VALUES, SCATTER_REVERSE);
249 auto zero_ghost_vec = [](Vec
g) {
257 for (
int i = 0;
i != s; ++
i)
260 CHKERR VecGhostRestoreLocalForm(
g, &
l);
265 auto vec_assemble_switch = boost::movelib::make_unique<bool>(
true);
266 auto cache_ptr = boost::make_shared<CacheTuple>();
267 CHKERR snes_ctx->mField.cache_problem_entities(snes_ctx->problemName,
270 auto set = [&](
auto &fe) {
280 CHKERR SNESGetKSP(snes, &fe.ksp);
284#if PETSC_VERSION_GE(3, 22, 0)
286 CHKERR PetscObjectTypeCompare((PetscObject)snes, SNESNEWTONAL, &same);
288 CHKERR SNESNewtonALGetLoadParameter(snes, &fe.ts_t);
293 fe.cacheWeakPtr = cache_ptr;
297 auto unset = [&](
auto &fe) {
303 for (
auto &
bit : snes_ctx->preProcessRhs) {
304 bit->vecAssembleSwitch = boost::move(vec_assemble_switch);
306 CHKERR snes_ctx->mField.problem_basic_method_preProcess(
307 snes_ctx->problemName, *
bit);
309 vec_assemble_switch = boost::move(
bit->vecAssembleSwitch);
312 for (
auto &lit : snes_ctx->loopsRhs) {
313 lit.second->vecAssembleSwitch = boost::move(vec_assemble_switch);
315 CHKERR snes_ctx->mField.loop_finite_elements(
316 snes_ctx->problemName, lit.first, *lit.second,
nullptr, snes_ctx->bH,
319 if (snes_ctx->vErify) {
321 CHKERR VecAssemblyBegin(f);
323 MPI_Comm comm = PetscObjectComm((PetscObject)f);
324 PetscSynchronizedPrintf(comm,
"SNES Verify f FE < %s >\n",
327 CHKERR snes_ctx->mField.get_problem(snes_ctx->problemName, &prb_ptr);
328 CHKERR snes_ctx->mField.getInterface<
Tools>()->checkVectorForNotANumber(
332 vec_assemble_switch = boost::move(lit.second->vecAssembleSwitch);
335 for (
auto &
bit : snes_ctx->postProcessRhs) {
336 bit->vecAssembleSwitch = boost::move(vec_assemble_switch);
338 CHKERR snes_ctx->mField.problem_basic_method_postProcess(
339 snes_ctx->problemName, *
bit);
341 vec_assemble_switch = boost::move(
bit->vecAssembleSwitch);
344 if (*(vec_assemble_switch)) {
345 CHKERR VecGhostUpdateBegin(f, ADD_VALUES, SCATTER_REVERSE);
346 CHKERR VecGhostUpdateEnd(f, ADD_VALUES, SCATTER_REVERSE);
347 CHKERR VecAssemblyBegin(f);
351 if (snes_ctx->rhsHook) {
352 CHKERR snes_ctx->rhsHook(snes, x, f, cache_ptr, ctx);
355 PetscLogEventEnd(snes_ctx->MOFEM_EVENT_SnesRhs, 0, 0, 0, 0);
362 PetscLogEventBegin(snes_ctx->MOFEM_EVENT_SnesLoadTangent, 0, 0, 0, 0);
364 CHKERR SNESGetSolutionUpdate(snes, &dx);
365 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
366 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
367 if (snes_ctx->vErify) {
369 CHKERR VecAssemblyBegin(f);
371 MPI_Comm comm = PetscObjectComm((PetscObject)f);
372 PetscSynchronizedPrintf(comm,
"SNES Verify x\n");
374 CHKERR snes_ctx->mField.get_problem(snes_ctx->problemName, &prb_ptr);
375 CHKERR snes_ctx->mField.getInterface<
Tools>()->checkVectorForNotANumber(
379 snes_ctx->problemName,
COL, x, INSERT_VALUES, SCATTER_REVERSE);
381 auto zero_ghost_vec = [](Vec
g) {
389 for (
int i = 0;
i != s; ++
i)
392 CHKERR VecGhostRestoreLocalForm(
g, &
l);
397 auto vec_assemble_switch = boost::movelib::make_unique<bool>(
true);
398 auto cache_ptr = boost::make_shared<CacheTuple>();
399 CHKERR snes_ctx->mField.cache_problem_entities(snes_ctx->problemName,
402 auto set = [&](
auto &fe) {
412 CHKERR SNESGetKSP(snes, &fe.ksp);
416#if PETSC_VERSION_GE(3, 22, 0)
418 CHKERR PetscObjectTypeCompare((PetscObject)snes, SNESNEWTONAL, &same);
420 CHKERR SNESNewtonALGetLoadParameter(snes, &fe.ts_t);
425 fe.cacheWeakPtr = cache_ptr;
429 auto unset = [&](
auto &fe) {
435 for (
auto &
bit : snes_ctx->preProcessLoadTangent) {
436 bit->vecAssembleSwitch = boost::move(vec_assemble_switch);
438 CHKERR snes_ctx->mField.problem_basic_method_preProcess(
439 snes_ctx->problemName, *
bit);
441 vec_assemble_switch = boost::move(
bit->vecAssembleSwitch);
444 for (
auto &lit : snes_ctx->loopsLoadTangent) {
445 lit.second->vecAssembleSwitch = boost::move(vec_assemble_switch);
447 CHKERR snes_ctx->mField.loop_finite_elements(
448 snes_ctx->problemName, lit.first, *lit.second,
nullptr, snes_ctx->bH,
451 if (snes_ctx->vErify) {
453 CHKERR VecAssemblyBegin(f);
455 MPI_Comm comm = PetscObjectComm((PetscObject)f);
456 PetscSynchronizedPrintf(comm,
"SNES Verify f FE < %s >\n",
459 CHKERR snes_ctx->mField.get_problem(snes_ctx->problemName, &prb_ptr);
460 CHKERR snes_ctx->mField.getInterface<
Tools>()->checkVectorForNotANumber(
464 vec_assemble_switch = boost::move(lit.second->vecAssembleSwitch);
467 for (
auto &
bit : snes_ctx->postProcessLoadTangent) {
468 bit->vecAssembleSwitch = boost::move(vec_assemble_switch);
470 CHKERR snes_ctx->mField.problem_basic_method_postProcess(
471 snes_ctx->problemName, *
bit);
473 vec_assemble_switch = boost::move(
bit->vecAssembleSwitch);
476 if (*(vec_assemble_switch)) {
477 CHKERR VecGhostUpdateBegin(f, ADD_VALUES, SCATTER_REVERSE);
478 CHKERR VecGhostUpdateEnd(f, ADD_VALUES, SCATTER_REVERSE);
479 CHKERR VecAssemblyBegin(f);
483 if (snes_ctx->loadTangentHook) {
484 CHKERR snes_ctx->loadTangentHook(snes, x, f, cache_ptr, ctx);
487 PetscLogEventEnd(snes_ctx->MOFEM_EVENT_SnesLoadTangent, 0, 0, 0, 0);
491PetscErrorCode
SnesMat(SNES snes, Vec x, Mat
A, Mat
B,
void *ctx) {
494 PetscLogEventBegin(snes_ctx->MOFEM_EVENT_SnesMat, 0, 0, 0, 0);
496 auto mat_assemble_switch = boost::movelib::make_unique<bool>(
true);
497 auto cache_ptr = boost::make_shared<CacheTuple>();
498 CHKERR snes_ctx->mField.cache_problem_entities(snes_ctx->problemName,
501 CHKERR SNESGetSolutionUpdate(snes, &dx);
503 auto set = [&](
auto &fe) {
515 CHKERR SNESGetKSP(snes, &fe.ksp);
517 fe.cacheWeakPtr = cache_ptr;
521 auto unset = [&](
auto &fe) {
527 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
528 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
530 snes_ctx->problemName,
COL, x, INSERT_VALUES, SCATTER_REVERSE);
532 if (*mat_assemble_switch) {
533 if (snes_ctx->zeroPreCondMatrixB)
536 for (
auto &
bit : snes_ctx->preProcessOperator) {
537 bit->matAssembleSwitch = boost::move(mat_assemble_switch);
539 CHKERR snes_ctx->mField.problem_basic_method_preProcess(
540 snes_ctx->problemName, *
bit);
542 mat_assemble_switch = boost::move(
bit->matAssembleSwitch);
545 for (
auto &lit : snes_ctx->loopsOperator) {
546 lit.second->matAssembleSwitch = boost::move(mat_assemble_switch);
548 CHKERR snes_ctx->mField.loop_finite_elements(
549 snes_ctx->problemName, lit.first, *(lit.second),
nullptr, snes_ctx->bH,
552 mat_assemble_switch = boost::move(lit.second->matAssembleSwitch);
555 for (
auto &
bit : snes_ctx->postProcessOperator) {
556 bit->matAssembleSwitch = boost::move(mat_assemble_switch);
558 CHKERR snes_ctx->mField.problem_basic_method_postProcess(
559 snes_ctx->problemName, *
bit);
561 mat_assemble_switch = boost::move(
bit->matAssembleSwitch);
564 if (*mat_assemble_switch) {
565 CHKERR MatAssemblyBegin(
B, snes_ctx->typeOfAssembly);
566 CHKERR MatAssemblyEnd(
B, snes_ctx->typeOfAssembly);
568 PetscLogEventEnd(snes_ctx->MOFEM_EVENT_SnesMat, 0, 0, 0, 0);
574 auto get_snes_ctx = [](SNES snes) {
577 "Cannot get SNES context");
582 get_snes_ctx(snes)->typeOfAssembly = type;
588 auto get_snes_ctx = [](SNES snes) {
591 "Cannot get SNES context");
596 get_snes_ctx(snes)->bH = bh;
604 auto &m_field = snes_ctx->mField;
605 auto problem_ptr = m_field.get_problem(snes_ctx->problemName);
606 auto fields_ptr = m_field.get_fields();
607 auto dofs = problem_ptr->numeredRowDofsPtr;
609 std::vector<double> lnorms(fields_ptr->size(), 0),
610 norms(fields_ptr->size(), 0);
613 CHKERR SNESGetFunction(snes, &res, NULL, NULL);
616 CHKERR VecGetArrayRead(res, &r);
619 for (
auto fi : *fields_ptr) {
622 const auto hi = dofs->get<
Unique_mi_tag>().upper_bound(hi_uid);
623 for (
auto lo = dofs->get<
Unique_mi_tag>().lower_bound(lo_uid); lo != hi;
625 const DofIdx loc_idx = (*lo)->getPetscLocalDofIdx();
626 if (loc_idx >= 0 && loc_idx < problem_ptr->nbLocDofsRow) {
627 lnorms[f] += PetscRealPart(PetscSqr(r[loc_idx]));
633 CHKERR VecRestoreArrayRead(res, &r);
635 MPIU_Allreduce(&*lnorms.begin(), &*norms.begin(), lnorms.size(), MPIU_REAL,
636 MPIU_SUM, PetscObjectComm((PetscObject)snes));
640 << its <<
" Function norm " << boost::format(
"%14.12e") % (
double)fgnorm
643 for (
auto fi : *fields_ptr) {
645 << its <<
"\t Field norm "
646 << boost::format(
"%14.12e") % (
double)PetscSqrtReal(norms[f]) <<
" "
650 MOFEM_LOG(
"SNES_WORLD", Sev::inform) << its <<
"]";
660 auto &m_field = snes_ctx->mField;
661 auto problem_ptr = m_field.get_problem(snes_ctx->problemName);
662 auto fields_ptr = m_field.get_fields();
663 auto dofs = problem_ptr->numeredRowDofsPtr;
665 std::vector<double> lnorms(3 * fields_ptr->size(), 0),
666 norms(3 * fields_ptr->size(), 0);
670 CHKERR SNESGetSolution(snes, &x_update);
672 CHKERR SNESGetSolutionUpdate(snes, &x_update);
673 CHKERR SNESGetFunction(snes, &res, PETSC_NULLPTR, PETSC_NULLPTR);
677 CHKERR VecGetArrayRead(res, &r);
678 CHKERR VecGetArrayRead(x_update, &x);
682 for (
auto fi : *fields_ptr) {
685 const auto hi = dofs->get<
Unique_mi_tag>().upper_bound(hi_uid);
686 for (
auto lo = dofs->get<
Unique_mi_tag>().lower_bound(lo_uid); lo != hi;
688 const DofIdx loc_idx = (*lo)->getPetscLocalDofIdx();
689 if (loc_idx >= 0 && loc_idx < problem_ptr->nbLocDofsRow) {
690 lnorms[3 * f] += std::abs(x[loc_idx] * r[loc_idx]);
691 lnorms[3 * f + 1] += r[loc_idx] * r[loc_idx];
692 lnorms[3 * f + 2] += x[loc_idx] * x[loc_idx];
698 CHKERR VecRestoreArrayRead(res, &r);
699 CHKERR VecRestoreArrayRead(x_update, &x);
701 MPIU_Allreduce(&*lnorms.begin(), &*norms.begin(), lnorms.size(), MPIU_REAL,
702 MPIU_SUM, PetscObjectComm((PetscObject)snes));
704 double energy_norm = 0, residual_norm = 0, increment_norm = 0;
705 for (
int f = 0; f != fields_ptr->size(); ++f) {
706 energy_norm += norms[3 * f];
707 residual_norm += norms[3 * f + 1];
708 increment_norm += norms[3 * f + 2];
710 energy_norm = std::sqrt(energy_norm);
711 residual_norm = std::sqrt(residual_norm);
712 increment_norm = std::sqrt(increment_norm);
716 << its <<
" Function norm Energy/Residual/Increment"
717 << boost::format(
" %14.12e ") % energy_norm
718 << boost::format(
" %14.12e ") % residual_norm
719 << boost::format(
" %14.12e ") % increment_norm <<
"[";
721 for (
auto fi : *fields_ptr) {
723 << its <<
"\t Energy/Residual/Increment norm "
724 << boost::format(
"%14.12e") % std::sqrt(norms[3 * f]) <<
"\t"
725 << boost::format(
"%14.12e") % std::sqrt(norms[3 * f + 1]) <<
" "
726 << boost::format(
"%14.12e") % std::sqrt(norms[3 * f + 2]) <<
"\t "
730 MOFEM_LOG(
"SNES_WORLD", Sev::inform) << its <<
" ]";
MoFEMTypes
Those types control how functions respond on arguments, f.e. error handling.
#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 ...
#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 ...
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.
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'l', 3 > l
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
std::deque< BasicMethodPtr > BasicMethodsSequence
std::deque< PairNameFEMethodPtr > FEMethodsSequence
Deprecated interface functions.
static UId getHiBitNumberUId(const FieldBitNumber bit_number)
static UId getLoBitNumberUId(const FieldBitNumber bit_number)
@ CTX_KSPNONE
No specific KSP context.
@ CTX_SETFUNCTION
Setting up the linear system function.
@ CTX_OPERATORS
Setting up linear operators.
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.
static bool checkIfChannelExist(const std::string channel)
Check if channel exist.
static constexpr Switches CtxSetA
Jacobian matrix switch.
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 CtxSetB
Preconditioner matrix switch.
static constexpr Switches CtxSetTime
Time value switch.
keeps basic data about problem
BasicMethodsSequence preProcessLoadTangent
FEMethodsSequence & getComputeRhs()
MatAssemblyType typeOfAssembly
type of assembly at the end
friend 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 contro...
FEMethodsSequence & getLoadTangent()
BasicMethodsSequence & getPreProcLoadTangent()
friend MoFEMErrorCode SnesMoFEMSetBehavior(SNES snes, MoFEMTypes bh)
Set behavior if finite element in sequence does not exist.
PetscLogEvent MOFEM_EVENT_SnesMat
Log events to assemble tangent matrix.
BasicMethodsSequence preProcessOperator
friend MoFEMErrorCode MoFEMSNESMonitorEnergy(SNES snes, PetscInt its, PetscReal fgnorm, SnesCtx *snes_ctx)
Sens monitor printing residual field by field.
FEMethodsSequence loopsRhs
BasicMethodsSequence & getPostProcComputeRhs()
moab::Interface & moab
moab Interface
BasicMethodsSequence postProcessLoadTangent
MoFEM::BasicMethodsSequence BasicMethodsSequence
std::string problemName
problem name
friend MoFEMErrorCode SNESMoFEMSetAssmblyType(SNES snes, MatAssemblyType type)
virtual ~SnesCtxImpl()=default
MoFEMErrorCode copyLoops(const SnesCtxImpl &snes_ctx)
friend 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.
friend 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.
HookFunction & getRhsHook()
FEMethodsSequence loopsOperator
HookFunction loadTangentHook
MoFEM::Interface & getMField()
SnesCtx::HookFunction HookFunction
BasicMethodsSequence & getPreProcComputeRhs()
FEMethodsSequence loopsLoadTangent
FEMethodsSequence & getSetOperators()
MoFEM::Interface & mField
database Interface
BasicMethodsSequence postProcessRhs
Sequence of methods run after residual is assembled.
BasicMethodsSequence & getPostProcSetOperators()
HookFunction & getLoadTangentHook()
MoFEMTypes bH
If set to MF_EXIST check if element exist, default MF_EXIST.
PetscLogEvent MOFEM_EVENT_SnesLoadTangent
SnesCtxImpl(Interface &m_field, std::string problem_name)
BasicMethodsSequence preProcessRhs
Sequence of methods run before residual is assembled.
MoFEMErrorCode clearLoops()
BasicMethodsSequence & getPostProcLoadTangent()
BasicMethodsSequence postProcessOperator
MoFEM::FEMethodsSequence FEMethodsSequence
PetscLogEvent MOFEM_EVENT_SnesRhs
Log events to assemble residual.
friend MoFEMErrorCode MoFEMSNESMonitorFields(SNES snes, PetscInt its, PetscReal fgnorm, SnesCtx *snes_ctx)
Sens monitor printing residual field by field.
bool vErify
If true verify vector.
BasicMethodsSequence & getPreProcSetOperators()
friend MoFEMErrorCode SnesMoFEMSetAssemblyType(SNES snes, MatAssemblyType type)
Set assembly type at the end of SnesMat.
Interface for nonlinear (SNES) solver.
MoFEM::BasicMethodsSequence BasicMethodsSequence
friend 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 contro...
FEMethodsSequence & getSetOperators()
friend MoFEMErrorCode SnesMoFEMSetBehavior(SNES snes, MoFEMTypes bh)
Set behavior if finite element in sequence does not exist.
friend MoFEMErrorCode MoFEMSNESMonitorEnergy(SNES snes, PetscInt its, PetscReal fgnorm, SnesCtx *snes_ctx)
Sens monitor printing residual field by field.
SnesCtx(Interface &m_field, std::string problem_name)
BasicMethodsSequence & getPreProcLoadTangent()
Get the BasicMethod sequence for preprocessing of FunctionFn.
BasicMethodsSequence & getPreProcSetOperators()
MoFEM::Interface & getMField()
Get mField reference.
MoFEM::FEMethodsSequence FEMethodsSequence
BasicMethodsSequence & getPostProcLoadTangent()
Get the BasicMethod sequence for postprocessing of FunctionFn.
MoFEMErrorCode copyLoops(const SnesCtx &snes_ctx)
Copy sequences from other SNES context.
boost::function< MoFEMErrorCode(SNES snes, Vec x, Vec F, boost::shared_ptr< CacheTuple > cache_ptr, void *ctx)> HookFunction
friend 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.
friend 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.
BasicMethodsSequence & getPostProcComputeRhs()
HookFunction & getLoadTangentHook()
Get the Load Tangent Hook function.
BasicMethodsSequence & getPostProcSetOperators()
boost::movelib::unique_ptr< SnesCtxImpl > snesCtxImpl
BasicMethodsSequence & getPreProcComputeRhs()
FEMethodsSequence & getLoadTangent()
Get the finite element pipeline for FunctionFn, that calculate tangent of function load for arc lengt...
FEMethodsSequence & getComputeRhs()
HookFunction & getRhsHook()
Get the Right Hand Side Hook function.
friend MoFEMErrorCode MoFEMSNESMonitorFields(SNES snes, PetscInt its, PetscReal fgnorm, SnesCtx *snes_ctx)
Sens monitor printing residual field by field.
MoFEMErrorCode clearLoops()
Clear loops.
friend MoFEMErrorCode SnesMoFEMSetAssemblyType(SNES snes, MatAssemblyType type)
Set assembly type at the end of SnesMat.
@ CTX_SNESSETJACOBIAN
Setting up Jacobian matrix computation.
@ CTX_SNESSETFUNCTION
Setting up nonlinear function evaluation.
@ CTX_SNESNONE
No specific SNES context.
Vector manager is used to create vectors \mofem_vectors.