v0.16.0
Loading...
Searching...
No Matches
cell_forces.cpp
Go to the documentation of this file.
1/**
2 \file cell_forces.cpp
3 \brief Calculate cell forces
4
5 \tableofcontents
6
7 \section cell_potential Implementation with forces potential
8
9In the following code, we solve the problem of identification of forces which
10result in given displacements on some surface inside the body.
11
12In the experiment, a body is covered on top by transparent gel layer, on the
13interface between movements of markers (bids) is observed. Strain in the body is
14generated by cells living on the top layer. Here we looking for forces generated
15by those cells.
16
17Following implementing when needed could be easily extended to curved surfaces
18arbitrary located in the body.
19
20\ref mofem_citation
21
22\htmlonly
23<a href="https://doi.org/10.5281/zenodo.439392"><img
24src="https://zenodo.org/badge/DOI/10.5281/zenodo.439392.svg" alt="DOI"></a> <a
25href="https://doi.org/10.5281/zenodo.439395"><img
26src="https://zenodo.org/badge/DOI/10.5281/zenodo.439395.svg" alt="DOI"></a>
27\endhtmlonly
28
29\subsection cell_local Local curl-free formulation
30
31This problem can be mathematically described by minimisation problem with the
32constraints, as follows
33\f[
34\left\{
35\begin{array}{l}
36\textrm{min}\,J(u,\rho) = \frac{1}{2} (u-u_d,S(u-u_d))_{S_u} +
37\frac{\epsilon_\rho}{2}(\rho,\rho)_{S_\rho} \\
38\textrm{div}[\sigma(u)] = 0 \quad \textrm{in}\,V \\
39n\cdot\sigma(u) = \rho \quad \textrm{on}\,S_\rho \\
40\end{array}
41\right.
42\f]
43Applying standard procedure, i.e. Lagrange multiplier method, we get
44\f[
45\left\{
46\begin{array}{l}
47\textrm{min}\,J(u,\rho,\Upsilon) =
48\frac{1}{2} (u,S(u-u_d))_{S_u} + \frac{\epsilon_\rho}{2}(\rho,\rho)_{S_\rho} +
49(\Upsilon,\textrm{div}[\sigma])_V \\ n\cdot\sigma = \rho \quad
50\textrm{on}\,S_\rho \end{array} \right. \f] and applying differentiation by
51parts \f[ J(u,\rho,\Upsilon) = \frac{1}{2} (u-u_d,S(u-u_d))_{S_u}
52+\frac{\epsilon_\rho}{2}(\rho,\rho)_{S_\rho}
53+(\textrm{grad}[\Upsilon],\sigma)_V - (\Upsilon,n\cdot\sigma)_{S_\rho}
54\f]
55and using second constraint, i.e. static constrain
56\f[
57J(u,\rho,\Upsilon) =
58\frac{1}{2} (u-u_d,S(u-u_d))_{S_u}
59+\frac{\epsilon_\rho}{2}(\rho,\rho)_{S_\rho}
60+(\textrm{grad}[\Upsilon],\sigma)_V - (\Upsilon,\rho)_{S_\rho}.
61\f]
62Note that force is enforced in week sense.
63
64Noting that
65\f[
66\sigma = \mathcal{A} \left( \textrm{grad}[u] \right)^{s}
67\f]
68and using symmetry of operator \f$\mathcal{A}\f$,
69\f[
70(\textrm{grad}[\Upsilon],\sigma)_V =
71(\textrm{grad}[\Upsilon],\mathcal{A} \textrm{grad}[u] )_V =
72(\mathcal{A}^{*}\textrm{grad}[\Upsilon],\textrm{grad}[u] )_V =
73(\Sigma,\textrm{grad}[u] )_V
74\f]
75we finally get
76\f[
77J(u,\rho,\Upsilon) =
78\frac{1}{2} (u-u_d,S(u-u_d))_{S_u}
79+\frac{\epsilon_\rho}{2}(\rho,\rho)_{S_\rho}
80+(\Sigma,\textrm{grad}[u])_V - (\Upsilon,\rho)_{S_\rho}
81\f]
82
83Calculating derivatives, we can get Euler equations in following form
84\f[
85\left\{
86\begin{array}{ll}
87(Su,\delta u)_{S_u} + (\Sigma,\textrm{grad}[\delta u])_V &= 0 \\
88(\sigma,\textrm{grad}[\delta \Upsilon])_V-(\rho,\delta \Upsilon)_{S_\rho} &= 0
89\\
90(\epsilon_\rho \rho,\delta \rho)_{S_\rho}-(\Upsilon,\delta \rho)_{S_\rho} &= 0
91\end{array}
92\right.
93\f]
94and applying finite element discretization, above equations are expressed
95by linear algebraic equations suitable for computer calculations
96\f[
97\left[
98\begin{array}{ccc}
99S & K_{u \Upsilon} & 0 \\
100K_{\Upsilon u} & 0 & -B^\textrm{T} \\
1010 & -B & D
102\end{array}
103\right]
104\left[
105\begin{array}{c}
106u \\ \Upsilon \\ \rho
107\end{array}
108\right]
109=
110\left[
111\begin{array}{c}
112S u_d \\ 0 \\ 0
113\end{array}
114\right]
115\f]
116and finally swapping first two rows, we finally get
117\f[
118\left[
119\begin{array}{ccc}
120K & 0 & -B^\textrm{T} \\
121S & K & 0 \\
1220 & -B & D
123\end{array}
124\right]
125\left[
126\begin{array}{c}
127u \\ \Upsilon \\ \rho
128\end{array}
129\right]
130=
131\left[
132\begin{array}{c}
1330 \\ S u_d \\ 0
134\end{array}
135\right]
136\f]
137where
138\f[
139S=\epsilon_u^{-1} I\\
140\epsilon_\rho^\textrm{abs} = \epsilon_\rho^\text{ref}\epsilon_u^{-1}
141\f]
142
143Displacement field is \f$\mathbf{u}\f$ and \f$\Upsilon\f$, force field on top
144surface is \f$\boldsymbol\rho\f$.
145
146We not yet explored nature of cell forces. Since the cells are attached to the
147body surface and anything else, the body as results those forces can not be
148subjected to rigid body motion.
149
150We assume that forces are generated by 2d objects, as results only tangential
151forces can be produced by those forces if the surface is planar. For non-planar
152surfaces addition force normal to the surface is present, although the magnitude
153of this force could be calculated purely from geometrical considerations, thus
154additional physical equations are not needed.
155
156Assuming that straight and very short pre-stressed fibres generate cell forces;
157a force field is curl-free. Utilizing that forces can be expressed by potential
158field as follows
159\f[
160\rho = \frac{\partial \Phi_\rho}{\partial \mathbf{x}}
161\f]
162where \f$\Phi\f$ is force potential field.
163
164 \subsubsection cell_local_approx Approximation
165
166For this problem \f$H^(\Omega)\f$ function space is required for \f$u\f$,
167\f$\Upsilon\f$ and \f$\rho\f$. Note that \f$\rho\f$ is given by derivative of
168potential field \f$\Phi\f$ which derivatives gives potential forces.
169
170 \subsection cell_nonlocal Nonlocal, i.e. weak curl-free
171
172In this variant generalization of the local model to a weakly enforced force
173curl-free cell force field is considered. This generalization is a consequence
174of the observation that cell has some small but finite size. Moreover, a cell
175has a complex pre-stressed structure which can transfer shear forces.
176
177We define model like before, however this time we add additional term,
178\f[
179 \left\{
180\begin{array}{l}
181\textrm{min}\,J(u,\rho) =
182\frac{1}{2} (u-u_d,S(u-u_d))_{S_u} +
183\frac{\epsilon_\rho}{2}(\rho,\rho-l^2\textrm{curl}^s
184[\textrm{curl}^s[\rho]])_{S_\rho} \\
185\textrm{div}[\sigma(u)] = 0 \quad \textrm{in}\,V \\
186n\cdot\sigma = \rho
187\end{array}
188\right.
189\f]
190and reformulating this we have
191\f[
192\left\{
193\begin{array}{l}
194\textrm{min}\,J(u,\rho) =
195\frac{1}{2} (u-u_d,S(u-u_d))_{S_u} + \frac{\epsilon_\rho}{2}(\rho,\rho)_{S_\rho}
196+\frac{\epsilon_l^{-1}}{2}(\textrm{curl}^s[\rho],\textrm{curl}^s[\rho])_{S_\rho}
197\\
198\textrm{div}[\sigma(u)] = 0 \quad \textrm{in}\,V \\
199n\cdot\sigma = \rho
200\end{array}
201\right.
202\f]
203where parameter \f$\epsilon_l\f$ controls curl-free term, if this parameter
204approach zero, this formulation converge to local variant presented above.
205
206Applying the same procedure like before, set of Euler equations is derived
207\f[
208\left\{
209\begin{array}{l}
210(Su,\delta u)_{S_u} + (\Sigma,\textrm{grad}[\delta u])_V= 0 \\
211(\sigma,\textrm{grad}[\delta \Upsilon])_V-(\rho,\delta \Upsilon)_{S_\rho} = 0 \\
212(\epsilon_\rho \rho,\delta
213\rho)_{S_\rho}+\epsilon_l^{-1}(\textrm{curl}^s[\rho],\textrm{curl}^s[\delta
214\rho])_{S_\rho}-(\Upsilon,\delta \rho)_{S_\rho} = 0 \end{array} \right. \f] That
215give following system of equations \f[ \left[ \begin{array}{ccc}
216S & K_{u \Upsilon} & 0 \\
217K_{\Upsilon u} & 0 & -B^\textrm{T} \\
2180 & -B & D
219\end{array}
220\right]
221\left[
222\begin{array}{c}
223u \\ \Upsilon \\ \rho
224\end{array}
225\right]
226=
227\left[
228\begin{array}{c}
229S u_d \\ 0 \\ 0
230\end{array}
231\right]
232\f]
233and swapping the first two rows we get
234\f[
235\left[
236\begin{array}{ccc}
237K & 0 & -B^\textrm{T} \\
238S & K & 0 \\
2390 & -B & D
240\end{array}
241\right]
242\left[
243\begin{array}{c}
244u \\ \Upsilon \\ \rho
245\end{array}
246\right]
247=
248\left[
249\begin{array}{c}
2500 \\ S u_d \\ 0
251\end{array}
252\right]
253\f]
254
255 \subsubsection cell_nonlocal_approx Approximation
256
257For this problem \f$H^(\Omega)\f$ function space is required for \f$u\f$,
258\f$\Upsilon\f$. Note that force field need to be in
259\f$H(\textrm{curl},S_\rho)\f$ space.
260
261\section cell_solution Field split pre-conditioner
262
263In this implementation, the block structure of the matrix is utilised. The \e
264PCFIELDSPLIT
265(see
266<http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/PC/PCFIELDSPLIT.html>)
267is utilised. Matrix is stored using nested matrix format \e MATNEST
268(see
269)<http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Mat/MatCreateNest.html>).
270
271The sub-netsetd matrix is created containing two upper-left blocks,
272\f[
273X = \left[
274\begin{array}{cc}
275K & 0 \\
276S & K
277\end{array}
278\right]
279\f]
280this netsed matrix is blocked in
281\f[
282A= \left[
283\begin{array}{cc}
284X & V \\
285H & D
286\end{array}
287\right]
288\f]
289where
290\f[
291V= \left[
292\begin{array}{c}
293-B^\textrm{T} \\
2940
295\end{array}
296\right]
297\f]
298and
299\f[
300H= \left[
301\begin{array}{cc}
3020 & -B^\textrm{T}
303\end{array}
304\right]
305\f]
306
307The system associated with X matrix is solved using \e PCFIELDSPLIT and
308multiplicative relaxation scheme. In following implementation sub-matrix, K is
309factorised only once. The system related to matrix \f$A\f$ composed form
310matrices \f$X,D,V,H\f$ is solved using Schur complement. Note that here we
311exploit MoFEM capability to create sub-problems in easy way.
312
313\section cell_running_code Running code
314
315Approximations of displacements
316\code
317./map_disp \
318-my_data_x ./examples/data_x.csv \
319-my_data_y ./examples/data_y.csv \
320-my_file ./examples/mesh_cell_force_map.cub \
321-ksp_type cg -pc_type lu -pc_factor_mat_solver_package mumps -ksp_monitor \
322-lambda 0.01 -my_order 3 -scale 0.05 -cube_size 1 -my_nparts 4
323\endcode
324
325If only one layer is specified, another thin polymer layer could be created
326automatically using prism elements,
327\code
328./map_disp_prism \
329-my_thinckness 0.01 \
330-my_data_x ./examples/data_x.csv \
331-my_data_y ./examples/data_y.csv \
332-my_file ./examples/mesh_for_prisms.cub \
333-ksp_type cg -pc_type lu -pc_factor_mat_solver_package mumps -ksp_monitor \
334-lambda 0.01 -my_order 3 -scale 0.05 -cube_size 1 -my_nparts 4
335\endcode
336
337Config file
338\include users_modules/cell_engineering/examples/block_config.in
339
340Calculating forces
341\code
342mpirun -np 4 ./cell_forces \
343-my_file analysis_mesh.h5m \
344-my_order 1 -my_order_force 2 -my_max_post_proc_ref_level 0 \
345-my_block_config ./examples/block_config.in \
346-ksp_type fgmres -ksp_monitor \
347-fieldsplit_1_ksp_type fgmres \
348-fieldsplit_1_pc_type lu \
349-fieldsplit_1_pc_factor_mat_solver_package mumps \
350-fieldsplit_1_ksp_max_it 100 \
351-fieldsplit_1_ksp_monitor \
352-fieldsplit_0_ksp_type gmres \
353-fieldsplit_0_ksp_max_it 25 \
354-fieldsplit_0_fieldsplit_0_ksp_type preonly \
355-fieldsplit_0_fieldsplit_0_pc_type lu \
356-fieldsplit_0_fieldsplit_0_pc_factor_mat_solver_package mumps \
357-fieldsplit_0_fieldsplit_1_ksp_type preonly \
358-fieldsplit_0_fieldsplit_1_pc_type lu \
359-fieldsplit_0_fieldsplit_1_pc_factor_mat_solver_package mumps \
360-ksp_atol 1e-6 -ksp_rtol 0 -my_eps_u 1e-4 -my_curl 1
361\endcode
362
363As results of above we get
364\image html cell_engineering_forces_example.gif "Example: results" width=600px
365
366\section cell_install Installation with docker
367
368- First install docker as per the instructions here:
369<https://docs.docker.com/installation/#installation>
370- Install cell user module: \e docker \e pull \e likask/cell_engineering
371
372\todo Improve documentation
373
374\todo Generalization to curved surfaces. That should not be difficult adding
375metric tensors and taking into account curvature.
376
377\todo Instead of elastic material we can use GEL model developed in other
378module. That will allow to take into account drying and other rheological
379effects.
380
381\todo For nonlinear material instead of KSP solver we can add SNES solver
382
383\todo Physical equations for cell mechanics could be added directly to minimized
384functional or by constrains.
385
386*/
387
388/**
389 \example cell_forces.cpp
390 Complete example for identifying cell forces from measured displacements.
391
392 See \ref cell_potential for the mathematical formulation, implementation
393 details, and command-line usage.
394*/
395
396/* Copyright (c) 2025 Authors under the MIT License.
397 * See LICENSE.md for details.
398 * SPDX-License-Identifier: MIT
399 */
400
401#include <MoFEM.hpp>
402using namespace MoFEM;
403#include <CellForces.hpp>
404
405constexpr int SPACE_DIM = 3;
407
408#include <HookeOps.hpp>
409
410static char help[] = "-my_block_config set block data\n"
411 "\n";
412
414
416 int oRder;
417 double yOung;
418 double pOisson;
419 BlockOptionData() : oRder(-1), yOung(-1), pOisson(-2) {}
420};
421
423 using VolumeElementForcesAndSourcesCore::VolumeElementForcesAndSourcesCore;
424 int getRule(int order) override { return 2 * order + 1; }
425};
426
427using ElasticBlockMap = std::map<int, Range>;
428
431
432 OpElasticEnergy(boost::shared_ptr<MatrixDouble> strain_ptr,
433 boost::shared_ptr<MatrixDouble> stress_ptr, double &energy)
435 NOSPACE, UserDataOperator::OPSPACE),
436 strainPtr(strain_ptr), stressPtr(stress_ptr), energy(energy) {}
437
438 MoFEMErrorCode doWork(int, EntityType,
439 EntitiesFieldData::EntData &) override {
441
442 const size_t nb_gauss_pts = getGaussPts().size2();
444 auto get_strain =
446 DL>::get(*strainPtr, nb_gauss_pts);
447 auto get_stress =
449 DL>::get(*stressPtr, nb_gauss_pts);
450 auto t_strain = get_strain();
451 auto t_stress = get_stress();
454
455 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
456 const double alpha = getMeasure() * getGaussPts()(SPACE_DIM, gg);
457 energy += 0.5 * alpha * t_strain(i, j) * t_stress(i, j);
458 ++t_strain;
459 ++t_stress;
460 }
461
463 }
464
465private:
466 boost::shared_ptr<MatrixDouble> strainPtr;
467 boost::shared_ptr<MatrixDouble> stressPtr;
468 double &energy;
469};
470
471} // namespace CellEngineering
472
473using namespace boost::numeric;
474using namespace CellEngineering;
475
476#include <boost/program_options.hpp>
477using namespace std;
478namespace po = boost::program_options;
479
480static int debug = 0;
481
482int main(int argc, char *argv[]) {
483
484 MoFEM::Core::Initialize(&argc, &argv, (char *)0, help);
485
486 try {
487
488 moab::Core mb_instance;
489 moab::Interface &moab = mb_instance;
490
491 PetscBool flg_block_config, flg_file;
492 char mesh_file_name[255];
493 char block_config_file[255];
494 PetscBool flg_order_force;
495 PetscInt order = 2;
496 PetscInt order_force = 2;
497 PetscBool flg_eps_u, flg_eps_rho, flg_eps_l;
498 double eps_u = 1e-6;
499 double eps_rho = 1e-3;
500 double eps_l = 0;
501 PetscBool is_curl = PETSC_TRUE;
502 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Elastic Config", "none");
503 CHKERR PetscOptionsString("-my_file", "mesh file name", "", "mesh.h5m",
504 mesh_file_name, 255, &flg_file);
505 CHKERR PetscOptionsInt("-my_order", "default approximation order", "",
506 order, &order, PETSC_NULLPTR);
507 CHKERR PetscOptionsInt(
508 "-my_order_force",
509 "default approximation order for force approximation", "", order_force,
510 &order_force, &flg_order_force);
511 CHKERR PetscOptionsString("-my_block_config", "elastic configure file name",
512 "", "block_conf.in", block_config_file, 255,
513 &flg_block_config);
514 CHKERR PetscOptionsReal("-my_eps_rho", "foce optimality parameter ", "",
515 eps_rho, &eps_rho, &flg_eps_rho);
516 CHKERR PetscOptionsReal("-my_eps_u", "displacement optimality parameter ",
517 "", eps_u, &eps_u, &flg_eps_u);
518 CHKERR PetscOptionsReal("-my_eps_l", "displacement optimality parameter ",
519 "", eps_l, &eps_l, &flg_eps_l);
520 CHKERR PetscOptionsBool("-my_curl", "use Hcurl space to approximate forces",
521 "", is_curl, &is_curl, PETSC_NULLPTR);
522 PetscOptionsEnd();
523
524 // Reade parameters from line command
525 if (flg_file != PETSC_TRUE) {
526 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA,
527 "*** ERROR -my_file (MESH FILE NEEDED)");
528 }
529
530 ParallelComm *pcomm = ParallelComm::get_pcomm(&moab, MYPCOMM_INDEX);
531 if (pcomm == nullptr)
532 pcomm = new ParallelComm(&moab, PETSC_COMM_WORLD);
533
534 // Read mesh to MOAB
535 const char *option;
536 option = "PARALLEL=READ_PART;"
537 "PARALLEL_RESOLVE_SHARED_ENTS;"
538 "PARTITION=PARALLEL_PARTITION;";
539 // option = "";
540 CHKERR moab.load_file(mesh_file_name, 0, option);
541
542 // Create MoFEM (Joseph) database
543 MoFEM::Core core(moab);
544 MoFEM::Interface &m_field = core;
545
546 auto mmanager_ptr = m_field.getInterface<MeshsetsManager>();
547 auto comm_interface_ptr = m_field.getInterface<CommInterface>();
548 // print bcs
549 CHKERR mmanager_ptr->printDisplacementSet();
550 CHKERR mmanager_ptr->printForceSet();
551 // print block sets with materials
552 CHKERR mmanager_ptr->printMaterialsSet();
553
554 // stl::bitset see for more details
555 BitRefLevel bit_level0;
556 bit_level0.set(0);
557 {
558 Range ents3d;
559 CHKERR moab.get_entities_by_dimension(0, 3, ents3d);
560 CHKERR m_field.getInterface<BitRefManager>()->setBitRefLevel(
561 ents3d, bit_level0, false);
562 }
563
564 // set app. order
565
566 std::vector<Range> setOrderToEnts(10);
567
568 // configure blocks by parsing config file
569 // it allow to set approximation order for each block independently
570 Range set_order_ents;
571 std::map<int, BlockOptionData> block_data;
572 if (flg_block_config) {
573 double read_eps_u, read_eps_rho, read_eps_l;
574 try {
575 ifstream ini_file(block_config_file);
576 if (!ini_file.is_open()) {
577 SETERRQ(PETSC_COMM_SELF, 1,
578 "*** -my_block_config does not exist ***");
579 }
580 // std::cerr << block_config_file << std::endl;
581 po::variables_map vm;
582 po::options_description config_file_options;
583 config_file_options.add_options()(
584 "eps_u", po::value<double>(&read_eps_u)->default_value(-1))(
585 "eps_rho", po::value<double>(&read_eps_rho)->default_value(-1))(
586 "eps_l", po::value<double>(&read_eps_l)->default_value(-1));
588 std::ostringstream str_order;
589 str_order << "block_" << it->getMeshsetId() << ".displacement_order";
590 config_file_options.add_options()(
591 str_order.str().c_str(),
592 po::value<int>(&block_data[it->getMeshsetId()].oRder)
593 ->default_value(order));
594 std::ostringstream str_cond;
595 str_cond << "block_" << it->getMeshsetId() << ".young_modulus";
596 config_file_options.add_options()(
597 str_cond.str().c_str(),
598 po::value<double>(&block_data[it->getMeshsetId()].yOung)
599 ->default_value(-1));
600 std::ostringstream str_capa;
601 str_capa << "block_" << it->getMeshsetId() << ".poisson_ratio";
602 config_file_options.add_options()(
603 str_capa.str().c_str(),
604 po::value<double>(&block_data[it->getMeshsetId()].pOisson)
605 ->default_value(-2));
606 }
607 po::parsed_options parsed =
608 parse_config_file(ini_file, config_file_options, true);
609 store(parsed, vm);
610 po::notify(vm);
612 if (block_data[it->getMeshsetId()].oRder == -1)
613 continue;
614 if (block_data[it->getMeshsetId()].oRder == order)
615 continue;
616 PetscPrintf(PETSC_COMM_WORLD, "Set block %d order to %d\n",
617 it->getMeshsetId(), block_data[it->getMeshsetId()].oRder);
618 Range block_ents;
619 CHKERR moab.get_entities_by_handle(it->getMeshset(), block_ents,
620 true);
621 // block_ents = block_ents.subset_by_type(MBTET);
622 Range nodes;
623 CHKERR moab.get_connectivity(block_ents, nodes, true);
624 Range ents_to_set_order, ents3d;
625 CHKERR moab.get_adjacencies(nodes, 3, false, ents3d,
626 moab::Interface::UNION);
627 CHKERR moab.get_adjacencies(ents3d, 2, false, ents_to_set_order,
628 moab::Interface::UNION);
629 CHKERR moab.get_adjacencies(ents3d, 1, false, ents_to_set_order,
630 moab::Interface::UNION);
631 ents_to_set_order = subtract(
632 ents_to_set_order, ents_to_set_order.subset_by_type(MBQUAD));
633 ents_to_set_order = subtract(
634 ents_to_set_order, ents_to_set_order.subset_by_type(MBPRISM));
635 set_order_ents.merge(ents3d);
636 set_order_ents.merge(ents_to_set_order);
637 setOrderToEnts[block_data[it->getMeshsetId()].oRder].merge(
638 set_order_ents);
639 }
640 CHKERR comm_interface_ptr->synchroniseEntities(set_order_ents, 0);
641 std::vector<std::string> additional_parameters;
642 additional_parameters =
643 collect_unrecognized(parsed.options, po::include_positional);
644 for (std::vector<std::string>::iterator vit =
645 additional_parameters.begin();
646 vit != additional_parameters.end(); vit++) {
647 CHKERR PetscPrintf(PETSC_COMM_WORLD,
648 "** WARNING Unrecognized option %s\n",
649 vit->c_str());
650 }
651 } catch (const std::exception &ex) {
652 std::ostringstream ss;
653 ss << ex.what() << std::endl;
654 SETERRQ(PETSC_COMM_SELF, MOFEM_STD_EXCEPTION_THROW, ss.str().c_str());
655 }
656 if (read_eps_u > 0) {
657 eps_u = read_eps_u;
658 };
659 if (read_eps_rho > 0) {
660 eps_rho = read_eps_rho;
661 }
662 if (read_eps_l > 0) {
663 eps_l = read_eps_l;
664 }
665 }
666
667 PetscPrintf(PETSC_COMM_WORLD, "epsU = %6.4e epsRho = %6.4e\n", eps_u,
668 eps_rho);
669
670 // Fields
671 CHKERR m_field.add_field("U", H1, AINSWORTH_LEGENDRE_BASE, 3, MB_TAG_SPARSE,
672 MF_ZERO);
673 CHKERR m_field.add_field("UPSILON", H1, AINSWORTH_LEGENDRE_BASE, 3,
674 MB_TAG_SPARSE, MF_ZERO);
675 if (is_curl) {
676 CHKERR m_field.add_field("RHO", HCURL, AINSWORTH_LEGENDRE_BASE, 1);
677 } else {
678 CHKERR m_field.add_field("RHO", H1, AINSWORTH_LEGENDRE_BASE, 1);
679 }
680
681 // add entitities (by tets) to the field
682 CHKERR m_field.add_ents_to_field_by_type(0, MBTET, "U");
683 CHKERR m_field.add_ents_to_field_by_type(0, MBTET, "UPSILON");
684 CHKERR m_field.add_ents_to_field_by_type(0, MBPRISM, "U");
685 CHKERR m_field.add_ents_to_field_by_type(0, MBPRISM, "UPSILON");
686
687 CHKERR comm_interface_ptr->synchroniseFieldEntities("U");
688 CHKERR comm_interface_ptr->synchroniseFieldEntities("UPSILON");
689 CHKERR comm_interface_ptr->synchroniseFieldEntities("RHO");
690
691 Range vertex_to_fix;
692 Range edges_to_fix;
693 Range ents_1st_layer;
694 // If problem is partitioned meshset culd not exist on this part
695 if (mmanager_ptr->checkMeshset(202, SIDESET)) {
696 CHKERR mmanager_ptr->getEntitiesByDimension(202, SIDESET, 2,
697 ents_1st_layer, true);
698 CHKERR mmanager_ptr->getEntitiesByDimension(202, SIDESET, 0,
699 vertex_to_fix, false);
700 CHKERR mmanager_ptr->getEntitiesByDimension(202, SIDESET, 1, edges_to_fix,
701 false);
702 if (vertex_to_fix.size() != 1 && !vertex_to_fix.empty()) {
703 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
704 "Should be one vertex only, but is %zu", vertex_to_fix.size());
705 }
706 }
707 CHKERR comm_interface_ptr->synchroniseEntities(ents_1st_layer, 0);
709 ents_1st_layer.subset_by_type(MBTRI), MBTRI, "RHO");
710 Range ents_2nd_layer;
711 // If problem is partitioned meshset culd not exist on this part
712 if (mmanager_ptr->checkMeshset(101, SIDESET)) {
713 CHKERR mmanager_ptr->getEntitiesByDimension(101, SIDESET, 2,
714 ents_2nd_layer, true);
715 }
716 CHKERR comm_interface_ptr->synchroniseEntities(ents_2nd_layer, 0);
717
718 for (int oo = 2; oo != setOrderToEnts.size(); oo++) {
719 if (setOrderToEnts[oo].size() > 0) {
720 CHKERR comm_interface_ptr->synchroniseEntities(setOrderToEnts[oo], 0);
721 CHKERR m_field.set_field_order(setOrderToEnts[oo], "U", oo);
722 CHKERR m_field.set_field_order(setOrderToEnts[oo], "UPSILON", oo);
723 }
724 }
725
726 const int through_thickness_order = 2;
727 {
728 Range ents3d;
729 CHKERR moab.get_entities_by_dimension(0, 3, ents3d);
730 Range ents;
731 CHKERR moab.get_adjacencies(ents3d, 2, false, ents,
732 moab::Interface::UNION);
733 CHKERR moab.get_adjacencies(ents3d, 1, false, ents,
734 moab::Interface::UNION);
735
736 Range prisms;
737 CHKERR moab.get_entities_by_type(0, MBPRISM, prisms);
738 {
739 Range quads;
740 CHKERR moab.get_adjacencies(prisms, 2, false, quads,
741 moab::Interface::UNION);
742 Range prism_tris;
743 prism_tris = quads.subset_by_type(MBTRI);
744 quads = subtract(quads, prism_tris);
745 Range quads_edges;
746 CHKERR moab.get_adjacencies(quads, 1, false, quads_edges,
747 moab::Interface::UNION);
748 Range prism_tris_edges;
749 CHKERR moab.get_adjacencies(prism_tris, 1, false, prism_tris_edges,
750 moab::Interface::UNION);
751 quads_edges = subtract(quads_edges, prism_tris_edges);
752 prisms.merge(quads);
753 prisms.merge(quads_edges);
754 }
755
756 ents.merge(ents3d);
757 ents = subtract(ents, set_order_ents);
758 ents = subtract(ents, prisms);
759
760 CHKERR comm_interface_ptr->synchroniseEntities(ents, 0);
761 CHKERR comm_interface_ptr->synchroniseEntities(prisms, 0);
762
763 CHKERR m_field.set_field_order(ents, "U", order);
764 CHKERR m_field.set_field_order(ents, "UPSILON", order);
765 // approx. order through thickness to 2
766 CHKERR m_field.set_field_order(prisms, "U", through_thickness_order);
767 CHKERR m_field.set_field_order(prisms, "UPSILON",
768 through_thickness_order);
769 }
770 CHKERR m_field.set_field_order(0, MBVERTEX, "U", 1);
771 CHKERR m_field.set_field_order(0, MBVERTEX, "UPSILON", 1);
772
773 if (is_curl) {
774 CHKERR m_field.set_field_order(0, MBTRI, "RHO", order_force);
775 CHKERR m_field.set_field_order(0, MBEDGE, "RHO", order_force);
776 } else {
777 CHKERR m_field.set_field_order(0, MBTRI, "RHO", order_force);
778 CHKERR m_field.set_field_order(0, MBEDGE, "RHO", order_force);
779 CHKERR m_field.set_field_order(0, MBVERTEX, "RHO", 1);
780 }
781
782 // The vec-0 Hooke operators read material data directly from
783 // MAT_ELASTIC* meshsets.
784 ElasticBlockMap elastic_blocks;
785 int default_block_id = -1;
786 Tag block_id_tag;
787 CHKERR moab.tag_get_handle("BLOCK_ID", 1, MB_TYPE_INTEGER, block_id_tag,
788 MB_TAG_CREAT | MB_TAG_SPARSE, &default_block_id);
790 m_field, BLOCKSET | MAT_ELASTICSET, it)) {
791 Mat_Elastic material;
792 CHKERR it->getAttributeDataStructure(material);
793 const int block_id = it->getMeshsetId();
794 CHKERR moab.get_entities_by_handle(it->getMeshset(),
795 elastic_blocks[block_id], true);
796 const auto block_elements =
797 elastic_blocks[block_id].subset_by_type(MBTET);
798 CHKERR moab.tag_clear_data(block_id_tag, block_elements, &block_id);
799
800 const auto options_it = block_data.find(block_id);
801 if (options_it != block_data.end() && options_it->second.yOung > 0) {
802 material.data.Young = options_it->second.yOung;
803 CHKERR PetscPrintf(PETSC_COMM_WORLD,
804 "Block %d set Young modulus %3.4g\n", block_id,
805 material.data.Young);
806 }
807 if (options_it != block_data.end() && options_it->second.pOisson >= -1) {
808 material.data.Poisson = options_it->second.pOisson;
809 CHKERR PetscPrintf(PETSC_COMM_WORLD,
810 "Block %d set Poisson ratio %3.4g\n", block_id,
811 material.data.Poisson);
812 }
813 CHKERR mmanager_ptr->setAttributesByDataStructure(BLOCKSET, block_id,
814 material);
815 }
816
817 CHKERR m_field.add_finite_element("ELASTIC", MF_ZERO);
818 CHKERR m_field.modify_finite_element_add_field_row("ELASTIC", "U");
819 CHKERR m_field.modify_finite_element_add_field_col("ELASTIC", "U");
820 CHKERR m_field.modify_finite_element_add_field_data("ELASTIC", "U");
821 for (const auto &[id, entities] : elastic_blocks)
822 CHKERR m_field.add_ents_to_finite_element_by_type(entities, MBTET,
823 "ELASTIC");
824
825 ElasticVolume elastic_rhs(m_field);
826 ElasticVolume elastic_lhs(m_field);
827 ElasticVolume elastic_energy_fe(m_field);
828 double elastic_energy = 0;
829 auto elastic_rhs_common =
830 HookeOps::commonDataFactory<SPACE_DIM, GAUSS, DomainEleOp>(
831 m_field, elastic_rhs.getOpPtrVector(), "U", "MAT_ELASTIC",
832 Sev::verbose);
833 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, PETSC, GAUSS, DomainEleOp>(
834 m_field, elastic_rhs.getOpPtrVector(), "U", elastic_rhs_common,
835 Sev::verbose, true);
836 auto elastic_lhs_common =
837 HookeOps::commonDataFactory<SPACE_DIM, GAUSS, DomainEleOp>(
838 m_field, elastic_lhs.getOpPtrVector(), "U", "MAT_ELASTIC",
839 Sev::verbose);
840 CHKERR HookeOps::opFactoryDomainLhs<SPACE_DIM, PETSC, GAUSS, DomainEleOp>(
841 m_field, elastic_lhs.getOpPtrVector(), "U", elastic_lhs_common,
842 Sev::verbose);
843 auto elastic_energy_common =
844 HookeOps::commonDataFactory<SPACE_DIM, GAUSS, DomainEleOp>(
845 m_field, elastic_energy_fe.getOpPtrVector(), "U", "MAT_ELASTIC",
846 Sev::verbose);
847 elastic_energy_fe.getOpPtrVector().push_back(new OpElasticEnergy(
848 elastic_energy_common->getMatStrain(),
849 elastic_energy_common->getMatCauchyStress(), elastic_energy));
850
851 // Add prisms
852 CellEngineering::FatPrism fat_prism_rhs(m_field);
853 CellEngineering::FatPrism fat_prism_lhs(m_field);
854 {
855 CHKERR m_field.add_finite_element("ELASTIC_PRISM", MF_ZERO);
856 CHKERR m_field.modify_finite_element_add_field_row("ELASTIC_PRISM", "U");
857 CHKERR m_field.modify_finite_element_add_field_col("ELASTIC_PRISM", "U");
858 CHKERR m_field.modify_finite_element_add_field_data("ELASTIC_PRISM", "U");
859 auto block_it = elastic_blocks.find(2);
860 if (block_it == elastic_blocks.end()) {
861 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
862 "Elastic material block 2 is required for prism elements");
863 }
864 CHKERR mmanager_ptr->getEntitiesByDimension(2, BLOCKSET, 3,
865 block_it->second);
867 block_it->second, MBPRISM, "ELASTIC_PRISM");
868 // right hand side operators
869 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
870 fat_prism_rhs.getOpPtrVector().push_back(
871 new MoFEM::OpCalculateInvJacForFatPrism(inv_jac_ptr));
872 fat_prism_rhs.getOpPtrVector().push_back(
873 new MoFEM::OpSetInvJacH1ForFatPrism(inv_jac_ptr));
875 auto prism_rhs_common =
876 HookeOps::commonDataFactory<SPACE_DIM, GAUSS, FatPrismOp>(
877 m_field, fat_prism_rhs.getOpPtrVector(), "U", "MAT_ELASTIC",
878 Sev::verbose);
879 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, PETSC, GAUSS, FatPrismOp>(
880 m_field, fat_prism_rhs.getOpPtrVector(), "U", prism_rhs_common,
881 Sev::verbose, true);
882 // Left hand side operators
883 fat_prism_lhs.getOpPtrVector().push_back(
884 new MoFEM::OpCalculateInvJacForFatPrism(inv_jac_ptr));
885 fat_prism_lhs.getOpPtrVector().push_back(
886 new MoFEM::OpSetInvJacH1ForFatPrism(inv_jac_ptr));
887 auto prism_lhs_common =
888 HookeOps::commonDataFactory<SPACE_DIM, GAUSS, FatPrismOp>(
889 m_field, fat_prism_lhs.getOpPtrVector(), "U", "MAT_ELASTIC",
890 Sev::verbose);
891 CHKERR HookeOps::opFactoryDomainLhs<SPACE_DIM, PETSC, GAUSS, FatPrismOp>(
892 m_field, fat_prism_lhs.getOpPtrVector(), "U", prism_lhs_common,
893 Sev::verbose);
894 }
895
896 // build field
897 CHKERR m_field.build_fields();
898
899 // Control elements
900 CHKERR m_field.add_finite_element("KUPSUPS");
901 CHKERR m_field.modify_finite_element_add_field_row("KUPSUPS", "UPSILON");
902 CHKERR m_field.modify_finite_element_add_field_col("KUPSUPS", "UPSILON");
903 CHKERR m_field.modify_finite_element_add_field_data("KUPSUPS", "UPSILON");
904 CHKERR m_field.add_ents_to_finite_element_by_type(0, MBTET, "KUPSUPS");
905 CHKERR m_field.add_ents_to_finite_element_by_type(0, MBPRISM, "KUPSUPS");
906
907 CHKERR m_field.add_finite_element("DISPLACEMENTS_PENALTY");
908 CHKERR m_field.modify_finite_element_add_field_row("DISPLACEMENTS_PENALTY",
909 "UPSILON");
910 CHKERR m_field.modify_finite_element_add_field_col("DISPLACEMENTS_PENALTY",
911 "U");
912 CHKERR m_field.modify_finite_element_add_field_data("DISPLACEMENTS_PENALTY",
913 "UPSILON");
914 CHKERR m_field.modify_finite_element_add_field_data("DISPLACEMENTS_PENALTY",
915 "U");
916 CHKERR m_field.modify_finite_element_add_field_data("DISPLACEMENTS_PENALTY",
917 "DISP_X");
918 CHKERR m_field.modify_finite_element_add_field_data("DISPLACEMENTS_PENALTY",
919 "DISP_Y");
920 CHKERR m_field.add_ents_to_finite_element_by_type(ents_2nd_layer, MBTRI,
921 "DISPLACEMENTS_PENALTY");
922
923 // Add element to calculate residual on 1st layer
924 CHKERR m_field.add_finite_element("BT");
926 CHKERR m_field.modify_finite_element_add_field_row("BT", "UPSILON");
927 CHKERR m_field.modify_finite_element_add_field_col("BT", "RHO");
929 CHKERR m_field.modify_finite_element_add_field_data("BT", "UPSILON");
930 CHKERR m_field.modify_finite_element_add_field_data("BT", "RHO");
931 CHKERR m_field.add_ents_to_finite_element_by_type(ents_1st_layer, MBTRI,
932 "BT");
933
934 CHKERR m_field.add_finite_element("B");
937 CHKERR m_field.modify_finite_element_add_field_col("B", "UPSILON");
939 CHKERR m_field.modify_finite_element_add_field_data("B", "UPSILON");
941 CHKERR m_field.add_ents_to_finite_element_by_type(ents_1st_layer, MBTRI,
942 "B");
943
944 // Add element to calculate residual on 1st layer
945 CHKERR m_field.add_finite_element("D");
949 CHKERR m_field.add_ents_to_finite_element_by_type(ents_1st_layer, MBTRI,
950 "D");
951
952 // build finite elemnts
954 // build adjacencies
955 CHKERR m_field.build_adjacencies(bit_level0);
956
957 // Register MOFEM DM
958 DMType dm_name = "MOFEM";
959 CHKERR DMRegister_MoFEM(dm_name);
960
961 DM dm_control;
962 {
963 // Craete dm_control instance
964 CHKERR DMCreate(PETSC_COMM_WORLD, &dm_control);
965 CHKERR DMSetType(dm_control, dm_name);
966 // set dm_control data structure which created mofem datastructures
967 CHKERR DMMoFEMCreateMoFEM(dm_control, &m_field, "CONTROL_PROB",
968 bit_level0);
969 CHKERR DMSetFromOptions(dm_control);
970 CHKERR DMMoFEMSetSquareProblem(dm_control, PETSC_TRUE);
971 CHKERR DMMoFEMSetIsPartitioned(dm_control, PETSC_TRUE);
972 // add elements to dm_control
973 CHKERR DMMoFEMAddElement(dm_control, "ELASTIC");
974 CHKERR DMMoFEMAddElement(dm_control, "ELASTIC_PRISM");
975 CHKERR DMMoFEMAddElement(dm_control, "KUPSUPS");
976 CHKERR DMMoFEMAddElement(dm_control, "DISPLACEMENTS_PENALTY");
977 CHKERR DMMoFEMAddElement(dm_control, "B");
978 CHKERR DMMoFEMAddElement(dm_control, "BT");
979 CHKERR DMMoFEMAddElement(dm_control, "D");
980 CHKERR DMSetUp(dm_control);
981 }
982
983 CellEngineering::CommonData common_data;
984
985 ublas::matrix<Mat> nested_matrices(2, 2);
986 ublas::vector<IS> nested_is_rows(2);
987 ublas::vector<IS> nested_is_cols(2);
988 for (int i = 0; i != 2; i++) {
989 nested_is_rows[i] = PETSC_NULLPTR;
990 nested_is_cols[i] = PETSC_NULLPTR;
991 for (int j = 0; j != 2; j++) {
992 nested_matrices(i, j) = PETSC_NULLPTR;
993 }
994 }
995
996 ublas::matrix<Mat> sub_nested_matrices(2, 2);
997 ublas::vector<IS> sub_nested_is_rows(2);
998 ublas::vector<IS> sub_nested_is_cols(2);
999 for (int i = 0; i != 2; i++) {
1000 sub_nested_is_rows[i] = PETSC_NULLPTR;
1001 sub_nested_is_cols[i] = PETSC_NULLPTR;
1002 for (int j = 0; j != 2; j++) {
1003 sub_nested_matrices(i, j) = PETSC_NULLPTR;
1004 }
1005 }
1006
1007 DM dm_sub_volume_control;
1008 {
1009 CHKERR DMCreate(PETSC_COMM_WORLD, &dm_sub_volume_control);
1010 CHKERR DMSetType(dm_sub_volume_control, dm_name);
1011 // set dm_sub_volume_control data structure which created mofem data
1012 // structures
1013 CHKERR DMMoFEMCreateSubDM(dm_sub_volume_control, dm_control,
1014 "SUB_CONTROL_PROB");
1015 CHKERR DMMoFEMSetSquareProblem(dm_sub_volume_control, PETSC_TRUE);
1016 CHKERR DMMoFEMAddSubFieldRow(dm_sub_volume_control, "U");
1017 CHKERR DMMoFEMAddSubFieldRow(dm_sub_volume_control, "UPSILON");
1018 CHKERR DMMoFEMAddSubFieldCol(dm_sub_volume_control, "U");
1019 CHKERR DMMoFEMAddSubFieldCol(dm_sub_volume_control, "UPSILON");
1020 // add elements to dm_sub_volume_control
1021 CHKERR DMSetUp(dm_sub_volume_control);
1022
1023 const Problem *prb_ptr;
1024 CHKERR m_field.get_problem("SUB_CONTROL_PROB", &prb_ptr);
1025 boost::shared_ptr<Problem::SubProblemData> sub_data =
1026 prb_ptr->getSubData();
1027
1028 CHKERR sub_data->getRowIs(&nested_is_rows[0]);
1029 CHKERR sub_data->getColIs(&nested_is_cols[0]);
1030 // That will be filled at the end
1031 nested_matrices(0, 0) = PETSC_NULLPTR;
1032 }
1033
1034 {
1035 DM dm_sub_sub_elastic;
1036
1037 CHKERR DMCreate(PETSC_COMM_WORLD, &dm_sub_sub_elastic);
1038 CHKERR DMSetType(dm_sub_sub_elastic, dm_name);
1039 // set dm_sub_sub_elastic data structure which created mofem data
1040 // structures
1041 CHKERR DMMoFEMCreateSubDM(dm_sub_sub_elastic, dm_sub_volume_control,
1042 "ELASTIC_PROB");
1043 CHKERR DMMoFEMSetSquareProblem(dm_sub_sub_elastic, PETSC_TRUE);
1044 CHKERR DMMoFEMAddElement(dm_sub_sub_elastic, "ELASTIC");
1045 CHKERR DMMoFEMAddElement(dm_sub_sub_elastic, "ELASTIC_PRISM");
1046 CHKERR DMMoFEMAddSubFieldRow(dm_sub_sub_elastic, "U");
1047 CHKERR DMMoFEMAddSubFieldCol(dm_sub_sub_elastic, "U");
1048 // add elements to dm_sub_sub_elastic
1049 CHKERR DMSetUp(dm_sub_sub_elastic);
1050 CHKERR m_field.getInterface<BcManager>()
1051 ->pushMarkDOFsOnEntities<DisplacementCubitBcData>("ELASTIC_PROB",
1052 "U");
1053
1054 Mat Kuu;
1055 Vec Du, Fu;
1056 CHKERR DMCreateMatrix(dm_sub_sub_elastic, &Kuu);
1057 CHKERR DMCreateGlobalVector(dm_sub_sub_elastic, &Du);
1058 CHKERR DMCreateGlobalVector(dm_sub_sub_elastic, &Fu);
1059 CHKERR MatZeroEntries(Kuu);
1060 CHKERR VecZeroEntries(Du);
1061 CHKERR VecZeroEntries(Fu);
1062 CHKERR DMoFEMMeshToLocalVector(dm_sub_sub_elastic, Du, INSERT_VALUES,
1063 SCATTER_REVERSE);
1064
1065 // Apply displacement constraints with the current core BC machinery.
1066 auto dirichlet_bc_ptr = boost::make_shared<FEMethod>();
1067 dirichlet_bc_ptr->vecAssembleSwitch =
1068 boost::movelib::make_unique<bool>(false);
1069 dirichlet_bc_ptr->matAssembleSwitch =
1070 boost::movelib::make_unique<bool>(false);
1071 dirichlet_bc_ptr->preProcessHook =
1073 m_field, dirichlet_bc_ptr,
1074 std::vector<boost::shared_ptr<ScalingMethod>>{}, false);
1075 dirichlet_bc_ptr->postProcessHook = [&]() {
1077 CHKERR VecGhostUpdateBegin(Fu, ADD_VALUES, SCATTER_REVERSE);
1078 CHKERR VecGhostUpdateEnd(Fu, ADD_VALUES, SCATTER_REVERSE);
1079 CHKERR VecAssemblyBegin(Fu);
1080 CHKERR VecAssemblyEnd(Fu);
1081 CHKERR MatAssemblyBegin(Kuu, MAT_FINAL_ASSEMBLY);
1082 CHKERR MatAssemblyEnd(Kuu, MAT_FINAL_ASSEMBLY);
1084 m_field, dirichlet_bc_ptr, 0., SmartPetscObj<Vec>(Fu, true))();
1086 m_field, dirichlet_bc_ptr, 1., SmartPetscObj<Mat>(Kuu, true))();
1088 };
1089 dirichlet_bc_ptr->snes_ctx = FEMethod::CTX_SNESNONE;
1090 dirichlet_bc_ptr->ts_ctx = FEMethod::CTX_TSNONE;
1091 // preproc
1092 CHKERR DMoFEMPreProcessFiniteElements(dm_sub_sub_elastic,
1093 dirichlet_bc_ptr.get());
1094 CHKERR DMoFEMMeshToLocalVector(dm_sub_sub_elastic, Du, INSERT_VALUES,
1095 SCATTER_REVERSE);
1096 // internal force vector (to take into account Dirichlet boundary
1097 // conditions)
1098 elastic_rhs.snes_f = Fu;
1099 fat_prism_rhs.snes_f = Fu;
1100 CHKERR DMoFEMLoopFiniteElements(dm_sub_sub_elastic, "ELASTIC",
1101 &elastic_rhs);
1102 CHKERR DMoFEMLoopFiniteElements(dm_sub_sub_elastic, "ELASTIC_PRISM",
1103 &fat_prism_rhs);
1104 // elastic element matrix
1105 elastic_lhs.snes_B = Kuu;
1106 fat_prism_lhs.snes_B = Kuu;
1107 CHKERR DMoFEMLoopFiniteElements(dm_sub_sub_elastic, "ELASTIC",
1108 &elastic_lhs);
1109 CHKERR DMoFEMLoopFiniteElements(dm_sub_sub_elastic, "ELASTIC_PRISM",
1110 &fat_prism_lhs);
1111 // postproc
1112 CHKERR DMoFEMPostProcessFiniteElements(dm_sub_sub_elastic,
1113 dirichlet_bc_ptr.get());
1114 CHKERR VecGhostUpdateBegin(Fu, ADD_VALUES, SCATTER_REVERSE);
1115 CHKERR VecGhostUpdateEnd(Fu, ADD_VALUES, SCATTER_REVERSE);
1116 CHKERR VecAssemblyBegin(Fu);
1117 CHKERR VecAssemblyEnd(Fu);
1118 CHKERR VecScale(Fu, -1);
1119 CHKERR VecDestroy(&Du);
1120 CHKERR VecDestroy(&Fu);
1121
1122 const Problem *prb_ptr;
1123 CHKERR m_field.get_problem("ELASTIC_PROB", &prb_ptr);
1124 boost::shared_ptr<Problem::SubProblemData> sub_data =
1125 prb_ptr->getSubData();
1126
1127 CHKERR sub_data->getRowIs(&sub_nested_is_rows[0]);
1128 CHKERR sub_data->getColIs(&sub_nested_is_cols[0]);
1129 sub_nested_matrices(0, 0) = Kuu;
1130 IS isUpsilon;
1131 CHKERR m_field.getInterface<ISManager>()
1132 ->isCreateFromProblemFieldToOtherProblemField(
1133 "ELASTIC_PROB", "U", ROW, "SUB_CONTROL_PROB", "UPSILON", ROW,
1134 PETSC_NULLPTR, &isUpsilon);
1135 sub_nested_is_rows[1] = isUpsilon;
1136 sub_nested_is_cols[1] = isUpsilon;
1137 sub_nested_matrices(1, 1) = Kuu;
1138 PetscObjectReference((PetscObject)Kuu);
1139 PetscObjectReference((PetscObject)isUpsilon);
1140
1141 // Matrix View
1142 if (debug) {
1143 cerr << "Kuu" << endl;
1144 MatView(Kuu, PETSC_VIEWER_DRAW_WORLD);
1145 std::string wait;
1146 std::cin >> wait;
1147 }
1148
1149 CHKERR DMDestroy(&dm_sub_sub_elastic);
1150 }
1151
1152 {
1153 DM dm_sub_disp_penalty;
1154
1155 // Craete dm_control instance
1156 CHKERR DMCreate(PETSC_COMM_WORLD, &dm_sub_disp_penalty);
1157 CHKERR DMSetType(dm_sub_disp_penalty, dm_name);
1158 // set dm_sub_disp_penalty data structure which created mofem
1159 // datastructures
1160 CHKERR DMMoFEMCreateSubDM(dm_sub_disp_penalty, dm_sub_volume_control,
1161 "S_PROB");
1162 CHKERR DMMoFEMSetSquareProblem(dm_sub_disp_penalty, PETSC_FALSE);
1163 CHKERR DMMoFEMAddSubFieldRow(dm_sub_disp_penalty, "UPSILON");
1164 CHKERR DMMoFEMAddSubFieldCol(dm_sub_disp_penalty, "U");
1165 // add elements to dm_sub_disp_penalty
1166 CHKERR DMMoFEMAddElement(dm_sub_disp_penalty, "DISPLACEMENTS_PENALTY");
1167 CHKERR DMSetUp(dm_sub_disp_penalty);
1168
1169 Mat S;
1170 CHKERR DMCreateMatrix(dm_sub_disp_penalty, &S);
1171 CHKERR MatZeroEntries(S);
1172
1173 CellEngineering::FaceElement face_element(m_field);
1174 CHKERR AddHOOps<2, 2, 2>::add(face_element.getOpPtrVector(), {H1});
1175 face_element.getOpPtrVector().push_back(new OpCellS(S, eps_u));
1176 CHKERR DMoFEMLoopFiniteElements(dm_sub_disp_penalty,
1177 "DISPLACEMENTS_PENALTY", &face_element);
1178 CHKERR MatAssemblyBegin(S, MAT_FLUSH_ASSEMBLY);
1179 CHKERR MatAssemblyEnd(S, MAT_FLUSH_ASSEMBLY);
1180
1181 // // Matrix View
1182 if (debug) {
1183 cerr << "S" << endl;
1184 MatView(S, PETSC_VIEWER_DRAW_WORLD);
1185 std::string wait;
1186 std::cin >> wait;
1187 }
1188
1189 const Problem *problem_ptr;
1190 CHKERR m_field.get_problem("S_PROB", &problem_ptr);
1191 boost::shared_ptr<Problem::SubProblemData> sub_data =
1192 problem_ptr->getSubData();
1193 // CHKERR sub_data->getRowIs(&sub_nested_is_rows[1]);
1194 // CHKERR sub_data->getColIs(&sub_nested_is_cols[0]);
1195 sub_nested_matrices(1, 0) = S;
1196
1197 CHKERR DMDestroy(&dm_sub_disp_penalty);
1198 }
1199
1200 // Calculate penalty matrix
1201 {
1202 DM dm_sub_force_penalty;
1203
1204 // Craete dm_control instance
1205 CHKERR DMCreate(PETSC_COMM_WORLD, &dm_sub_force_penalty);
1206 CHKERR DMSetType(dm_sub_force_penalty, dm_name);
1207 // set dm_sub_force_penalty data structure which created mofem
1208 // datastructures
1209 CHKERR DMMoFEMCreateSubDM(dm_sub_force_penalty, dm_control, "D_PROB");
1210 CHKERR DMMoFEMSetSquareProblem(dm_sub_force_penalty, PETSC_TRUE);
1211 CHKERR DMMoFEMAddSubFieldRow(dm_sub_force_penalty, "RHO");
1212 CHKERR DMMoFEMAddSubFieldCol(dm_sub_force_penalty, "RHO");
1213 // add elements to dm_sub_force_penalty
1214 CHKERR DMMoFEMAddElement(dm_sub_force_penalty, "D");
1215 CHKERR DMSetUp(dm_sub_force_penalty);
1216
1217 Mat D;
1218 CHKERR DMCreateMatrix(dm_sub_force_penalty, &D);
1219 CHKERR MatZeroEntries(D);
1220
1221 {
1222 CellEngineering::FaceElement face_d_matrix(m_field);
1223
1224 if (is_curl) {
1226 {HCURL});
1227 face_d_matrix.getOpPtrVector().push_back(
1228 new OpCellCurlD(D, eps_rho / eps_u, eps_l * eps_u));
1229 } else {
1230 CHKERR AddHOOps<2, 2, 2>::add(face_d_matrix.getOpPtrVector(), {H1});
1231 face_d_matrix.getOpPtrVector().push_back(
1232 new OpCellPotentialD(D, eps_rho / eps_u));
1233 }
1234 CHKERR DMoFEMLoopFiniteElements(dm_sub_force_penalty, "D",
1235 &face_d_matrix);
1236 }
1237 CHKERR MatAssemblyBegin(D, MAT_FINAL_ASSEMBLY);
1238 CHKERR MatAssemblyEnd(D, MAT_FINAL_ASSEMBLY);
1239
1240 const Problem *problem_ptr;
1241 CHKERR m_field.get_problem("D_PROB", &problem_ptr);
1242
1243 // Zero rows, force field is given by gradients of potential field, so one
1244 // of the values has to be fixed like for rigid body motion.
1245 if (is_curl == PETSC_FALSE) {
1246 int nb_dofs_to_fix = 0;
1247 int index_to_fix = 0;
1248 if (!vertex_to_fix.empty()) {
1249 boost::shared_ptr<NumeredDofEntity> dof_ptr;
1251 m_field.get_field_bit_number("RHO"), vertex_to_fix[0], 0, ROW,
1252 dof_ptr);
1253 if (dof_ptr) {
1254 if (dof_ptr->getPart() == m_field.get_comm_rank()) {
1255 nb_dofs_to_fix = 1;
1256 index_to_fix = dof_ptr->getPetscGlobalDofIdx();
1257 cerr << *dof_ptr << endl;
1258 }
1259 }
1260 }
1261 CHKERR MatZeroRowsColumns(D, nb_dofs_to_fix, &index_to_fix,
1262 eps_rho / eps_u, PETSC_NULLPTR,
1263 PETSC_NULLPTR);
1264 } else {
1265 std::vector<int> dofs_to_fix;
1266 for (auto p_eit = edges_to_fix.pair_begin();
1267 p_eit != edges_to_fix.pair_end(); ++p_eit) {
1268 auto bit_number = m_field.get_field_bit_number("RHO");
1269 auto row_dofs = problem_ptr->numeredRowDofsPtr;
1270 auto lo = row_dofs->lower_bound(
1271 FieldEntity::getLoLocalEntityBitNumber(bit_number, p_eit->first));
1272 auto hi =
1273 row_dofs->upper_bound(FieldEntity::getHiLocalEntityBitNumber(
1274 bit_number, p_eit->second));
1275 for (; lo != hi; ++lo)
1276 if ((*lo)->getPart() == m_field.get_comm_rank())
1277 dofs_to_fix.push_back((*lo)->getPetscGlobalDofIdx());
1278 }
1279 CHKERR MatZeroRowsColumns(D, dofs_to_fix.size(), &*dofs_to_fix.begin(),
1280 eps_rho / eps_u, PETSC_NULLPTR,
1281 PETSC_NULLPTR);
1282 }
1283
1284 // Matrix View
1285 if (debug) {
1286 cerr << "D" << endl;
1287 MatView(D, PETSC_VIEWER_DRAW_WORLD);
1288 std::string wait;
1289 std::cin >> wait;
1290 }
1291
1292 boost::shared_ptr<Problem::SubProblemData> sub_data =
1293 problem_ptr->getSubData();
1294 CHKERR sub_data->getRowIs(&nested_is_rows[1]);
1295 CHKERR sub_data->getColIs(&nested_is_cols[1]);
1296 nested_matrices(1, 1) = D;
1297
1298 CHKERR DMDestroy(&dm_sub_force_penalty);
1299 }
1300
1301 {
1302 DM dm_sub_force;
1303
1304 // Craete dm_control instance
1305 CHKERR DMCreate(PETSC_COMM_WORLD, &dm_sub_force);
1306 CHKERR DMSetType(dm_sub_force, dm_name);
1307 // set dm_sub_force data structure which created mofem data structures
1308 CHKERR DMMoFEMCreateSubDM(dm_sub_force, dm_control, "FORCES_PROB");
1309 CHKERR DMMoFEMSetSquareProblem(dm_sub_force, PETSC_FALSE);
1310 CHKERR DMMoFEMAddSubFieldRow(dm_sub_force, "RHO");
1311 CHKERR DMMoFEMAddSubFieldCol(dm_sub_force, "U");
1312 CHKERR DMMoFEMAddSubFieldCol(dm_sub_force, "UPSILON");
1313 // add elements to dm_sub_force
1314 CHKERR DMMoFEMAddElement(dm_sub_force, "B");
1315 CHKERR DMSetUp(dm_sub_force);
1316
1317 Mat UB, UPSILONB;
1318 CHKERR DMCreateMatrix(dm_sub_force, &UB);
1319 CHKERR MatZeroEntries(UB);
1320 // note be will be transposed in place latter on
1321 CHKERR DMCreateMatrix(dm_sub_force, &UPSILONB);
1322 CHKERR MatZeroEntries(UPSILONB);
1323 {
1324 CellEngineering::FaceElement face_b_matrices(m_field);
1325 if (is_curl) {
1327 {H1, HCURL});
1328 face_b_matrices.getOpPtrVector().push_back(new OpCellCurlB(UB, "U"));
1329 face_b_matrices.getOpPtrVector().push_back(
1330 new OpCellCurlB(UPSILONB, "UPSILON"));
1331 } else {
1333 {H1});
1334 face_b_matrices.getOpPtrVector().push_back(
1335 new OpCellPotentialB(UB, "U"));
1336 face_b_matrices.getOpPtrVector().push_back(
1337 new OpCellPotentialB(UPSILONB, "UPSILON"));
1338 }
1339 CHKERR DMoFEMLoopFiniteElements(dm_sub_force, "B", &face_b_matrices);
1340 }
1341 CHKERR MatAssemblyBegin(UB, MAT_FINAL_ASSEMBLY);
1342 CHKERR MatAssemblyBegin(UPSILONB, MAT_FINAL_ASSEMBLY);
1343 CHKERR MatAssemblyEnd(UB, MAT_FINAL_ASSEMBLY);
1344 CHKERR MatAssemblyEnd(UPSILONB, MAT_FINAL_ASSEMBLY);
1345
1346 const Problem *problem_ptr;
1347 CHKERR m_field.get_problem("FORCES_PROB", &problem_ptr);
1348
1349 // Zero rows, force field is given by gradients of potential field, so one
1350 // of the values has to be fixed like for rigid body motion.
1351 if (is_curl == PETSC_FALSE) {
1352 int nb_dofs_to_fix = 0;
1353 int index_to_fix = 0;
1354 if (!vertex_to_fix.empty()) {
1355 boost::shared_ptr<NumeredDofEntity> dof_ptr;
1357 m_field.get_field_bit_number("RHO"), vertex_to_fix[0], 0, ROW,
1358 dof_ptr);
1359 if (dof_ptr) {
1360 if (dof_ptr->getPart() == m_field.get_comm_rank()) {
1361 nb_dofs_to_fix = 1;
1362 index_to_fix = dof_ptr->getPetscGlobalDofIdx();
1363 cerr << *dof_ptr << endl;
1364 }
1365 }
1366 }
1367 CHKERR MatZeroRows(UB, nb_dofs_to_fix, &index_to_fix, 0, PETSC_NULLPTR,
1368 PETSC_NULLPTR);
1369 CHKERR MatZeroRows(UPSILONB, nb_dofs_to_fix, &index_to_fix, 0,
1370 PETSC_NULLPTR, PETSC_NULLPTR);
1371 } else {
1372 std::vector<int> dofs_to_fix;
1373 for (auto p_eit = edges_to_fix.pair_begin();
1374 p_eit != edges_to_fix.pair_end(); ++p_eit) {
1375 auto bit_number = m_field.get_field_bit_number("RHO");
1376 auto row_dofs = problem_ptr->numeredRowDofsPtr;
1377 auto lo = row_dofs->lower_bound(
1378 FieldEntity::getLoLocalEntityBitNumber(bit_number, p_eit->first));
1379 auto hi =
1380 row_dofs->upper_bound(FieldEntity::getHiLocalEntityBitNumber(
1381 bit_number, p_eit->second));
1382 for (; lo != hi; ++lo)
1383 if ((*lo)->getPart() == m_field.get_comm_rank())
1384 dofs_to_fix.push_back((*lo)->getPetscGlobalDofIdx());
1385 }
1386 CHKERR MatZeroRows(UB, dofs_to_fix.size(), &*dofs_to_fix.begin(), 0,
1387 PETSC_NULLPTR, PETSC_NULLPTR);
1388 CHKERR MatZeroRows(UPSILONB, dofs_to_fix.size(), &*dofs_to_fix.begin(),
1389 0, PETSC_NULLPTR, PETSC_NULLPTR);
1390 }
1391
1392 Mat UBT;
1393 CHKERR MatTranspose(UB, MAT_INITIAL_MATRIX, &UBT);
1394 CHKERR MatDestroy(&UB);
1395
1396 // Matrix View
1397 if (debug) {
1398 cerr << "UBT" << endl;
1399 MatView(UBT, PETSC_VIEWER_DRAW_WORLD);
1400 std::string wait;
1401 std::cin >> wait;
1402 }
1403
1404 boost::shared_ptr<Problem::SubProblemData> sub_data =
1405 problem_ptr->getSubData();
1406 // CHKERR sub_data->getColIs(&nested_is_rows[0]);
1407 // CHKERR sub_data->getRowIs(&nested_is_cols[1]);
1408 nested_matrices(0, 1) = UBT;
1409
1410 if (debug) {
1411 cerr << "UPSILONB" << endl;
1412 MatView(UPSILONB, PETSC_VIEWER_DRAW_WORLD);
1413 std::string wait;
1414 std::cin >> wait;
1415 }
1416
1417 // CHKERR sub_data->getRowIs(&nested_is_rows[1]);
1418 // CHKERR sub_data->getColIs(&nested_is_cols[0]);
1419 nested_matrices(1, 0) = UPSILONB;
1420
1421 CHKERR DMDestroy(&dm_sub_force);
1422 }
1423
1424 Mat SubA;
1425 CHKERR MatCreateNest(PETSC_COMM_WORLD, 2, &sub_nested_is_rows[0], 2,
1426 &sub_nested_is_cols[0], &sub_nested_matrices(0, 0),
1427 &SubA);
1428 nested_matrices(0, 0) = SubA;
1429
1430 CHKERR MatAssemblyBegin(SubA, MAT_FINAL_ASSEMBLY);
1431 CHKERR MatAssemblyEnd(SubA, MAT_FINAL_ASSEMBLY);
1432
1433 if (debug) {
1434 cerr << "Nested SubA" << endl;
1435 MatView(SubA, PETSC_VIEWER_STDOUT_WORLD);
1436 }
1437
1438 Mat A;
1439 CHKERR MatCreateNest(PETSC_COMM_WORLD, 2, &nested_is_rows[0], 2,
1440 &nested_is_cols[0], &nested_matrices(0, 0), &A);
1441
1442 CHKERR MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);
1443 CHKERR MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);
1444
1445 if (debug) {
1446 cerr << "Nested A" << endl;
1447 MatView(A, PETSC_VIEWER_STDOUT_WORLD);
1448 }
1449
1450 Vec D, F;
1451 CHKERR DMCreateGlobalVector(dm_control, &D);
1452 CHKERR DMCreateGlobalVector(dm_control, &F);
1453
1454 // Asseble the right hand side vector
1455 {
1456 CellEngineering::FaceElement face_element(m_field);
1457 CHKERR AddHOOps<2, 2, 2>::add(face_element.getOpPtrVector(), {H1});
1458 face_element.getOpPtrVector().push_back(new OpGetDispX(common_data));
1459 face_element.getOpPtrVector().push_back(new OpGetDispY(common_data));
1460 face_element.getOpPtrVector().push_back(
1461 new OpCell_g(F, eps_u, common_data));
1462 CHKERR DMoFEMLoopFiniteElements(dm_control, "DISPLACEMENTS_PENALTY",
1463 &face_element);
1464 CHKERR VecGhostUpdateBegin(F, ADD_VALUES, SCATTER_REVERSE);
1465 CHKERR VecGhostUpdateEnd(F, ADD_VALUES, SCATTER_REVERSE);
1466 CHKERR VecAssemblyBegin(F);
1467 CHKERR VecAssemblyEnd(F);
1468 }
1469
1470 KSP solver;
1471 // KSP solver;
1472 {
1473 CHKERR KSPCreate(PETSC_COMM_WORLD, &solver);
1474 CHKERR KSPSetDM(solver, dm_control);
1475 CHKERR KSPSetFromOptions(solver);
1476 CHKERR KSPSetOperators(solver, A, A);
1477 CHKERR KSPSetDMActive(solver, PETSC_FALSE);
1478 CHKERR KSPSetInitialGuessKnoll(solver, PETSC_FALSE);
1479 CHKERR KSPSetInitialGuessNonzero(solver, PETSC_FALSE);
1480 PC pc;
1481 CHKERR KSPGetPC(solver, &pc);
1482 CHKERR PCSetType(pc, PCFIELDSPLIT);
1483 PetscBool is_pcfs = PETSC_FALSE;
1484 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
1485 if (is_pcfs) {
1486 CHKERR PCSetOperators(pc, A, A);
1487 CHKERR PCFieldSplitSetIS(pc, NULL, nested_is_rows[0]);
1488 CHKERR PCFieldSplitSetIS(pc, NULL, nested_is_rows[1]);
1489 CHKERR PCFieldSplitSetType(pc, PC_COMPOSITE_SCHUR);
1490 CHKERR PCSetUp(pc);
1491 KSP *sub_ksp;
1492 PetscInt n;
1493 CHKERR PCFieldSplitGetSubKSP(pc, &n, &sub_ksp);
1494 {
1495 PC sub_pc_0;
1496 CHKERR KSPGetPC(sub_ksp[0], &sub_pc_0);
1497 CHKERR PCSetOperators(sub_pc_0, SubA, SubA);
1498 CHKERR PCSetType(sub_pc_0, PCFIELDSPLIT);
1499 CHKERR PCFieldSplitSetIS(sub_pc_0, NULL, sub_nested_is_rows[0]);
1500 CHKERR PCFieldSplitSetIS(sub_pc_0, NULL, sub_nested_is_rows[1]);
1501 CHKERR PCFieldSplitSetType(sub_pc_0, PC_COMPOSITE_MULTIPLICATIVE);
1502 // CHKERR
1503 // PCFieldSplitSetSchurFactType(sub_pc_0,PC_FIELDSPLIT_SCHUR_FACT_LOWER);
1504 // CHKERR PCFieldSplitSetType(sub_pc_0,PC_COMPOSITE_SCHUR);
1505 CHKERR PCSetUp(sub_pc_0);
1506 }
1507 } else {
1508 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
1509 "Only works with pre-conditioner PCFIELDSPLIT");
1510 }
1511 CHKERR KSPSetUp(solver);
1512 }
1513
1514 // Solve system of equations
1515 CHKERR KSPSolve(solver, F, D);
1516
1517 CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
1518 CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
1519 CHKERR DMoFEMMeshToLocalVector(dm_control, D, INSERT_VALUES,
1520 SCATTER_REVERSE);
1521
1522 if (debug) {
1523 CHKERR VecView(D, PETSC_VIEWER_DRAW_WORLD);
1524 std::string wait;
1525 std::cin >> wait;
1526 }
1527
1528 // Clean sub matrices and sub indices
1529 for (int i = 0; i != 2; i++) {
1530 if (sub_nested_is_rows[i]) {
1531 CHKERR ISDestroy(&sub_nested_is_rows[i]);
1532 }
1533 if (sub_nested_is_cols[i]) {
1534 CHKERR ISDestroy(&sub_nested_is_cols[i]);
1535 }
1536 for (int j = 0; j != 2; j++) {
1537 if (sub_nested_matrices(i, j)) {
1538 CHKERR MatDestroy(&sub_nested_matrices(i, j));
1539 }
1540 }
1541 }
1542 for (int i = 0; i != 2; i++) {
1543 if (nested_is_rows[i]) {
1544 CHKERR ISDestroy(&nested_is_rows[i]);
1545 }
1546 if (nested_is_cols[i]) {
1547 CHKERR ISDestroy(&nested_is_cols[i]);
1548 }
1549 for (int j = 0; j != 2; j++) {
1550 if (nested_matrices(i, j)) {
1551 CHKERR MatDestroy(&nested_matrices(i, j));
1552 }
1553 }
1554 }
1555
1556 CHKERR MatDestroy(&SubA);
1557 CHKERR MatDestroy(&A);
1558 CHKERR VecDestroy(&D);
1559 CHKERR VecDestroy(&F);
1560
1561 CHKERR DMDestroy(&dm_sub_volume_control);
1562
1563 using PostProcVolume =
1565 using OpPPVolume = OpPostProcMapInMoab<3, 3>;
1566
1567 PostProcVolume post_proc(m_field, "my");
1568 {
1569 CHKERR AddHOOps<3, 3, 3>::add(post_proc.getOpPtrVector(), {H1});
1570
1571 auto u_ptr = boost::make_shared<MatrixDouble>();
1572 post_proc.getOpPtrVector().push_back(
1573 new OpCalculateVectorFieldValues<3>("U", u_ptr));
1574 auto hooke_common =
1575 HookeOps::commonDataFactory<SPACE_DIM, GAUSS, DomainEleOp>(
1576 m_field, post_proc.getOpPtrVector(), "U", "MAT_ELASTIC",
1577 Sev::verbose);
1578 post_proc.getOpPtrVector().push_back(new OpPPVolume(
1579 post_proc.getPostProcMesh(), post_proc.getMapGaussPts(),
1580 OpPPVolume::DataMapVec{}, OpPPVolume::DataMapMat{{"U", u_ptr}},
1581 OpPPVolume::DataMapMat{{"U_GRAD", hooke_common->matGradPtr}},
1582 OpPPVolume::DataMapMat{
1583 {"STRESS", hooke_common->getMatCauchyStress()}}));
1584 CHKERR post_proc.setTagsToTransfer({block_id_tag});
1585
1586 CHKERR DMoFEMLoopFiniteElements(dm_control, "ELASTIC", &post_proc);
1587 CHKERR post_proc.writeFile("out.h5m");
1588 elastic_energy = 0;
1589 CHKERR DMoFEMLoopFiniteElements(dm_control, "ELASTIC",
1590 &elastic_energy_fe);
1591 double global_elastic_energy = 0;
1592 CHKERR MPI_Allreduce(&elastic_energy, &global_elastic_energy, 1,
1593 MPI_DOUBLE, MPI_SUM, m_field.get_comm());
1594 PetscPrintf(PETSC_COMM_WORLD, "Elastic energy %6.4e\n",
1595 global_elastic_energy);
1596 }
1597
1598 {
1599 using PostProcFace =
1601 PostProcFace post_proc_face(m_field, "my");
1602 if (is_curl) {
1604 {HCURL});
1605 post_proc_face.getOpPtrVector().push_back(
1606 new OpVirtualCurlRho("RHO", common_data));
1607 } else {
1608 CHKERR AddHOOps<2, 2, 2>::add(post_proc_face.getOpPtrVector(), {H1});
1609 post_proc_face.getOpPtrVector().push_back(
1610 new OpVirtualPotentialRho("RHO", common_data));
1611 }
1612 post_proc_face.getOpPtrVector().push_back(
1613 new PostProcTraction(m_field, post_proc_face.getPostProcMesh(),
1614 post_proc_face.getMapGaussPts(), common_data));
1615 CHKERR DMoFEMLoopFiniteElements(dm_control, "D", &post_proc_face);
1616 CHKERR post_proc_face.writeFile("out_tractions.h5m");
1617 }
1618
1619 CHKERR DMDestroy(&dm_control);
1620 }
1622
1624 return 0;
1625}
int main()
static char help[]
constexpr int SPACE_DIM
constexpr int SPACE_DIM
@ ROW
#define CATCH_ERRORS
Catch errors.
@ MF_ZERO
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition definitions.h:60
@ H1
continuous field
Definition definitions.h:85
@ NOSPACE
Definition definitions.h:83
@ HCURL
field with continuous tangents
Definition definitions.h:86
#define MYPCOMM_INDEX
default communicator number PCOMM
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MAT_ELASTICSET
block name is "MAT_ELASTIC"
@ SIDESET
@ BLOCKSET
@ MOFEM_STD_EXCEPTION_THROW
Definition definitions.h:39
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
@ MOFEM_INVALID_DATA
Definition definitions.h:36
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
constexpr int order
@ F
PetscErrorCode DMMoFEMSetIsPartitioned(DM dm, PetscBool is_partitioned)
Definition DMMoFEM.cpp:1113
PetscErrorCode DMMoFEMCreateSubDM(DM subdm, DM dm, const char problem_name[])
Must be called by user to set Sub DM MoFEM data structures.
Definition DMMoFEM.cpp:215
PetscErrorCode DMMoFEMAddElement(DM dm, std::string fe_name)
add element to dm
Definition DMMoFEM.cpp:488
PetscErrorCode DMMoFEMSetSquareProblem(DM dm, PetscBool square_problem)
set squared problem
Definition DMMoFEM.cpp:450
PetscErrorCode DMMoFEMCreateMoFEM(DM dm, MoFEM::Interface *m_field_ptr, const char problem_name[], const MoFEM::BitRefLevel bit_level, const MoFEM::BitRefLevel bit_mask=MoFEM::BitRefLevel().set())
Must be called by user to set MoFEM data structures.
Definition DMMoFEM.cpp:114
PetscErrorCode DMoFEMPostProcessFiniteElements(DM dm, MoFEM::FEMethod *method)
execute finite element method for each element in dm (problem)
Definition DMMoFEM.cpp:546
PetscErrorCode DMMoFEMAddSubFieldRow(DM dm, const char field_name[])
Definition DMMoFEM.cpp:238
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:514
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:576
PetscErrorCode DMMoFEMAddSubFieldCol(DM dm, const char field_name[])
Definition DMMoFEM.cpp:280
PetscErrorCode DMoFEMPreProcessFiniteElements(DM dm, MoFEM::FEMethod *method)
execute finite element method for each element in dm (problem)
Definition DMMoFEM.cpp:536
virtual const Problem * get_problem(const std::string problem_name) const =0
Get the problem object.
virtual MoFEMErrorCode add_finite_element(const std::string &fe_name, enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
add finite element
virtual MoFEMErrorCode build_finite_elements(int verb=DEFAULT_VERBOSITY)=0
Build finite elements.
virtual MoFEMErrorCode modify_finite_element_add_field_col(const std::string &fe_name, const std::string name_row)=0
set field col which finite element use
virtual MoFEMErrorCode add_ents_to_finite_element_by_type(const EntityHandle entities, const EntityType type, const std::string name, const bool recursive=true)=0
add entities to finite element
virtual MoFEMErrorCode modify_finite_element_add_field_row(const std::string &fe_name, const std::string name_row)=0
set field row which finite element use
virtual MoFEMErrorCode modify_finite_element_add_field_data(const std::string &fe_name, const std::string name_field)=0
set finite element field data
virtual MoFEMErrorCode build_fields(int verb=DEFAULT_VERBOSITY)=0
virtual MoFEMErrorCode set_field_order(const EntityHandle meshset, const EntityType type, const std::string &name, const ApproximationOrder order, int verb=DEFAULT_VERBOSITY)=0
Set order approximation of the entities in the field.
virtual MoFEMErrorCode add_ents_to_field_by_type(const Range &ents, const EntityType type, const std::string &name, int verb=DEFAULT_VERBOSITY)=0
Add entities to field meshset.
MoFEMErrorCode writeFile(const std::string file_name)
wrote results in (MOAB) format, use "file_name.h5m"
#define _IT_CUBITMESHSETS_BY_BCDATA_TYPE_FOR_LOOP_(MESHSET_MANAGER, CUBITBCTYPE, IT)
Iterator that loops over a specific Cubit MeshSet in a moFEM field.
#define _IT_CUBITMESHSETS_BY_SET_TYPE_FOR_LOOP_(MESHSET_MANAGER, CUBITBCTYPE, IT)
Iterator that loops over a specific Cubit MeshSet having a particular BC meshset in a moFEM field.
FTensor::Index< 'i', SPACE_DIM > i
double D
const double n
refractive index of diffusive medium
FTensor::Index< 'j', 3 > j
std::map< int, Range > ElasticBlockMap
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
Definition Types.hpp:40
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
decltype(GetFTensor2SymmetricFromMatImpl< Tensor_Dim, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor2SymmetricFromMatType
static const bool debug
constexpr AssemblyType A
int getRule(int order) override
Calculate and assemble Z matrix.
Calculate and assemble Z matrix.
Calculate and assemble B matrix.
Calculate and assemble D matrix.
Calculate and assemble S matrix.
Calculate and assemble g vector.
boost::shared_ptr< MatrixDouble > stressPtr
boost::shared_ptr< MatrixDouble > strainPtr
MoFEMErrorCode doWork(int, EntityType, EntitiesFieldData::EntData &) override
OpElasticEnergy(boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, double &energy)
Post-process tractions.
Shave results on mesh tags for post-processing.
Add operators pushing bases from local to physical configuration.
Boundary condition manager for finite element problem setup.
Managing BitRefLevels.
Managing BitRefLevels.
virtual FieldBitNumber get_field_bit_number(const std::string name) const =0
get field bit number
virtual MoFEMErrorCode build_adjacencies(const Range &ents, int verb=DEFAULT_VERBOSITY)=0
build adjacencies
virtual MoFEMErrorCode add_field(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_EXCL, int verb=DEFAULT_VERBOSITY)=0
Add field.
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)
Class (Function) to enforce essential constrains on the left hand side diagonal.
Definition Essential.hpp:33
Class (Function) to enforce essential constrains on the right hand side diagonal.
Definition Essential.hpp:41
Class (Function) to enforce essential constrains.
Definition Essential.hpp:25
static UId getLoLocalEntityBitNumber(const char bit_number, const EntityHandle ent)
static UId getHiLocalEntityBitNumber(const char bit_number, const EntityHandle ent)
boost::ptr_deque< UserDataOperator > & getOpPtrVector()
Use to push back operator for row operator.
Section manager is used to create indexes and sections.
Definition ISManager.hpp:23
Elastic material data structure.
Interface for managing meshsets containing materials and boundary conditions.
Calculate inverse of jacobian for face element.
Specialization for MatrixDouble vector field values calculation.
Post post-proc data at points from hash maps.
Transform local reference derivatives of shape functions to global derivatives.
auto & getMapGaussPts()
Get vector of vectors associated to integration points.
auto & getPostProcMesh()
Get postprocessing mesh.
keeps basic data about problem
MoFEMErrorCode getDofByNameEntAndEntDofIdx(const int field_bit_number, const EntityHandle ent, const int ent_dof_idx, const RowColData row_or_col, boost::shared_ptr< NumeredDofEntity > &dof_ptr) const
get DOFs from problem
boost::shared_ptr< SubProblemData > & getSubData() const
Get main problem of sub-problem is.
boost::shared_ptr< NumeredDofEntity_multiIndex > numeredRowDofsPtr
store DOFs on rows for this problem
intrusive_ptr for managing petsc objects
Vec & snes_f
Reference to residual vector.
Mat & snes_B
Reference to preconditioner of Jacobian matrix.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.