v0.16.3
Loading...
Searching...
No Matches
approx_sphere.cpp
Go to the documentation of this file.
1/**
2 * \file approx_sphere.cpp
3 * \example mofem/tutorials/vec-4_shallow_wave/approx_sphere.cpp
4 *
5 */
6
7#include <MoFEM.hpp>
8
9using namespace MoFEM;
10
11static char help[] = "...\n\n";
12
13#include <MoFEM.hpp>
14
15constexpr int FM_DIM = 2;
16
17template <int DIM> struct ElementsAndOps {};
18
19template <> struct ElementsAndOps<2> {
21};
22
24using DomainEleOp = DomainEle::UserDataOperator;
26
29
30constexpr double a = 1;
31constexpr double a2 = a * a;
32[[maybe_unused]] constexpr double a4 = a2 * a2;
33
34constexpr double A = 6371220;
35
39
40auto res_J = [](const double x, const double y, const double z) {
41 const double res = (x * x + y * y + z * z - a2);
42 return res;
43};
44
45auto res_J_dx = [](const double x, const double y, const double z) {
46 const double res = res_J(x, y, z);
47 return FTensor::Tensor1<double, 3>{res * (2 * x), res * (2 * y),
48 res * (2 * z)};
49};
50
51auto lhs_J_dx2 = [](const double x, const double y, const double z) {
52 const double res = res_J(x, y, z);
54
55 (res * 2 + (4 * x * x)),
56 (4 * y * x),
57 (4 * z * x),
58
59 (4 * x * y),
60 (2 * res + (4 * y * y)),
61 (4 * z * y),
62
63 (4 * x * z),
64 (4 * y * z),
65 (2 * res + (4 * z * z))};
66};
67
68struct OpRhs : public AssemblyDomainEleOp {
69
70 OpRhs(const std::string field_name, boost::shared_ptr<MatrixDouble> x_ptr,
71 boost::shared_ptr<MatrixDouble> dot_x_ptr)
73 xPtr(x_ptr), xDotPtr(dot_x_ptr) {}
74
77
78 auto t_w = getFTensor0IntegrationWeight();
79 auto t_row_base = row_data.getFTensor0N();
80
81 auto t_x0 = getFTensor1CoordsAtGaussPts();
82 auto t_x = getFTensor1FromMat<3>(*xPtr);
83 auto t_dot_x = getFTensor1FromMat<3>(*xDotPtr);
84 auto t_normal = getFTensor1NormalsAtGaussPts();
85
86 for (int gg = 0; gg != nbIntegrationPts; gg++) {
87
88 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
89 FTensor::Tensor1<double, 3> t_n{t_x0(0), t_x0(1), t_x0(2)};
90 t_n.normalize();
92 t_P(i, j) = t_n(i) * t_n(j);
93 t_Q(i, j) = t_kd(i, j) - t_P(i, j);
94
95 auto t_J_res = res_J_dx(t_x(0), t_x(1), t_x(2));
96
97 const double alpha = t_w;
98 auto t_nf = getFTensor1FromArray<3, 3>(locF);
99 double l = std::sqrt(t_normal(i) * t_normal(i));
100
102 t_res(i) =
103 alpha * l * ((t_P(i, k) * t_J_res(k) + t_Q(i, k) * t_dot_x(k)));
104
105 int rr = 0;
106 for (; rr != nbRows / 3; ++rr) {
107
108 t_nf(j) += t_row_base * t_res(j);
109
110 ++t_row_base;
111 ++t_nf;
112 }
113 for (; rr < nbRowBaseFunctions; ++rr) {
114 ++t_row_base;
115 }
116
117 ++t_w;
118 ++t_x;
119 ++t_dot_x;
120 ++t_x0;
121 ++t_normal;
122 }
123
125 }
126
127private:
128 boost::shared_ptr<MatrixDouble> xPtr;
129 boost::shared_ptr<MatrixDouble> xDotPtr;
130};
131
132struct OpLhs : public AssemblyDomainEleOp {
133
134 OpLhs(const std::string field_name, boost::shared_ptr<MatrixDouble> x_ptr,
135 boost::shared_ptr<MatrixDouble> dot_x_ptr)
137 AssemblyDomainEleOp::OPROWCOL),
138 xPtr(x_ptr), xDotPtr(dot_x_ptr) {
139 this->sYmm = false;
140 }
141
143 EntitiesFieldData::EntData &col_data) {
145
146 auto t_w = getFTensor0IntegrationWeight();
147 auto t_row_base = row_data.getFTensor0N();
148
149 auto t_x0 = getFTensor1CoordsAtGaussPts();
150 auto t_x = getFTensor1FromMat<3>(*xPtr);
151 auto t_normal = getFTensor1NormalsAtGaussPts();
152
153 auto get_t_mat = [&](const int rr) {
155 &locMat(rr + 0, 0), &locMat(rr + 0, 1), &locMat(rr + 0, 2),
156
157 &locMat(rr + 1, 0), &locMat(rr + 1, 1), &locMat(rr + 1, 2),
158
159 &locMat(rr + 2, 0), &locMat(rr + 2, 1), &locMat(rr + 2, 2)};
160 };
161
162 const double ts_a = getTSa();
163
164 for (int gg = 0; gg != nbIntegrationPts; gg++) {
165
166 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
167 FTensor::Tensor1<double, 3> t_n{t_x0(0), t_x0(1), t_x0(2)};
168 t_n.normalize();
170 t_P(i, j) = t_n(i) * t_n(j);
171 t_Q(i, j) = t_kd(i, j) - t_P(i, j);
172
173 auto t_J_lhs = lhs_J_dx2(t_x(0), t_x(1), t_x(2));
174 double l = std::sqrt(t_normal(i) * t_normal(i));
175
176 const double alpha = t_w;
178 t_lhs(i, j) =
179 (alpha * l) * (t_P(i, k) * t_J_lhs(k, j) + t_Q(i, j) * ts_a);
180
181 int rr = 0;
182 for (; rr != nbRows / 3; rr++) {
183
184 auto t_col_base = col_data.getFTensor0N(gg, 0);
185 auto t_mat = get_t_mat(3 * rr);
186
187 for (int cc = 0; cc != nbCols / 3; cc++) {
188
189 const double rc = t_row_base * t_col_base;
190 t_mat(i, j) += rc * t_lhs(i, j);
191
192 ++t_col_base;
193 ++t_mat;
194 }
195 ++t_row_base;
196 }
197
198 for (; rr < nbRowBaseFunctions; ++rr)
199 ++t_row_base;
200
201 ++t_w;
202 ++t_x;
203 ++t_x0;
204 ++t_normal;
205 }
206
208 }
209
210private:
211 boost::shared_ptr<MatrixDouble> xPtr;
212 boost::shared_ptr<MatrixDouble> xDotPtr;
213};
214
215struct OpError : public DomainEleOp {
216
217 OpError(const std::string field_name, boost::shared_ptr<MatrixDouble> x_ptr)
219 xPtr(x_ptr) {
220
221 std::fill(&doEntities[MBEDGE], &doEntities[MBMAXTYPE], false);
222 }
223
224 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
225
227
228 auto t_w = getFTensor0IntegrationWeight();
229 auto t_x = getFTensor1FromMat<3>(*xPtr);
230 auto t_normal = getFTensor1NormalsAtGaussPts();
231 auto nb_integration_pts = getGaussPts().size2();
232
233 double error = 0;
234
235 for (int gg = 0; gg != nb_integration_pts; gg++) {
236
237 double l = std::sqrt(t_normal(i) * t_normal(i));
238 error += t_w * l * std::abs((t_x(i) * t_x(i) - A * A));
239
240 ++t_w;
241 ++t_x;
242 ++t_normal;
243 }
244
245 CHKERR VecSetValue(errorVec, 0, error, ADD_VALUES);
246
248 }
249
251
252private:
253 boost::shared_ptr<MatrixDouble> xPtr;
254};
255
257
274
275//! [Run programme]
286//! [Run programme]
287
292
293//! [Read mesh]
301//! [Read mesh]
302
303//! [Set up problem]
306
309 CHKERR simple->addDataField("HO_POSITIONS", H1, AINSWORTH_LEGENDRE_BASE, 3);
310
311 int order = 3;
312 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order", &order, PETSC_NULLPTR);
313 CHKERR simple->setFieldOrder("HO_POSITIONS", order);
314 CHKERR simple->setUp();
315
317}
318//! [Set up problem]
319
320//! [Push operators to pipeline]
324
325 auto integration_rule = [](int, int, int approx_order) {
326 return 3 * approx_order;
327 };
330
331 auto x_ptr = boost::make_shared<MatrixDouble>();
332 auto dot_x_ptr = boost::make_shared<MatrixDouble>();
333 auto det_ptr = boost::make_shared<VectorDouble>();
334 auto jac_ptr = boost::make_shared<MatrixDouble>();
335 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
336
337 auto def_ops = [&](auto &pipeline) {
338 pipeline.push_back(
339 new OpCalculateVectorFieldValues<3>("HO_POSITIONS", x_ptr));
340 pipeline.push_back(
341 new OpCalculateVectorFieldValuesDot<3>("HO_POSITIONS", dot_x_ptr));
342 };
343
344 def_ops(pipeline_mng->getOpDomainRhsPipeline());
345 def_ops(pipeline_mng->getOpDomainLhsPipeline());
346
347 pipeline_mng->getOpDomainRhsPipeline().push_back(
348 new OpRhs("HO_POSITIONS", x_ptr, dot_x_ptr));
349 pipeline_mng->getOpDomainLhsPipeline().push_back(
350 new OpLhs("HO_POSITIONS", x_ptr, dot_x_ptr));
351
353}
354//! [Push operators to pipeline]
355
356//! [Solve]
359
360 // Project HO geometry from mesh
361 Projection10NodeCoordsOnField ent_method_material(mField, "HO_POSITIONS");
362 CHKERR mField.loop_dofs("HO_POSITIONS", ent_method_material);
363
364 auto *simple = mField.getInterface<Simple>();
365 auto *pipeline_mng = mField.getInterface<PipelineManager>();
366
367 auto dm = simple->getDM();
369 ts = pipeline_mng->createTSIM();
370
371 double ftime = 1;
372 CHKERR TSSetMaxSteps(ts, 1);
373 CHKERR TSSetExactFinalTime(ts, TS_EXACTFINALTIME_MATCHSTEP);
374
375 auto T = createDMVector(simple->getDM());
376 CHKERR DMoFEMMeshToLocalVector(simple->getDM(), T, INSERT_VALUES,
377 SCATTER_FORWARD);
378 CHKERR TSSetSolution(ts, T);
379 CHKERR TSSetFromOptions(ts);
380
381 CHKERR TSSolve(ts, NULL);
382 // Solver convergence is cheap to check and carries no magic numbers, so it
383 // stands alone rather than waiting on a "-test_nb"/"-test_name" selector.
384 {
385 PetscReal expected_time;
386 CHKERR TSGetTime(ts, &expected_time);
388 ts, expected_time, {1e-12, 1e-12}, "shallow wave sphere");
389 }
390 CHKERR TSGetTime(ts, &ftime);
391
392 CHKERR mField.getInterface<FieldBlas>()->fieldScale(A, "HO_POSITIONS");
393
395}
396
397//! [Solve]
400
401 auto x_ptr = boost::make_shared<MatrixDouble>();
402 auto det_ptr = boost::make_shared<VectorDouble>();
403 auto jac_ptr = boost::make_shared<MatrixDouble>();
404 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
405
407 auto dm = simple->getDM();
408
409 auto post_proc_fe =
410 boost::make_shared<PostProcBrokenMeshInMoab<DomainEle>>(mField);
411
412 post_proc_fe->getOpPtrVector().push_back(
413 new OpCalculateVectorFieldValues<3>("HO_POSITIONS", x_ptr));
414
416
417 post_proc_fe->getOpPtrVector().push_back(
418
419 new OpPPMap(post_proc_fe->getPostProcMesh(),
420 post_proc_fe->getMapGaussPts(),
421
422 {},
423
424 {{"HO_POSITIONS", x_ptr}},
425
426 {}, {}
427
428 )
429
430 );
431
432 CHKERR DMoFEMLoopFiniteElements(dm, "dFE", post_proc_fe);
433 CHKERR post_proc_fe->writeFile("out_approx.h5m");
434
435 auto error_fe = boost::make_shared<DomainEle>(mField);
436
437 error_fe->getOpPtrVector().push_back(
438 new OpGetHONormalsOnFace("HO_POSITIONS"));
439 error_fe->getOpPtrVector().push_back(
440 new OpCalculateVectorFieldValues<3>("HO_POSITIONS", x_ptr));
441 error_fe->getOpPtrVector().push_back(new OpError("HO_POSITIONS", x_ptr));
442
443 error_fe->preProcessHook = [&]() {
445 MOFEM_LOG("EXAMPLE", Sev::inform) << "Create vec ";
447 mField.get_comm(), (!mField.get_comm_rank()) ? 1 : 0, 1);
448 VecZeroEntries(OpError::errorVec);
450 };
451
452 error_fe->postProcessHook = [&]() {
454 CHKERR VecAssemblyBegin(OpError::errorVec);
455 CHKERR VecAssemblyEnd(OpError::errorVec);
456 double error2;
457 CHKERR VecSum(OpError::errorVec, &error2);
458 MOFEM_LOG("EXAMPLE", Sev::inform)
459 << "Error " << std::sqrt(error2 / (4 * M_PI * A * A));
460 OpError::errorVec.reset();
462 };
463
464 CHKERR DMoFEMLoopFiniteElements(dm, "dFE", error_fe);
465
466 CHKERR simple->deleteDM();
467 CHKERR simple->deleteFiniteElements();
468 if (mField.get_comm_size() > 1)
469 CHKERR mField.get_moab().write_file("out_ho_mesh.h5m", "MOAB",
470 "PARALLEL=WRITE_PART");
471 else
472 CHKERR mField.get_moab().write_file("out_ho_mesh.h5m");
474}
475//! [Postprocess results]
476
477int main(int argc, char *argv[]) {
478
479 // Initialisation of MoFEM/PETSc and MOAB data structures
480 const char param_file[] = "param_file.petsc";
481 MoFEM::Core::Initialize(&argc, &argv, param_file, help);
482
483 auto core_log = logging::core::get();
484 core_log->add_sink(
486 LogManager::setLog("EXAMPLE");
487 MOFEM_LOG_TAG("EXAMPLE", "example");
488
489 try {
490
491 //! [Register MoFEM discrete manager in PETSc]
492 DMType dm_name = "DMMOFEM";
493 CHKERR DMRegister_MoFEM(dm_name);
494 //! [Register MoFEM discrete manager in PETSc
495
496 //! [Create MoAB]
497 moab::Core mb_instance; ///< mesh database
498 moab::Interface &moab = mb_instance; ///< mesh database interface
499 //! [Create MoAB]
500
501 //! [Create MoFEM]
502 MoFEM::Core core(moab); ///< finite element database
503 MoFEM::Interface &m_field = core; ///< finite element database insterface
504 //! [Create MoFEM]
505
506 //! [ApproxSphere]
507 ApproxSphere ex(m_field);
508 CHKERR ex.runProblem();
509 //! [ApproxSphere]
510 }
512
514}
std::string type
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
int main()
constexpr double a2
constexpr double a
static char help[]
constexpr double a4
constexpr double A
auto lhs_J_dx2
constexpr int FM_DIM
FTensor::Index< 'j', 3 > j
FTensor::Index< 'i', 3 > i
auto res_J_dx
auto res_J
FTensor::Index< 'k', 3 > k
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
Kronecker Delta class.
Tensor1< T, Tensor_Dim > normalize()
#define CATCH_ERRORS
Catch errors.
@ 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()
@ 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 ...
#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 ...
constexpr int order
auto integration_rule
constexpr auto t_kd
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode, RowColData rc=RowColData::COL)
set local (or ghosted) vector values on mesh for partition only
Definition DMMoFEM.cpp:543
PetscErrorCode DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
Definition DMMoFEM.cpp:43
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:605
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
Definition DMMoFEM.hpp:1250
boost::ptr_deque< UserDataOperator > & getOpDomainLhsPipeline()
Get the Op Domain Lhs Pipeline object.
boost::ptr_deque< UserDataOperator > & getOpDomainRhsPipeline()
Get the Op Domain Rhs Pipeline object.
@ PETSC
Standard PETSc assembly.
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.
virtual MoFEMErrorCode loop_dofs(const Problem *problem_ptr, const std::string &field_name, RowColData rc, DofMethod &method, int lower_rank, int upper_rank, int verb=DEFAULT_VERBOSITY)=0
Make a loop over dofs.
FTensor::Index< 'l', 3 > l
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
auto createVectorMPI(MPI_Comm comm, PetscInt n, PetscInt N)
Create MPI Vector.
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
constexpr auto field_name
static constexpr int approx_order
MoFEMErrorCode readMesh()
[Read mesh]
MoFEMErrorCode solveSystem()
[Push operators to pipeline]
MoFEM::Interface & mField
MoFEMErrorCode setupProblem()
[Read mesh]
ApproxSphere(MoFEM::Interface &m_field)
MoFEMErrorCode runProblem()
[Run programme]
MoFEMErrorCode setOPs()
[Set up problem]
MoFEMErrorCode getOptions()
[Run programme]
MoFEMErrorCode outputResults()
[Solve]
[Operators_definition]
virtual int get_comm_size() const =0
virtual moab::Interface & get_moab()=0
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
Core (interface) class.
Definition Core.hpp:83
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
Definition Core.cpp:68
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Definition Core.cpp:123
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)
FTensor::Tensor0< FTensor::PackPtr< double *, 1 > > getFTensor0N(const FieldApproximationBase base)
Get base function as Tensor0.
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.
static boost::shared_ptr< std::ostream > getStrmWorld()
Get the strm world object.
VectorDouble locF
local entity vector
int nbRows
number of dofs on rows
int nbIntegrationPts
number of integration points
MatrixDouble locMat
local entity block matrix
int nbCols
number if dof on column
int nbRowBaseFunctions
number or row base functions
Approximate field values for given petsc vector.
Specialization for MatrixDouble vector field values calculation.
Calculate normal vectors at Gauss points of face elements.
Post post-proc data at points from hash maps.
PipelineManager interface.
MoFEMErrorCode setDomainRhsIntegrationRule(RuleHookFun rule)
Set integration rule for domain right-hand side finite element.
MoFEMErrorCode setDomainLhsIntegrationRule(RuleHookFun rule)
Set integration rule for domain left-hand side finite element.
Projection of edge entities with one mid-node on hierarchical basis.
Simple interface for fast problem set-up.
Definition Simple.hpp:27
MoFEMErrorCode addDomainField(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_ZERO, int verb=-1)
Add field on domain.
Definition Simple.cpp:261
MoFEMErrorCode getOptions()
get options
Definition Simple.cpp:180
MoFEMErrorCode getDM(DM *dm)
Get DM.
Definition Simple.cpp:799
intrusive_ptr for managing petsc objects
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
OpError(const std::string field_name, boost::shared_ptr< MatrixDouble > x_ptr)
static SmartPetscObj< Vec > errorVec
boost::shared_ptr< MatrixDouble > xPtr
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data, EntitiesFieldData::EntData &col_data)
Integrate grad-grad operator.
boost::shared_ptr< MatrixDouble > xPtr
boost::shared_ptr< MatrixDouble > xDotPtr
OpLhs(const std::string field_name, boost::shared_ptr< MatrixDouble > x_ptr, boost::shared_ptr< MatrixDouble > dot_x_ptr)
boost::shared_ptr< MatrixDouble > xPtr
boost::shared_ptr< MatrixDouble > xDotPtr
OpRhs(const std::string field_name, boost::shared_ptr< MatrixDouble > x_ptr, boost::shared_ptr< MatrixDouble > dot_x_ptr)
MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data)
Class dedicated to integrate operator.