v0.14.0
Loading...
Searching...
No Matches
heat_equation.cpp
Go to the documentation of this file.
1/**
2 * \file heat_equation.cpp
3 * \example heat_equation.cpp
4 *
5 * \brief Solve the time-dependent Heat Equation
6 \f[
7 \begin{aligned}
8\frac{\partial u(\mathbf{x}, t)}{\partial t}-\Delta u(\mathbf{x}, t)
9&=f(\mathbf{x}, t) & & \forall \mathbf{x} \in \Omega, t \in(0, T), \\
10u(\mathbf{x}, 0) &=u_{0}(\mathbf{x}) & & \forall \mathbf{x} \in \Omega, \\
11u(\mathbf{x}, t) &=g(\mathbf{x}, t) & & \forall \mathbf{x} \in \partial \Omega,
12t \in(0, T). \end{aligned}
13 \f]
14 **/
15
16#include <stdlib.h>
17#include <cmath>
19
20using namespace MoFEM;
21
22static char help[] = "...\n\n";
23
24template <int DIM> struct ElementsAndOps {};
25
26//! [Define dimension]
27constexpr int SPACE_DIM = 2; //< Space dimension of problem, mesh
28//! [Define dimension]
29
36
47
54
55// Capacity
56constexpr double c = 1;
57constexpr double k = 1;
58constexpr double init_u = 0.;
59
60/**
61 * @brief Monitor solution
62 *
63 * This functions is called by TS solver at the end of each step. It is used
64 * to output results to the hard drive.
65 */
66struct Monitor : public FEMethod {
67
68 Monitor(SmartPetscObj<DM> dm, boost::shared_ptr<PostProcEle> post_proc)
69 : dM(dm), postProc(post_proc){};
70
71 MoFEMErrorCode preProcess() { return 0; }
72 MoFEMErrorCode operator()() { return 0; }
73
74 static constexpr int saveEveryNthStep = 1;
75
78 if (ts_step % saveEveryNthStep == 0) {
80 CHKERR postProc->writeFile(
81 "out_level_" + boost::lexical_cast<std::string>(ts_step) + ".h5m");
82 }
84 }
85
86private:
88 boost::shared_ptr<PostProcEle> postProc;
89};
90
92public:
94
95 // Declaration of the main function to run analysis
97
98private:
99 // Declaration of other main functions called in runProgram()
108
109 // Main interfaces
111
112 // Object to mark boundary entities for the assembling of domain elements
113 boost::shared_ptr<std::vector<unsigned char>> boundaryMarker;
114};
115
116HeatEquation::HeatEquation(MoFEM::Interface &m_field) : mField(m_field) {}
117
120
121 auto *simple = mField.getInterface<Simple>();
123 CHKERR simple->getOptions();
124 CHKERR simple->loadFile();
125
127}
128
131
132 auto *simple = mField.getInterface<Simple>();
133 CHKERR simple->addDomainField("U", H1, AINSWORTH_LEGENDRE_BASE, 1);
134 CHKERR simple->addBoundaryField("U", H1, AINSWORTH_LEGENDRE_BASE, 1);
135
136 int order = 3;
137 CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-order", &order, PETSC_NULL);
138 CHKERR simple->setFieldOrder("U", order);
139
140 CHKERR simple->setUp();
141
143}
144
147
148 auto integration_rule = [](int o_row, int o_col, int approx_order) {
149 return 2 * approx_order;
150 };
151
152 auto *pipeline_mng = mField.getInterface<PipelineManager>();
153 CHKERR pipeline_mng->setDomainRhsIntegrationRule(integration_rule);
154 CHKERR pipeline_mng->setDomainLhsIntegrationRule(integration_rule);
155 CHKERR pipeline_mng->setBoundaryLhsIntegrationRule(integration_rule);
156 CHKERR pipeline_mng->setBoundaryRhsIntegrationRule(integration_rule);
157
159}
160
163
164 // Get surface entities form blockset, set initial values in those
165 // blocksets. To keep it simple, it is assumed that inital values are on
166 // blockset 1
168 Range inner_surface;
169 CHKERR mField.getInterface<MeshsetsManager>()->getEntitiesByDimension(
170 1, BLOCKSET, 2, inner_surface, true);
171 if (!inner_surface.empty()) {
172 Range inner_surface_verts;
173 CHKERR mField.get_moab().get_connectivity(inner_surface,
174 inner_surface_verts, false);
175 CHKERR mField.getInterface<FieldBlas>()->setField(
176 init_u, MBVERTEX, inner_surface_verts, "U");
177 }
178 }
179
181}
182
185
186 auto bc_mng = mField.getInterface<BcManager>();
187 auto *simple = mField.getInterface<Simple>();
188 CHKERR bc_mng->pushMarkDOFsOnEntities(simple->getProblemName(), "ESSENTIAL",
189 "U", 0, 0);
190
191 auto &bc_map = bc_mng->getBcMapByBlockName();
192 boundaryMarker = boost::make_shared<std::vector<char unsigned>>();
193 for (auto b : bc_map) {
194 if (std::regex_match(b.first, std::regex("(.*)ESSENTIAL(.*)"))) {
195 boundaryMarker->resize(b.second->bcMarkers.size(), 0);
196 for (int i = 0; i != b.second->bcMarkers.size(); ++i) {
197 (*boundaryMarker)[i] |= b.second->bcMarkers[i];
198 }
199 }
200 }
201
203}
204
207
208 auto add_domain_lhs_ops = [&](auto &pipeline) {
210 pipeline.push_back(new OpSetBc("U", true, boundaryMarker));
211 pipeline.push_back(new OpDomainGradGrad(
212 "U", "U", [](double, double, double) -> double { return k; }));
213 auto get_c = [this](const double, const double, const double) {
214 auto pipeline_mng = mField.getInterface<PipelineManager>();
215 auto &fe_domain_lhs = pipeline_mng->getDomainLhsFE();
216 return c * fe_domain_lhs->ts_a;
217 };
218 pipeline.push_back(new OpDomainMass("U", "U", get_c));
219 pipeline.push_back(new OpUnSetBc("U"));
220 };
221
222 auto add_domain_rhs_ops = [&](auto &pipeline) {
224 pipeline.push_back(new OpSetBc("U", true, boundaryMarker));
225 auto grad_u_at_gauss_pts = boost::make_shared<MatrixDouble>();
226 auto dot_u_at_gauss_pts = boost::make_shared<VectorDouble>();
227 pipeline.push_back(new OpCalculateScalarFieldGradient<SPACE_DIM>(
228 "U", grad_u_at_gauss_pts));
229 pipeline.push_back(
230 new OpCalculateScalarFieldValuesDot("U", dot_u_at_gauss_pts));
231 pipeline.push_back(new OpDomainGradTimesVec(
232 "U", grad_u_at_gauss_pts,
233 [](double, double, double) -> double { return k; }));
234 pipeline.push_back(new OpDomainTimesScalarField(
235 "U", dot_u_at_gauss_pts,
236 [](const double, const double, const double) { return c; }));
237 auto source_term = [&](const double x, const double y, const double z) {
238 auto pipeline_mng = mField.getInterface<PipelineManager>();
239 auto &fe_domain_lhs = pipeline_mng->getDomainRhsFE();
240 const auto t = fe_domain_lhs->ts_t;
241 return 1e1 * pow(M_E, -M_PI * M_PI * t) * sin(1. * M_PI * x) *
242 sin(2. * M_PI * y);
243 };
244 pipeline.push_back(new OpDomainSource("U", source_term));
245 pipeline.push_back(new OpUnSetBc("U"));
246 };
247
248 auto add_boundary_lhs_ops = [&](auto &pipeline) {
249 pipeline.push_back(new OpSetBc("U", false, boundaryMarker));
250 pipeline.push_back(new OpBoundaryMass(
251 "U", "U", [](const double, const double, const double) { return c; }));
252 pipeline.push_back(new OpUnSetBc("U"));
253 };
254 auto add_boundary_rhs_ops = [&](auto &pipeline) {
255 pipeline.push_back(new OpSetBc("U", false, boundaryMarker));
256 auto u_at_gauss_pts = boost::make_shared<VectorDouble>();
257 auto boundary_function = [&](const double x, const double y,
258 const double z) {
259 auto pipeline_mng = mField.getInterface<PipelineManager>();
260 auto &fe_rhs = pipeline_mng->getBoundaryRhsFE();
261 const auto t = fe_rhs->ts_t;
262 return 0;
263 // abs(0.1 * pow(M_E, -M_PI * M_PI * t) * sin(2. * M_PI * x) *
264 // sin(3. * M_PI * y));
265 };
266 pipeline.push_back(new OpCalculateScalarFieldValues("U", u_at_gauss_pts));
267 pipeline.push_back(new OpBoundaryTimeScalarField(
268 "U", u_at_gauss_pts,
269 [](const double, const double, const double) { return c; }));
270 pipeline.push_back(new OpBoundarySource("U", boundary_function));
271 pipeline.push_back(new OpUnSetBc("U"));
272 };
273
274 auto pipeline_mng = mField.getInterface<PipelineManager>();
275 add_domain_lhs_ops(pipeline_mng->getOpDomainLhsPipeline());
276 add_domain_rhs_ops(pipeline_mng->getOpDomainRhsPipeline());
277 add_boundary_lhs_ops(pipeline_mng->getOpBoundaryLhsPipeline());
278 add_boundary_rhs_ops(pipeline_mng->getOpBoundaryRhsPipeline());
279
281}
282
284 static PetscErrorCode set(TS ts, PetscReal t, Vec u, Vec u_t, PetscReal a,
285 Mat A, Mat B, void *ctx) {
287 if (a != lastA) {
288 lastA = a;
289 CHKERR TsSetIJacobian(ts, t, u, u_t, a, A, B, ctx);
290 }
292 }
293
294private:
295 static double lastA;
296};
297
298double CalcJacobian::lastA = 0;
299
302
303 auto *simple = mField.getInterface<Simple>();
304 auto *pipeline_mng = mField.getInterface<PipelineManager>();
305
306 auto create_post_process_element = [&]() {
307 auto post_proc_fe = boost::make_shared<PostProcEle>(mField);
308 auto det_ptr = boost::make_shared<VectorDouble>();
309 auto jac_ptr = boost::make_shared<MatrixDouble>();
310 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
311 post_proc_fe->getOpPtrVector().push_back(new OpCalculateHOJac<2>(jac_ptr));
312 post_proc_fe->getOpPtrVector().push_back(
313 new OpInvertMatrix<2>(jac_ptr, det_ptr, inv_jac_ptr));
314 post_proc_fe->getOpPtrVector().push_back(
315 new OpSetHOInvJacToScalarBases<2>(H1, inv_jac_ptr));
316
317 auto u_ptr = boost::make_shared<VectorDouble>();
318 post_proc_fe->getOpPtrVector().push_back(
319 new OpCalculateScalarFieldValues("U", u_ptr));
320
322
323 post_proc_fe->getOpPtrVector().push_back(
324
325 new OpPPMap(post_proc_fe->getPostProcMesh(),
326 post_proc_fe->getMapGaussPts(),
327
328 {{"U", u_ptr}},
329
330 {}, {}, {}
331
332 )
333
334 );
335
336 return post_proc_fe;
337 };
338
339 auto set_time_monitor = [&](auto dm, auto solver) {
341 boost::shared_ptr<Monitor> monitor_ptr(
342 new Monitor(dm, create_post_process_element()));
343 boost::shared_ptr<ForcesAndSourcesCore> null;
344 CHKERR DMMoFEMTSSetMonitor(dm, solver, simple->getDomainFEName(),
345 monitor_ptr, null, null);
347 };
348
349 auto set_fieldsplit_preconditioner = [&](auto solver) {
351 SNES snes;
352 CHKERR TSGetSNES(solver, &snes);
353 KSP ksp;
354 CHKERR SNESGetKSP(snes, &ksp);
355 PC pc;
356 CHKERR KSPGetPC(ksp, &pc);
357 PetscBool is_pcfs = PETSC_FALSE;
358 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
359
360 if (is_pcfs == PETSC_TRUE) {
361 auto bc_mng = mField.getInterface<BcManager>();
362 auto name_prb = simple->getProblemName();
363 auto is_all_bc = bc_mng->getBlockIS(name_prb, "ESSENTIAL", "U", 0, 0);
364 int is_all_bc_size;
365 CHKERR ISGetSize(is_all_bc, &is_all_bc_size);
366 MOFEM_LOG("EXAMPLE", Sev::inform)
367 << "Field split block size " << is_all_bc_size;
368 CHKERR PCFieldSplitSetIS(pc, PETSC_NULL,
369 is_all_bc); // boundary block
370 }
372 };
373
374 /**
375 * That to work, you have to create solver, as follows,
376 \code
377 auto solver = // pipeline_mng->createTSIM( simple->getDM());
378 \endcode
379 That is explicitly use use Simple DM to create solver for DM. Pipeline
380 menage by default creat copy of DM, in case several solvers are used the
381 same DM.
382
383 Alternatively you can get dm directly from the solver, i.e.
384 \code
385 DM ts_dm;
386 CHKERR TSGetDM(solver, &ts_dm);
387 CHKERR DMTSSetIJacobian(
388 ts_dm, CalcJacobian::set, getDMTsCtx(ts_dm).get());
389 \endcode
390 */
391 auto set_user_ts_jacobian = [&](auto dm) {
393 CHKERR DMTSSetIJacobian(dm, CalcJacobian::set, getDMTsCtx(dm).get());
395 };
396
397 auto dm = simple->getDM();
398 auto D = createDMVector(dm);
399 CHKERR DMoFEMMeshToLocalVector(dm, D, INSERT_VALUES, SCATTER_FORWARD);
400
401 auto solver = pipeline_mng->createTSIM(
402 simple->getDM()); // Note DM is set as argument. If DM is not, internal
403 // copy of pipeline DM is created.
404 CHKERR set_user_ts_jacobian(dm);
405 CHKERR set_time_monitor(dm, solver);
406 CHKERR TSSetSolution(solver, D);
407 CHKERR TSSetFromOptions(solver);
408 CHKERR set_fieldsplit_preconditioner(solver);
409 CHKERR TSSetUp(solver);
410
411 CHKERR TSSolve(solver, D);
412
414}
415
418
419 // Processes to set output results are integrated in solveSystem()
420
422}
423
426
435
437}
438
439int main(int argc, char *argv[]) {
440
441 // Initialisation of MoFEM/PETSc and MOAB data structures
442 const char param_file[] = "param_file.petsc";
444
445 // Add logging channel for example
446 auto core_log = logging::core::get();
447 core_log->add_sink(
449 LogManager::setLog("EXAMPLE");
450 MOFEM_LOG_TAG("EXAMPLE", "example")
451
452 // Error handling
453 try {
454 // Register MoFEM discrete manager in PETSc
455 DMType dm_name = "DMMOFEM";
456 CHKERR DMRegister_MoFEM(dm_name);
457
458 // Create MOAB instance
459 moab::Core mb_instance; // mesh database
460 moab::Interface &moab = mb_instance; // mesh database interface
461
462 // Create MoFEM instance
463 MoFEM::Core core(moab); // finite element database
464 MoFEM::Interface &m_field = core; // finite element interface
465
466 // Run the main analysis
467 HeatEquation heat_problem(m_field);
468 CHKERR heat_problem.runProgram();
469 }
471
472 // Finish work: cleaning memory, getting statistics, etc.
474
475 return 0;
476}
std::string param_file
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition: acoustic.cpp:69
int main()
Definition: adol-c_atom.cpp:46
constexpr double a
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpSource< 1, FIELD_DIM > OpDomainSource
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, FIELD_DIM > OpDomainMass
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
#define CATCH_ERRORS
Catch errors.
Definition: definitions.h:372
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition: definitions.h:60
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
Definition: definitions.h:447
@ H1
continuous field
Definition: definitions.h:85
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:346
@ BLOCKSET
Definition: definitions.h:148
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
Definition: definitions.h:416
#define CHKERR
Inline error check.
Definition: definitions.h:535
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:440
auto integration_rule
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode)
set local (or ghosted) vector values on mesh for partition only
Definition: DMMoFEM.cpp:509
PetscErrorCode DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
Definition: DMMoFEM.cpp:47
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
Definition: DMMoFEM.cpp:572
auto createDMVector(DM dm)
Get smart vector from DM.
Definition: DMMoFEM.hpp:1003
static LoggerType & setLog(const std::string channel)
Set ans resset chanel logger.
Definition: LogManager.cpp:389
#define MOFEM_LOG(channel, severity)
Log.
Definition: LogManager.hpp:308
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
Definition: LogManager.hpp:339
bool checkMeshset(const int ms_id, const CubitBCType cubit_bc_type) const
check for CUBIT Id and CUBIT type
FTensor::Index< 'i', SPACE_DIM > i
constexpr double init_u
FormsIntegrators< BoundaryEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpBaseTimesScalar< 1 > OpBoundaryTimeScalarField
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, 1 > OpDomainMass
static char help[]
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpBaseTimesScalar< 1 > OpDomainTimesScalarField
constexpr double k
constexpr int SPACE_DIM
[Define dimension]
constexpr double c
FormsIntegrators< BoundaryEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpSource< 1, 1 > OpBoundarySource
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpGradTimesTensor< 1, 1, SPACE_DIM > OpDomainGradTimesVec
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpGradGrad< 1, 1, SPACE_DIM > OpDomainGradGrad
FormsIntegrators< BoundaryEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, 1 > OpBoundaryMass
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpSource< 1, 1 > OpDomainSource
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpGradGrad< 1, 1, SPACE_DIM > OpDomainGradGrad
Definition: helmholtz.cpp:25
FormsIntegrators< EdgeEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, 1 > OpBoundaryMass
Definition: helmholtz.cpp:29
FormsIntegrators< EdgeEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpSource< 1, 1 > OpBoundarySource
Definition: helmholtz.cpp:31
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpBaseTimesScalar< 1 > OpDomainTimesScalarField
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpGradTimesTensor< 1, 1, SPACE_DIM > OpDomainGradTimesVec
double D
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
Definition: Exceptions.hpp:56
implementation of Data Operators for Forces and Sources
Definition: Common.hpp:10
PetscErrorCode DMMoFEMTSSetMonitor(DM dm, TS ts, const std::string fe_name, boost::shared_ptr< MoFEM::FEMethod > method, boost::shared_ptr< MoFEM::BasicMethod > pre_only, boost::shared_ptr< MoFEM::BasicMethod > post_only)
Set Monitor To TS solver.
Definition: DMMoFEM.cpp:1042
PetscErrorCode TsSetIJacobian(TS ts, PetscReal t, Vec u, Vec u_t, PetscReal a, Mat A, Mat B, void *ctx)
Set function evaluating jacobina in TS solver.
Definition: TsCtx.cpp:131
auto getDMTsCtx(DM dm)
Get TS context data structure used by DM.
Definition: DMMoFEM.hpp:1045
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
OpCalculateScalarFieldValuesFromPetscVecImpl< PetscData::CTX_SET_X_T > OpCalculateScalarFieldValuesDot
constexpr AssemblyType A
FormsIntegrators< BoundaryEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpBaseTimesScalar< 1 > OpBoundaryTimeScalarField
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
constexpr double t
plate stiffness
Definition: plate.cpp:59
static constexpr int approx_order
static double lastA
static PetscErrorCode set(TS ts, PetscReal t, Vec u, Vec u_t, PetscReal a, Mat A, Mat B, void *ctx)
MoFEM::Interface & mField
MoFEMErrorCode solveSystem()
MoFEMErrorCode outputResults()
HeatEquation(MoFEM::Interface &m_field)
MoFEMErrorCode setupProblem()
MoFEMErrorCode setIntegrationRules()
MoFEMErrorCode assembleSystem()
MoFEMErrorCode readMesh()
MoFEMErrorCode boundaryCondition()
boost::shared_ptr< std::vector< unsigned char > > boundaryMarker
MoFEMErrorCode runProgram()
MoFEMErrorCode initialCondition()
Add operators pushing bases from local to physical configuration.
Simple interface for fast problem set-up.
Definition: BcManager.hpp:25
virtual moab::Interface & get_moab()=0
Core (interface) class.
Definition: Core.hpp:82
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
Definition: Core.cpp:72
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Definition: Core.cpp:112
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)
structure for User Loop Methods on finite elements
Basic algebra on fields.
Definition: FieldBlas.hpp:21
static boost::shared_ptr< SinkType > createSink(boost::shared_ptr< std::ostream > stream_ptr, std::string comm_filter)
Create a sink object.
Definition: LogManager.cpp:298
static boost::shared_ptr< std::ostream > getStrmWorld()
Get the strm world object.
Definition: LogManager.cpp:344
Interface for managing meshsets containing materials and boundary conditions.
Get field gradients at integration pts for scalar filed rank 0, i.e. vector field.
Get value at integration points for scalar field.
Post post-proc data at points from hash maps.
Set indices on entities on finite element.
Set inverse jacobian to base functions.
PipelineManager interface.
boost::shared_ptr< FEMethod > & getDomainRhsFE()
boost::shared_ptr< FEMethod > & getDomainLhsFE()
MoFEM::FaceElementForcesAndSourcesCore FaceEle
MoFEM::EdgeElementForcesAndSourcesCore EdgeEle
boost::shared_ptr< FEMethod > & getBoundaryRhsFE()
Simple interface for fast problem set-up.
Definition: Simple.hpp:27
intrusive_ptr for managing petsc objects
PetscInt ts_step
time step number
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface refernce to pointer of interface.
[Push operators to pipeline]
Monitor(SmartPetscObj< DM > dm, boost::shared_ptr< PostProcEle > post_proc)
static constexpr int saveEveryNthStep
SmartPetscObj< DM > dM
MoFEMErrorCode postProcess()
function is run at the end of loop
boost::shared_ptr< PostProcEle > postProc
MoFEMErrorCode operator()()
function is run for every finite element
MoFEMErrorCode preProcess()
function is run at the beginning of loop