v0.15.0
Loading...
Searching...
No Matches
h_adaptive_transport.cpp
Go to the documentation of this file.
1/** \file h_adaptive_transport.cpp
2\brief Example implementation of transport problem using mixed formulation
3
4\todo Should be implemented and tested problem from this article
5Demkowicz, Leszek, and Jayadeep Gopalakrishnan. "Analysis of the DPG method for
6the Poisson equation." SIAM Journal on Numerical Analysis 49.5 (2011):
71788-1809.
8
9\ingroup mofem_mix_transport_elem
10*/
11
12
13
14#include <MoFEM.hpp>
15
16using namespace MoFEM;
17#include <MethodForForceScaling.hpp>
19
20using namespace MixTransport;
21
22
23static char help[] = "-my_file input file"
24 "-my_order order of approximation"
25 "-nb_levels number of refinements levels"
26 "\n\n";
27
28/**
29 * Data structure to pass information between function evaluating boundary
30 * values and fluxes and generic data structures for boundary conditions on
31 * meshsets.
32 */
33struct BcFluxData {
35 double fLux;
36};
37typedef map<int, BcFluxData> BcFluxMap;
38
39/** \brief Application of mix transport data structure
40 *
41 * MixTransportElement is a class collecting functions, operators and
42 * data for mix implementation of transport element. See there to
43 * learn how elements are created or how operators look like.
44 *
45 * Some methods in MixTransportElement are abstract, f.e. user need to
46 * implement own source therm.
47
48 * \ingroup mofem_mix_transport_elem
49 */
50struct MyTransport : public MixTransportElement {
51
54 double lastFlux;
55
56 MyTransport(MoFEM::Interface &m_field, BcFluxMap &bc_flux_map)
57 : MixTransportElement(m_field), bcFluxMap(bc_flux_map), lastEnt(0),
58 lastFlux(0) {}
59
60 /**
61 * \brief set source term
62 * @param ent handle to entity on which function is evaluated
63 * @param x coord
64 * @param y coord
65 * @param z coord
66 * @param flux reference to source term set by function
67 * @return error code
68 */
69 MoFEMErrorCode getSource(EntityHandle ent, const double x, const double y,
70 const double z, double &flux) {
72 flux = 0;
74 }
75
76 /**
77 * \brief natural (Dirihlet) boundary conditions (set values)
78 * @param ent handle to finite element entity
79 * @param x coord
80 * @param y coord
81 * @param z coord
82 * @param value reference to value set by function
83 * @return error code
84 */
85 MoFEMErrorCode getBcOnValues(const EntityHandle ent, const double x,
86 const double y, const double z, double &value) {
88 value = 0;
90 }
91
92 /**
93 * \brief essential (Neumann) boundary condition (set fluxes)
94 * @param ent handle to finite element entity
95 * @param x coord
96 * @param y coord
97 * @param z coord
98 * @param flux reference to flux which is set by function
99 * @return [description]
100 */
101 MoFEMErrorCode getBcOnFluxes(const EntityHandle ent, const double x,
102 const double y, const double z, double &flux) {
104 if (lastEnt == ent) {
105 flux = lastFlux;
106 } else {
107 flux = 0;
108 for (BcFluxMap::iterator mit = bcFluxMap.begin(); mit != bcFluxMap.end();
109 mit++) {
110 Range &tris = mit->second.eNts;
111 if (tris.find(ent) != tris.end()) {
112 flux = mit->second.fLux;
113 }
114 }
115 lastEnt = ent;
116 lastFlux = flux;
117 }
119 }
120
121 /**
122 * \brief set-up boundary conditions
123 * @param ref_level mesh refinement level
124
125 \note It is assumed that user would like to something non-standard with
126 boundary conditions, have a own type of data structures to pass to functions
127 calculating values and fluxes on boundary. For example BcFluxMap. That way
128 this function is implemented here not in generic class MixTransportElement.
129
130 * @return error code
131 */
134 Range tets;
135 CHKERR mField.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
136 ref_level, BitRefLevel().set(), MBTET, tets);
137 Skinner skin(&mField.get_moab());
138 Range skin_faces; // skin faces from 3d ents
139 CHKERR skin.find_skin(0, tets, false, skin_faces);
140 // note: what is essential (dirichlet) is natural (neumann) for mix-FE
141 // compared to classical FE
142 Range natural_bc;
144 mField, NODESET | TEMPERATURESET, it)) {
145 Range tris;
146 CHKERR it->getMeshsetIdEntitiesByDimension(mField.get_moab(), 2, tris,
147 true);
148 natural_bc.insert(tris.begin(), tris.end());
149 }
151 mField, SIDESET | HEATFLUXSET, it)) {
152 HeatFluxCubitBcData mydata;
153 CHKERR it->getBcDataStructure(mydata);
154 if (mydata.data.flag1 == 1) {
155 Range tris;
156 CHKERR it->getMeshsetIdEntitiesByDimension(mField.get_moab(), 2, tris,
157 true);
158 bcFluxMap[it->getMeshsetId()].eNts = tris;
159 bcFluxMap[it->getMeshsetId()].fLux = mydata.data.value1;
160 // cerr << bcFluxMap[it->getMeshsetId()].eNts << endl;
161 // cerr << bcFluxMap[it->getMeshsetId()].fLux << endl;
162 }
163 }
164 Range essential_bc = subtract(skin_faces, natural_bc);
165 Range bit_tris;
166 CHKERR mField.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
167 ref_level, BitRefLevel().set(), MBTRI, bit_tris);
168 essential_bc = intersect(bit_tris, essential_bc);
169 natural_bc = intersect(bit_tris, natural_bc);
171 "MIX_BCFLUX");
173 "MIX_BCVALUE");
174 // CHKERR
175 // mField.add_ents_to_finite_element_by_type(skin_faces,MBTRI,"MIX_BCVALUE");
177 }
178
179 /**
180 * \brief Refine mesh
181 * @param ufe general data structure
182 * @param nb_levels number of refinement levels
183 * @param order set order of approximation
184 * @return errpr code
185
186 Refinement of could result in distorted mesh, for example, imagine when you
187 have two levels of non-uniform refinement. Some tetrahedra on the mesh at
188 first refinement instance are only refined by splitting subset of edges on
189 it. Then refined child tetrahedra usually will have worse quality than
190 quality of parent element. Refining such element in subsequent mesh
191 refinement, potentially will deteriorate elements quality even worse. To
192 prevent that adding new refinement level, recreate whole hierarchy of meshes.
193
194 Note on subsequent improvement could include refinement of
195 tetrahedra from different levels, including initial mesh. So refinement two
196 could split elements created during refinement one and also split elements
197 from an initial mesh.
198
199 That adding the new refinement level creates refinement hierarchy of meshes
200 from a scratch, not adding to existing one.
201
202 Entities from previous hierarchy are used in that process, but bit levels on
203 those entities are squashed.
204
205 */
207 const int order) {
208 MeshRefinement *refine_ptr;
210 // get refined edges having child vertex
211 auto ref_ents_ptr = mField.get_ref_ents();
212 typedef RefEntity_multiIndex::index<
213 Composite_EntType_and_ParentEntType_mi_tag>::type RefEntsByComposite;
214 const RefEntsByComposite &ref_ents =
216 RefEntsByComposite::iterator rit, hi_rit;
217 rit = ref_ents.lower_bound(boost::make_tuple(MBVERTEX, MBEDGE));
218 hi_rit = ref_ents.upper_bound(boost::make_tuple(MBVERTEX, MBEDGE));
219 Range refined_edges;
220 // thist loop is over vertices which parent is edge
221 for (; rit != hi_rit; rit++) {
222 refined_edges.insert((*rit)->getParentEnt()); // get parent edge
223 }
224 // get tets which has large error
225 Range tets_to_refine;
226 const double max_error = ufe.errorMap.rbegin()->first;
227 // int size = ((double)5/6)*ufe.errorMap.size();
228 for (map<double, EntityHandle>::iterator mit = ufe.errorMap.begin();
229 mit != ufe.errorMap.end(); mit++) {
230 // cerr << mit->first << " " << mit->second << endl;
231 // if((size--)>0) continue;
232 if (mit->first < 0.25 * max_error)
233 continue;
234 tets_to_refine.insert(mit->second);
235 }
236 Range tets_to_refine_edges;
237 CHKERR mField.get_moab().get_adjacencies(
238 tets_to_refine, 1, false, tets_to_refine_edges, moab::Interface::UNION);
239 refined_edges.merge(tets_to_refine_edges);
240 CHKERR mField.getInterface(refine_ptr);
241 for (int ll = 0; ll != nb_levels; ll++) {
242 Range edges;
243 CHKERR mField.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
244 BitRefLevel().set(ll), BitRefLevel().set(), MBEDGE, edges);
245 edges = intersect(edges, refined_edges);
246 // add edges to refine at current level edges (some of the where refined
247 // before)
249 edges, BitRefLevel().set(ll + 1));
250 // get tets at current level
251 Range tets;
252 CHKERR mField.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
253 BitRefLevel().set(ll), BitRefLevel().set(), MBTET, tets);
254 CHKERR refine_ptr->refineTets(tets, BitRefLevel().set(ll + 1));
256 }
257
258 // update fields and elements
259 EntityHandle ref_meshset;
260 CHKERR mField.get_moab().create_meshset(MESHSET_SET, ref_meshset);
261 {
262 // cerr << BitRefLevel().set(nb_levels) << endl;
263 CHKERR mField.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
264 BitRefLevel().set(nb_levels), BitRefLevel().set(), MBTET,
265 ref_meshset);
266
267 Range ref_tets;
268 CHKERR mField.get_moab().get_entities_by_type(ref_meshset, MBTET,
269 ref_tets);
270
271 // add entities to field
272 CHKERR mField.add_ents_to_field_by_type(ref_meshset, MBTET, "FLUXES");
273 CHKERR mField.add_ents_to_field_by_type(ref_meshset, MBTET, "VALUES");
274 CHKERR mField.set_field_order(0, MBTET, "FLUXES", order + 1);
275 CHKERR mField.set_field_order(0, MBTRI, "FLUXES", order + 1);
276 CHKERR mField.set_field_order(0, MBTET, "VALUES", order);
277
278 // add entities to skeleton
279 Range ref_tris;
280 CHKERR mField.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
281 BitRefLevel().set(nb_levels), BitRefLevel().set(), MBTRI, ref_tris);
283 "MIX_SKELETON");
284
285 // add entities to finite elements
288 Mat_Thermal temp_data;
289 CHKERR it->getAttributeDataStructure(temp_data);
290 setOfBlocks[it->getMeshsetId()].cOnductivity =
291 temp_data.data.Conductivity;
292 setOfBlocks[it->getMeshsetId()].cApacity = temp_data.data.HeatCapacity;
293 CHKERR mField.get_moab().get_entities_by_type(
294 it->meshset, MBTET, setOfBlocks[it->getMeshsetId()].tEts, true);
295 setOfBlocks[it->getMeshsetId()].tEts =
296 intersect(ref_tets, setOfBlocks[it->getMeshsetId()].tEts);
298 setOfBlocks[it->getMeshsetId()].tEts, MBTET, "MIX");
299 }
300 }
301 CHKERR mField.get_moab().delete_entities(&ref_meshset, 1);
303 }
304
305 /**
306 * \brief Squash bits of entities
307
308 Information about hierarchy of meshsets is lost, but entities are not deleted
309 from the mesh. After squash entities bits, new hierarchy can be created.
310
311 * @return error code
312 */
315 BitRefLevel all_but_0;
316 all_but_0.set(0);
317 all_but_0.flip();
318 BitRefLevel garbage_bit;
319 garbage_bit.set(BITREFLEVEL_SIZE - 1); // Garbage level
320 auto ref_ents_ptr = mField.get_ref_ents();
321 RefEntity_multiIndex::iterator mit = ref_ents_ptr->begin();
322 for (; mit != ref_ents_ptr->end(); mit++) {
323 if (mit->get()->getEntType() == MBENTITYSET)
324 continue;
325 BitRefLevel bit = mit->get()->getBitRefLevel();
326 if ((all_but_0 & bit) == bit) {
327 *(const_cast<RefEntity *>(mit->get())->getBitRefLevelPtr()) =
328 garbage_bit;
329 } else {
330 *(const_cast<RefEntity *>(mit->get())->getBitRefLevelPtr()) =
331 BitRefLevel().set(0);
332 }
333 }
335 }
336
337 /**
338 * \brief update meshsets with new entities after mesh refinement
339 * @param nb_levels nb_levels
340 * @param order appropriate order
341 * @return error code
342 */
344 BitRefLevel ref_level;
346 ref_level.set(nb_levels);
348 EntityHandle meshset = it->meshset;
350 ->updateMeshsetByEntitiesChildren(meshset, ref_level, meshset,
351 MBMAXTYPE, true);
352 }
354 }
355};
356
357int main(int argc, char *argv[]) {
358
359 const string default_options = "-ksp_type fgmres \n"
360 "-pc_type lu \n"
361 "-pc_factor_mat_solver_type mumps \n"
362 "-mat_mumps_icntl_20 0 \n"
363 "-ksp_monitor\n";
364
365 string param_file = "param_file.petsc";
366 if (!static_cast<bool>(ifstream(param_file))) {
367 std::ofstream file(param_file.c_str(), std::ios::ate);
368 if (file.is_open()) {
369 file << default_options;
370 file.close();
371 }
372 }
373
374 MoFEM::Core::Initialize(&argc, &argv, param_file.c_str(), help);
375
376 try {
377
378 moab::Core mb_instance;
379 moab::Interface &moab = mb_instance;
380 int rank;
381 MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
382
383 // get file name form command line
384 PetscBool flg = PETSC_TRUE;
385 char mesh_file_name[255];
386 CHKERR PetscOptionsGetString(PETSC_NULLPTR, PETSC_NULLPTR, "-my_file",
387 mesh_file_name, 255, &flg);
388 if (flg != PETSC_TRUE) {
389 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA,
390 "*** ERROR -my_file (MESH FILE NEEDED)");
391 }
392
393 const char *option;
394 option = "";
395 CHKERR moab.load_file(mesh_file_name, 0, option);
396
397 // Create mofem interface
398 MoFEM::Core core(moab);
399 MoFEM::Interface &m_field = core;
400
401 // Add meshsets with material and boundary conditions
402 MeshsetsManager *meshsets_manager_ptr;
403 CHKERR m_field.getInterface(meshsets_manager_ptr);
404 CHKERR meshsets_manager_ptr->setMeshsetFromFile();
405
406 PetscPrintf(PETSC_COMM_WORLD,
407 "Read meshsets add added meshsets for bc.cfg\n");
408 for (_IT_CUBITMESHSETS_FOR_LOOP_(m_field, it)) {
409 PetscPrintf(PETSC_COMM_WORLD, "%s",
410 static_cast<std::ostringstream &>(
411 std::ostringstream().seekp(0) << *it << endl)
412 .str()
413 .c_str());
414 cerr << *it << endl;
415 }
416
417 // set entities bit level
418 BitRefLevel ref_level;
419 ref_level.set(0);
420 CHKERR m_field.getInterface<BitRefManager>()->setBitRefLevelByDim(
421 0, 3, ref_level);
422
423 // set app. order
424 // see Hierarchic Finite Element Bases on Unstructured Tetrahedral Meshes
425 // (Mark Ainsworth & Joe Coyle)
426 PetscInt order;
427 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, PETSC_NULLPTR, "-my_order", &order,
428 &flg);
429 if (flg != PETSC_TRUE) {
430 order = 0;
431 }
432
433 // finite elements
434
435 BcFluxMap bc_flux_map;
436 MyTransport ufe(m_field, bc_flux_map);
437
438 // Initially calculate problem on coarse mesh
439
440 CHKERR ufe.addFields("VALUES", "FLUXES", order);
441 CHKERR ufe.addFiniteElements("FLUXES", "VALUES");
442 // Set boundary conditions
443 CHKERR ufe.addBoundaryElements(ref_level);
444 CHKERR ufe.buildProblem(ref_level);
448 CHKERR ufe.evaluateError();
450 CHKERR ufe.postProc("out_0.h5m");
451
452 int nb_levels = 5; // default number of refinement levels
453 // get number of refinement levels form command line
454 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, PETSC_NULLPTR, "-nb_levels", &nb_levels,
455 PETSC_NULLPTR);
456
457 // refine mesh, solve problem and do it again until number of refinement
458 // levels are exceeded.
459 for (int ll = 1; ll != nb_levels; ll++) {
460 const int nb_levels = ll;
461 CHKERR ufe.squashBits();
462 CHKERR ufe.refineMesh(ufe, nb_levels, order);
463 ref_level = BitRefLevel().set(nb_levels);
464 bc_flux_map.clear();
465 CHKERR ufe.addBoundaryElements(ref_level);
466 CHKERR ufe.buildProblem(ref_level);
470 CHKERR ufe.evaluateError();
472 CHKERR ufe.postProc(
473 static_cast<std::ostringstream &>(std::ostringstream().seekp(0)
474 << "out_" << nb_levels << ".h5m")
475 .str());
476 }
477 }
479
481
482 return 0;
483}
Mix implementation of transport element.
int main()
#define CATCH_ERRORS
Catch errors.
#define BITREFLEVEL_SIZE
max number of refinements
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ TEMPERATURESET
@ HEATFLUXSET
@ NODESET
@ SIDESET
@ MAT_THERMALSET
block name is "MAT_THERMAL"
@ BLOCKSET
@ 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.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
constexpr int order
virtual const RefEntity_multiIndex * get_ref_ents() const =0
Get the ref ents object.
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 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.
#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_FOR_LOOP_(MESHSET_MANAGER, IT)
Iterator that loops over all the Cubit MeshSets in a moFEM field.
static char help[]
map< int, BcFluxData > BcFluxMap
auto bit
set bit
constexpr int nb_levels
Definition level_set.cpp:58
char mesh_file_name[255]
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
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
PetscErrorCode PetscOptionsGetString(PetscOptions *, const char pre[], const char name[], char str[], size_t size, PetscBool *set)
MoFEMErrorCode postProc(const string out_file)
Post process results.
MoFEMErrorCode destroyMatrices()
destroy matrices
MoFEMErrorCode evaluateError()
Calculate error on elements.
MoFEMErrorCode solveLinearProblem()
solve problem
MoFEMErrorCode createMatrices()
create matrices
MoFEMErrorCode calculateResidual()
calculate residual
MoFEMErrorCode addFiniteElements(const std::string &fluxes_name, const std::string &values_name)
add finite elements
MoFEMErrorCode addFields(const std::string &values, const std::string &fluxes, const int order)
Add fields to database.
std::map< int, BlockData > setOfBlocks
maps block set id with appropriate BlockData
MoFEMErrorCode buildProblem(BitRefLevel &ref_level)
Build problem.
Managing BitRefLevels.
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:118
Deprecated interface functions.
Definition of the heat flux bc data structure.
Definition BCData.hpp:423
Thermal material data structure.
Mesh refinement interface.
MoFEMErrorCode refineTets(const EntityHandle meshset, const BitRefLevel &bit, int verb=QUIET, const bool debug=false)
refine TET in the meshset
MoFEMErrorCode addVerticesInTheMiddleOfEdges(const EntityHandle meshset, const BitRefLevel &bit, const bool recursive=false, int verb=QUIET, EntityHandle start_v=0)
make vertices in the middle of edges in meshset and add them to refinement levels defined by bit
Interface for managing meshsets containing materials and boundary conditions.
MoFEMErrorCode setMeshsetFromFile(const string file_name, const bool clean_file_options=true)
add blocksets reading config file
Struct keeps handle to refined handle.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
Application of mix transport data structure.
MoFEMErrorCode updateMeshsetsFieldsAndElements(const int nb_levels)
update meshsets with new entities after mesh refinement
MyTransport(MoFEM::Interface &m_field, BcFluxMap &bc_flux_map)
MoFEMErrorCode getBcOnValues(const EntityHandle ent, const double x, const double y, const double z, double &value)
natural (Dirihlet) boundary conditions (set values)
MoFEMErrorCode addBoundaryElements(BitRefLevel &ref_level)
set-up boundary conditions
MoFEMErrorCode getBcOnFluxes(const EntityHandle ent, const double x, const double y, const double z, double &flux)
essential (Neumann) boundary condition (set fluxes)
MoFEMErrorCode squashBits()
Squash bits of entities.
MoFEMErrorCode refineMesh(MixTransportElement &ufe, const int nb_levels, const int order)
Refine mesh.
MoFEMErrorCode getSource(EntityHandle ent, const double x, const double y, const double z, double &flux)
set source term