52 friend PetscErrorCode
SnesRhs(SNES snes, Vec x, Vec f,
void *ctx);
54 friend PetscErrorCode
SnesMat(SNES snes, Vec x, Mat
A, Mat
B,
void *ctx);
57 MatAssemblyType type);
61 MatAssemblyType type);
127 m_field, problem_name)) {}
182 : mField(m_field), moab(m_field.get_moab()), problemName(problem_name) {
187 auto core_log = logging::core::get();
211 loopsOperator.clear();
213 preProcessOperator.clear();
214 postProcessOperator.clear();
215 preProcessRhs.clear();
216 postProcessRhs.clear();
217 loopsLoadTangent.clear();
218 preProcessLoadTangent.clear();
219 postProcessLoadTangent.clear();
223PetscErrorCode
SnesRhs(SNES snes, Vec x, Vec f,
void *ctx) {
226 PetscLogEventBegin(snes_ctx->MOFEM_EVENT_SnesRhs, 0, 0, 0, 0);
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) {
233 CHKERR VecAssemblyBegin(f);
235 MPI_Comm comm = PetscObjectComm((PetscObject)f);
236 PetscSynchronizedPrintf(comm,
"SNES Verify x\n");
238 CHKERR snes_ctx->mField.get_problem(snes_ctx->problemName, &prb_ptr);
239 CHKERR snes_ctx->mField.getInterface<
Tools>()->checkVectorForNotANumber(
243 snes_ctx->problemName,
COL, x, INSERT_VALUES, SCATTER_REVERSE);
245 auto zero_ghost_vec = [](Vec
g) {
253 for (
int i = 0;
i != s; ++
i)
256 CHKERR VecGhostRestoreLocalForm(
g, &
l);
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,
266 auto set = [&](
auto &fe) {
276 CHKERR SNESGetKSP(snes, &fe.ksp);
280#if PETSC_VERSION_GE(3, 22, 0)
282 CHKERR PetscObjectTypeCompare((PetscObject)snes, SNESNEWTONAL, &same);
284 CHKERR SNESNewtonALGetLoadParameter(snes, &fe.ts_t);
289 fe.cacheWeakPtr = cache_ptr;
293 auto unset = [&](
auto &fe) {
299 for (
auto &
bit : snes_ctx->preProcessRhs) {
300 bit->vecAssembleSwitch = boost::move(vec_assemble_switch);
302 CHKERR snes_ctx->mField.problem_basic_method_preProcess(
303 snes_ctx->problemName, *
bit);
305 vec_assemble_switch = boost::move(
bit->vecAssembleSwitch);
308 for (
auto &lit : snes_ctx->loopsRhs) {
309 lit.second->vecAssembleSwitch = boost::move(vec_assemble_switch);
311 CHKERR snes_ctx->mField.loop_finite_elements(
312 snes_ctx->problemName, lit.first, *lit.second,
nullptr, snes_ctx->bH,
315 if (snes_ctx->vErify) {
317 CHKERR VecAssemblyBegin(f);
319 MPI_Comm comm = PetscObjectComm((PetscObject)f);
320 PetscSynchronizedPrintf(comm,
"SNES Verify f FE < %s >\n",
323 CHKERR snes_ctx->mField.get_problem(snes_ctx->problemName, &prb_ptr);
324 CHKERR snes_ctx->mField.getInterface<
Tools>()->checkVectorForNotANumber(
328 vec_assemble_switch = boost::move(lit.second->vecAssembleSwitch);
331 for (
auto &
bit : snes_ctx->postProcessRhs) {
332 bit->vecAssembleSwitch = boost::move(vec_assemble_switch);
334 CHKERR snes_ctx->mField.problem_basic_method_postProcess(
335 snes_ctx->problemName, *
bit);
337 vec_assemble_switch = boost::move(
bit->vecAssembleSwitch);
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);
347 if (snes_ctx->rhsHook) {
348 CHKERR snes_ctx->rhsHook(snes, x, f, cache_ptr, ctx);
351 PetscLogEventEnd(snes_ctx->MOFEM_EVENT_SnesRhs, 0, 0, 0, 0);
358 PetscLogEventBegin(snes_ctx->MOFEM_EVENT_SnesLoadTangent, 0, 0, 0, 0);
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) {
365 CHKERR VecAssemblyBegin(f);
367 MPI_Comm comm = PetscObjectComm((PetscObject)f);
368 PetscSynchronizedPrintf(comm,
"SNES Verify x\n");
370 CHKERR snes_ctx->mField.get_problem(snes_ctx->problemName, &prb_ptr);
371 CHKERR snes_ctx->mField.getInterface<
Tools>()->checkVectorForNotANumber(
375 snes_ctx->problemName,
COL, x, INSERT_VALUES, SCATTER_REVERSE);
377 auto zero_ghost_vec = [](Vec
g) {
385 for (
int i = 0;
i != s; ++
i)
388 CHKERR VecGhostRestoreLocalForm(
g, &
l);
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,
398 auto set = [&](
auto &fe) {
408 CHKERR SNESGetKSP(snes, &fe.ksp);
412#if PETSC_VERSION_GE(3, 22, 0)
414 CHKERR PetscObjectTypeCompare((PetscObject)snes, SNESNEWTONAL, &same);
416 CHKERR SNESNewtonALGetLoadParameter(snes, &fe.ts_t);
421 fe.cacheWeakPtr = cache_ptr;
425 auto unset = [&](
auto &fe) {
431 for (
auto &
bit : snes_ctx->preProcessLoadTangent) {
432 bit->vecAssembleSwitch = boost::move(vec_assemble_switch);
434 CHKERR snes_ctx->mField.problem_basic_method_preProcess(
435 snes_ctx->problemName, *
bit);
437 vec_assemble_switch = boost::move(
bit->vecAssembleSwitch);
440 for (
auto &lit : snes_ctx->loopsLoadTangent) {
441 lit.second->vecAssembleSwitch = boost::move(vec_assemble_switch);
443 CHKERR snes_ctx->mField.loop_finite_elements(
444 snes_ctx->problemName, lit.first, *lit.second,
nullptr, snes_ctx->bH,
447 if (snes_ctx->vErify) {
449 CHKERR VecAssemblyBegin(f);
451 MPI_Comm comm = PetscObjectComm((PetscObject)f);
452 PetscSynchronizedPrintf(comm,
"SNES Verify f FE < %s >\n",
455 CHKERR snes_ctx->mField.get_problem(snes_ctx->problemName, &prb_ptr);
456 CHKERR snes_ctx->mField.getInterface<
Tools>()->checkVectorForNotANumber(
460 vec_assemble_switch = boost::move(lit.second->vecAssembleSwitch);
463 for (
auto &
bit : snes_ctx->postProcessLoadTangent) {
464 bit->vecAssembleSwitch = boost::move(vec_assemble_switch);
466 CHKERR snes_ctx->mField.problem_basic_method_postProcess(
467 snes_ctx->problemName, *
bit);
469 vec_assemble_switch = boost::move(
bit->vecAssembleSwitch);
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);
479 if (snes_ctx->loadTangentHook) {
480 CHKERR snes_ctx->loadTangentHook(snes, x, f, cache_ptr, ctx);
483 PetscLogEventEnd(snes_ctx->MOFEM_EVENT_SnesLoadTangent, 0, 0, 0, 0);
487PetscErrorCode
SnesMat(SNES snes, Vec x, Mat
A, Mat
B,
void *ctx) {
490 PetscLogEventBegin(snes_ctx->MOFEM_EVENT_SnesMat, 0, 0, 0, 0);
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,
497 CHKERR SNESGetSolutionUpdate(snes, &dx);
499 auto set = [&](
auto &fe) {
511 CHKERR SNESGetKSP(snes, &fe.ksp);
513 fe.cacheWeakPtr = cache_ptr;
517 auto unset = [&](
auto &fe) {
523 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
524 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
526 snes_ctx->problemName,
COL, x, INSERT_VALUES, SCATTER_REVERSE);
528 if (*mat_assemble_switch) {
529 if (snes_ctx->zeroPreCondMatrixB)
532 for (
auto &
bit : snes_ctx->preProcessOperator) {
533 bit->matAssembleSwitch = boost::move(mat_assemble_switch);
535 CHKERR snes_ctx->mField.problem_basic_method_preProcess(
536 snes_ctx->problemName, *
bit);
538 mat_assemble_switch = boost::move(
bit->matAssembleSwitch);
541 for (
auto &lit : snes_ctx->loopsOperator) {
542 lit.second->matAssembleSwitch = boost::move(mat_assemble_switch);
544 CHKERR snes_ctx->mField.loop_finite_elements(
545 snes_ctx->problemName, lit.first, *(lit.second),
nullptr, snes_ctx->bH,
548 mat_assemble_switch = boost::move(lit.second->matAssembleSwitch);
551 for (
auto &
bit : snes_ctx->postProcessOperator) {
552 bit->matAssembleSwitch = boost::move(mat_assemble_switch);
554 CHKERR snes_ctx->mField.problem_basic_method_postProcess(
555 snes_ctx->problemName, *
bit);
557 mat_assemble_switch = boost::move(
bit->matAssembleSwitch);
560 if (*mat_assemble_switch) {
561 CHKERR MatAssemblyBegin(
B, snes_ctx->typeOfAssembly);
562 CHKERR MatAssemblyEnd(
B, snes_ctx->typeOfAssembly);
564 PetscLogEventEnd(snes_ctx->MOFEM_EVENT_SnesMat, 0, 0, 0, 0);
570 auto get_snes_ctx = [](SNES snes) {
573 "Cannot get SNES context");
578 get_snes_ctx(snes)->typeOfAssembly = type;
584 auto get_snes_ctx = [](SNES snes) {
587 "Cannot get SNES context");
592 get_snes_ctx(snes)->bH = bh;
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;
605 std::vector<double> lnorms(fields_ptr->size(), 0),
606 norms(fields_ptr->size(), 0);
609 CHKERR SNESGetFunction(snes, &res, NULL, NULL);
612 CHKERR VecGetArrayRead(res, &r);
615 for (
auto fi : *fields_ptr) {
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;
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]));
629 CHKERR VecRestoreArrayRead(res, &r);
631 MPIU_Allreduce(&*lnorms.begin(), &*norms.begin(), lnorms.size(), MPIU_REAL,
632 MPIU_SUM, PetscObjectComm((PetscObject)snes));
636 << its <<
" Function norm " << boost::format(
"%14.12e") % (
double)fgnorm
639 for (
auto fi : *fields_ptr) {
641 << its <<
"\t Field norm "
642 << boost::format(
"%14.12e") % (
double)PetscSqrtReal(norms[f]) <<
" "
646 MOFEM_LOG(
"SNES_WORLD", Sev::inform) << its <<
"]";
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;
661 std::vector<double> lnorms(3 * fields_ptr->size(), 0),
662 norms(3 * fields_ptr->size(), 0);
666 CHKERR SNESGetSolution(snes, &x_update);
668 CHKERR SNESGetSolutionUpdate(snes, &x_update);
669 CHKERR SNESGetFunction(snes, &res, PETSC_NULLPTR, PETSC_NULLPTR);
673 CHKERR VecGetArrayRead(res, &r);
674 CHKERR VecGetArrayRead(x_update, &x);
678 for (
auto fi : *fields_ptr) {
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;
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];
694 CHKERR VecRestoreArrayRead(res, &r);
695 CHKERR VecRestoreArrayRead(x_update, &x);
697 MPIU_Allreduce(&*lnorms.begin(), &*norms.begin(), lnorms.size(), MPIU_REAL,
698 MPIU_SUM, PetscObjectComm((PetscObject)snes));
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];
706 energy_norm = std::sqrt(energy_norm);
707 residual_norm = std::sqrt(residual_norm);
708 increment_norm = std::sqrt(increment_norm);
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 <<
"[";
717 for (
auto fi : *fields_ptr) {
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 "
726 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
constexpr AssemblyType A
[Define dimension]
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
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::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.