v0.14.0
Loading...
Searching...
No Matches
thermo_elastic.cpp
Go to the documentation of this file.
1/**
2 * \file thermo_elastic.cpp
3 * \example thermo_elastic.cpp
4 *
5 * Thermo plasticity
6 *
7 */
8
9#ifndef EXECUTABLE_DIMENSION
10 #define EXECUTABLE_DIMENSION 3
11#endif
12
13#include <MoFEM.hpp>
14using namespace MoFEM;
15
16#include <ThermalConvection.hpp>
17#include <ThermalRadiation.hpp>
18
19constexpr int SPACE_DIM =
20 EXECUTABLE_DIMENSION; //< Space dimension of problem, mesh
21
24using DomainEleOp = DomainEle::UserDataOperator;
27using BoundaryEleOp = BoundaryEle::UserDataOperator;
31
34
35//! [Linear elastic problem]
37 GAUSS>::OpGradSymTensorGrad<1, SPACE_DIM, SPACE_DIM,
38 0>; //< Elastic stiffness matrix
41 GAUSS>::OpGradTimesSymTensor<1, SPACE_DIM,
42 SPACE_DIM>; //< Elastic internal forces
43//! [Linear elastic problem]
44
45//! [Thermal problem]
46/**
47 * @brief Integrate Lhs base of flux (1/k) base of flux (FLUX x FLUX)
48 *
49 */
52
53/**
54 * @brief Integrate Lhs div of base of flux time base of temperature (FLUX x T)
55 * and transpose of it, i.e. (T x FLAX)
56 *
57 */
59 GAUSS>::OpMixDivTimesScalar<SPACE_DIM>;
60
61/**
62 * @brief Integrate Lhs base of temperature times (heat capacity) times base of
63 * temperature (T x T)
64 *
65 */
68
69/**
70 * @brief Integrating Rhs flux base (1/k) flux (FLUX)
71 */
73 GAUSS>::OpBaseTimesVector<3, SPACE_DIM, 1>;
74
75/**
76 * @brief Integrate Rhs div flux base times temperature (T)
77 *
78 */
80 GAUSS>::OpMixDivTimesU<3, 1, SPACE_DIM>;
81
82/**
83 * @brief Integrate Rhs base of temperature time heat capacity times heat rate
84 * (T)
85 *
86 */
88 GAUSS>::OpBaseTimesScalar<1>;
89
90/**
91 * @brief Integrate Rhs base of temperature times divergence of flux (T)
92 *
93 */
95
96//! [Thermal problem]
97
98//! [Body and heat source]
107//! [Body and heat source]
108
109//! [Natural boundary conditions]
113
114//! [Natural boundary conditions]
115
116//! [Essential boundary conditions (Least square approach)]
119 GAUSS>::OpEssentialRhs<HeatFluxCubitBcData, 3, SPACE_DIM>;
122 GAUSS>::OpEssentialLhs<HeatFluxCubitBcData, 3, SPACE_DIM>;
123//! [Essential boundary conditions (Least square approach)]
124
127double ref_temp = 0.0;
128double init_temp = 0.0;
129
130PetscBool is_plane_strain = PETSC_FALSE;
131
134 1; // Force / (time temperature ) or Power /
135 // (length temperature) // Time unit is hour. force unit kN
136double default_heat_capacity = 1; // length^2/(time^2 temperature) // length is
137 // millimeter time is hour
138
139int order_temp = 2; //< default approximation order for the temperature field
140int order_flux = 3; //< default approximation order for heat flux field
141int order_disp = 3; //< default approximation order for the displacement field
142
143int atom_test = 0;
144
145int save_every = 1; //< Save every n-th step
148
149#include <ThermoElasticOps.hpp> //< additional coupling operators
150using namespace ThermoElasticOps; //< name space of coupling operators
151
156
157auto save_range = [](moab::Interface &moab, const std::string name,
158 const Range r) {
160 auto out_meshset = get_temp_meshset_ptr(moab);
161 CHKERR moab.add_entities(*out_meshset, r);
162 CHKERR moab.write_file(name.c_str(), "VTK", "", out_meshset->get_ptr(), 1);
164};
165
167
169
171
172private:
174
175 PetscBool doEvalField;
176 std::array<double, SPACE_DIM> fieldEvalCoords;
177 boost::shared_ptr<FieldEvaluatorInterface::SetPtsData> fieldEvalData;
178
179 boost::shared_ptr<VectorDouble> tempFieldPtr;
180 boost::shared_ptr<MatrixDouble> fluxFieldPtr;
181 boost::shared_ptr<MatrixDouble> dispFieldPtr;
182 boost::shared_ptr<MatrixDouble> dispGradPtr;
183 boost::shared_ptr<MatrixDouble> strainFieldPtr;
184 boost::shared_ptr<MatrixDouble> stressFieldPtr;
185
186 MoFEMErrorCode setupProblem(); ///< add fields
188 getCommandLineParameters(); //< read parameters from command line
189 MoFEMErrorCode bC(); //< read boundary conditions
190 MoFEMErrorCode OPs(); //< add operators to pipeline
191 MoFEMErrorCode tsSolve(); //< time solver
192
194 : public boost::enable_shared_from_this<BlockedParameters> {
199
200 inline auto getDPtr() {
201 return boost::shared_ptr<MatrixDouble>(shared_from_this(), &mD);
202 }
203
204 inline auto getCoeffExpansionPtr() {
205 return boost::shared_ptr<VectorDouble>(shared_from_this(),
207 }
208
210 return boost::shared_ptr<double>(shared_from_this(), &heatConductivity);
211 }
212
213 inline auto getHeatCapacityPtr() {
214 return boost::shared_ptr<double>(shared_from_this(), &heatCapacity);
215 }
216 };
217
219 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
220 std::string block_elastic_name, std::string block_thermal_name,
221 boost::shared_ptr<BlockedParameters> blockedParamsPtr, Sev sev);
222};
223
225 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
226 std::string block_elastic_name, std::string block_thermal_name,
227 boost::shared_ptr<BlockedParameters> blockedParamsPtr, Sev sev) {
229
230 struct OpMatElasticBlocks : public DomainEleOp {
231 OpMatElasticBlocks(boost::shared_ptr<MatrixDouble> m, double bulk_modulus_K,
232 double shear_modulus_G, MoFEM::Interface &m_field,
233 Sev sev,
234 std::vector<const CubitMeshSets *> meshset_vec_ptr)
235 : DomainEleOp(NOSPACE, DomainEleOp::OPSPACE), matDPtr(m),
236 bulkModulusKDefault(bulk_modulus_K),
237 shearModulusGDefault(shear_modulus_G) {
238 CHK_THROW_MESSAGE(extractElasticBlockData(m_field, meshset_vec_ptr, sev),
239 "Can not get data from block");
240 }
241
242 MoFEMErrorCode doWork(int side, EntityType type,
245
246 for (auto &b : blockData) {
247
248 if (b.blockEnts.find(getFEEntityHandle()) != b.blockEnts.end()) {
249 CHKERR getMatDPtr(matDPtr, b.bulkModulusK, b.shearModulusG);
251 }
252 }
253
254 CHKERR getMatDPtr(matDPtr, bulkModulusKDefault, shearModulusGDefault);
256 }
257
258 private:
259 boost::shared_ptr<MatrixDouble> matDPtr;
260
261 struct BlockData {
262 double bulkModulusK;
263 double shearModulusG;
264 Range blockEnts;
265 };
266
267 double bulkModulusKDefault;
268 double shearModulusGDefault;
269 std::vector<BlockData> blockData;
270
272 extractElasticBlockData(MoFEM::Interface &m_field,
273 std::vector<const CubitMeshSets *> meshset_vec_ptr,
274 Sev sev) {
276
277 for (auto m : meshset_vec_ptr) {
278 MOFEM_TAG_AND_LOG("WORLD", sev, "Mat Elastic Block") << *m;
279 std::vector<double> block_data;
280 CHKERR m->getAttributes(block_data);
281 if (block_data.size() < 2) {
282 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
283 "Expected that block has two attributes");
284 }
285 auto get_block_ents = [&]() {
286 Range ents;
287 CHKERR
288 m_field.get_moab().get_entities_by_handle(m->meshset, ents, true);
289 return ents;
290 };
291
292 double young_modulus = block_data[0];
293 double poisson_ratio = block_data[1];
294 double bulk_modulus_K = young_modulus / (3 * (1 - 2 * poisson_ratio));
295 double shear_modulus_G = young_modulus / (2 * (1 + poisson_ratio));
296
297 MOFEM_TAG_AND_LOG("WORLD", sev, "Mat Elastic Block")
298 << m->getName() << ": E = " << young_modulus
299 << " nu = " << poisson_ratio;
300
301 blockData.push_back(
302 {bulk_modulus_K, shear_modulus_G, get_block_ents()});
303 }
304 MOFEM_LOG_CHANNEL("WORLD");
306 }
307
308 MoFEMErrorCode getMatDPtr(boost::shared_ptr<MatrixDouble> mat_D_ptr,
309 double bulk_modulus_K, double shear_modulus_G) {
311 //! [Calculate elasticity tensor]
312 auto set_material_stiffness = [&]() {
318 double A = 1;
319 if (SPACE_DIM == 2 && !is_plane_strain) {
320 A = 2 * shear_modulus_G /
321 (bulk_modulus_K + (4. / 3.) * shear_modulus_G);
322 }
324 t_D(i, j, k, l) =
325 2 * shear_modulus_G * ((t_kd(i, k) ^ t_kd(j, l)) / 4.) +
326 A * (bulk_modulus_K - (2. / 3.) * shear_modulus_G) * t_kd(i, j) *
327 t_kd(k, l);
328 };
329 //! [Calculate elasticity tensor]
330 constexpr auto size_symm = (SPACE_DIM * (SPACE_DIM + 1)) / 2;
331 mat_D_ptr->resize(size_symm * size_symm, 1);
332 set_material_stiffness();
334 }
335 };
336
337 double default_bulk_modulus_K =
339 double default_shear_modulus_G =
341
342 pipeline.push_back(new OpMatElasticBlocks(
343 blockedParamsPtr->getDPtr(), default_bulk_modulus_K,
344 default_shear_modulus_G, mField, sev,
345
346 // Get blockset using regular expression
348
349 (boost::format("%s(.*)") % block_elastic_name).str()
350
351 ))
352
353 ));
354
355 struct OpMatThermalBlocks : public DomainEleOp {
356 OpMatThermalBlocks(boost::shared_ptr<VectorDouble> expansion_ptr,
357 boost::shared_ptr<double> conductivity_ptr,
358 boost::shared_ptr<double> capacity_ptr,
359 MoFEM::Interface &m_field, Sev sev,
360 std::vector<const CubitMeshSets *> meshset_vec_ptr)
361 : DomainEleOp(NOSPACE, DomainEleOp::OPSPACE),
362 expansionPtr(expansion_ptr), conductivityPtr(conductivity_ptr),
363 capacityPtr(capacity_ptr) {
364 CHK_THROW_MESSAGE(extractThermallockData(m_field, meshset_vec_ptr, sev),
365 "Can not get data from block");
366 }
367
368 MoFEMErrorCode doWork(int side, EntityType type,
371
372 for (auto &b : blockData) {
373
374 if (b.blockEnts.find(getFEEntityHandle()) != b.blockEnts.end()) {
375 *expansionPtr = b.expansion;
376 *conductivityPtr = b.conductivity;
377 *capacityPtr = b.capacity;
379 }
380 }
381
383 *conductivityPtr = default_heat_conductivity;
384 *capacityPtr = default_heat_capacity;
385
387 }
388
389 private:
390 struct BlockData {
391 double conductivity;
392 double capacity;
393 VectorDouble expansion;
394 Range blockEnts;
395 };
396
397 std::vector<BlockData> blockData;
398
400 extractThermallockData(MoFEM::Interface &m_field,
401 std::vector<const CubitMeshSets *> meshset_vec_ptr,
402 Sev sev) {
404
405 for (auto m : meshset_vec_ptr) {
406 MOFEM_TAG_AND_LOG("WORLD", sev, "Mat Thermal Block") << *m;
407 std::vector<double> block_data;
408 CHKERR m->getAttributes(block_data);
409 if (block_data.size() < 3) {
410 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
411 "Expected that block has at least three attributes");
412 }
413 auto get_block_ents = [&]() {
414 Range ents;
415 CHKERR
416 m_field.get_moab().get_entities_by_handle(m->meshset, ents, true);
417 return ents;
418 };
419
420 auto get_expansion = [&]() {
421 VectorDouble expansion(SPACE_DIM, block_data[2]);
422 if (block_data.size() > 3) {
423 expansion[1] = block_data[3];
424 }
425 if (SPACE_DIM == 3 && block_data.size() > 4) {
426 expansion[2] = block_data[4];
427 }
428 return expansion;
429 };
430
431 auto coeff_exp_vec = get_expansion();
432
433 MOFEM_TAG_AND_LOG("WORLD", sev, "Mat Thermal Block")
434 << m->getName() << ": conductivity = " << block_data[0]
435 << " capacity = " << block_data[1]
436 << " expansion = " << coeff_exp_vec;
437
438 blockData.push_back(
439 {block_data[0], block_data[1], coeff_exp_vec, get_block_ents()});
440 }
441 MOFEM_LOG_CHANNEL("WORLD");
443 }
444
445 boost::shared_ptr<VectorDouble> expansionPtr;
446 boost::shared_ptr<double> conductivityPtr;
447 boost::shared_ptr<double> capacityPtr;
448 };
449
450 pipeline.push_back(new OpMatThermalBlocks(
451 blockedParamsPtr->getCoeffExpansionPtr(),
452 blockedParamsPtr->getHeatConductivityPtr(),
453 blockedParamsPtr->getHeatCapacityPtr(), mField, sev,
454
455 // Get blockset using regular expression
457
458 (boost::format("%s(.*)") % block_thermal_name).str()
459
460 ))
461
462 ));
463
465}
466
467//! [Run problem]
477//! [Run problem]
478
479//! [Get command line parameters]
482
483 auto get_command_line_parameters = [&]() {
485
486 CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-order", &order_temp,
487 PETSC_NULL);
488 CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-order_temp", &order_temp,
489 PETSC_NULL);
491 CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-order_flux", &order_flux,
492 PETSC_NULL);
494 CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-order_disp", &order_disp,
495 PETSC_NULL);
496 CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-atom_test", &atom_test,
497 PETSC_NULL);
498 CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-save_every", &save_every,
499 PETSC_NULL);
500
501 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-young_modulus",
502 &default_young_modulus, PETSC_NULL);
503 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-poisson_ratio",
504 &default_poisson_ratio, PETSC_NULL);
505 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-plane_strain",
506 &is_plane_strain, PETSC_NULL);
507 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-coeff_expansion",
508 &default_coeff_expansion, PETSC_NULL);
509 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-ref_temp", &ref_temp,
510 PETSC_NULL);
511 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-init_temp", &init_temp,
512 PETSC_NULL);
513
514 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-capacity",
515 &default_heat_capacity, PETSC_NULL);
516 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-conductivity",
517 &default_heat_conductivity, PETSC_NULL);
518
519 if constexpr (SPACE_DIM == 2) {
520 do_output_domain = PETSC_TRUE;
521 do_output_skin = PETSC_FALSE;
522 } else {
523 do_output_domain = PETSC_FALSE;
524 do_output_skin = PETSC_TRUE;
525 }
526
527 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-output_domain",
528 &do_output_domain, PETSC_NULL);
529 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-output_skin", &do_output_skin,
530 PETSC_NULL);
531
532 MOFEM_LOG("ThermoElastic", Sev::inform)
533 << "Default Young's modulus " << default_young_modulus;
534 MOFEM_LOG("ThermoElastic", Sev::inform)
535 << "DefaultPoisson ratio " << default_poisson_ratio;
536 MOFEM_LOG("ThermoElastic", Sev::inform)
537 << "Default coeff of expansion " << default_coeff_expansion;
538 MOFEM_LOG("ThermoElastic", Sev::inform)
539 << "Default heat capacity " << default_heat_capacity;
540 MOFEM_LOG("ThermoElastic", Sev::inform)
541 << "Default heat conductivity " << default_heat_conductivity;
542
543 MOFEM_LOG("ThermoElastic", Sev::inform)
544 << "Reference temperature " << ref_temp;
545 MOFEM_LOG("ThermoElastic", Sev::inform)
546 << "Initial temperature " << init_temp;
547
549 };
550
551 CHKERR get_command_line_parameters();
552
554}
555//! [Get command line parameters]
556
557//! [Set up problem]
561 // Add field
563 // Mechanical fields
564 CHKERR simple->addDomainField("U", H1, AINSWORTH_LEGENDRE_BASE, SPACE_DIM);
565 CHKERR simple->addBoundaryField("U", H1, AINSWORTH_LEGENDRE_BASE, SPACE_DIM);
566 // Temperature
567 constexpr auto flux_space = (SPACE_DIM == 2) ? HCURL : HDIV;
568 CHKERR simple->addDomainField("T", L2, base, 1);
569 CHKERR simple->addDomainField("FLUX", flux_space, base, 1);
570 CHKERR simple->addBoundaryField("FLUX", flux_space, base, 1);
571 CHKERR simple->addBoundaryField("TBC", L2, base, 1);
572
573 CHKERR simple->setFieldOrder("U", order_disp);
574 CHKERR simple->setFieldOrder("FLUX", order_flux);
575 CHKERR simple->setFieldOrder("T", order_temp);
576 CHKERR simple->setFieldOrder("TBC", order_temp);
577
578 CHKERR simple->setUp();
579
580 int coords_dim = SPACE_DIM;
581 CHKERR PetscOptionsGetRealArray(NULL, NULL, "-field_eval_coords",
582 fieldEvalCoords.data(), &coords_dim,
583 &doEvalField);
584
585 tempFieldPtr = boost::make_shared<VectorDouble>();
586 fluxFieldPtr = boost::make_shared<MatrixDouble>();
587 dispFieldPtr = boost::make_shared<MatrixDouble>();
588 dispGradPtr = boost::make_shared<MatrixDouble>();
589 strainFieldPtr = boost::make_shared<MatrixDouble>();
590 stressFieldPtr = boost::make_shared<MatrixDouble>();
591
592 if (doEvalField) {
594 mField.getInterface<FieldEvaluatorInterface>()->getData<DomainEle>();
595
596 if constexpr (SPACE_DIM == 3) {
598 fieldEvalData, simple->getDomainFEName());
599 } else {
601 fieldEvalData, simple->getDomainFEName());
602 }
603
604 fieldEvalData->setEvalPoints(fieldEvalCoords.data(), 1);
605 auto no_rule = [](int, int, int) { return -1; };
606
607 auto field_eval_fe_ptr = fieldEvalData->feMethodPtr.lock();
608 field_eval_fe_ptr->getRuleHook = no_rule;
609
610 auto block_params = boost::make_shared<BlockedParameters>();
611 auto mDPtr = block_params->getDPtr();
612 auto coeff_expansion_ptr = block_params->getCoeffExpansionPtr();
613
614 CHKERR addMatBlockOps(field_eval_fe_ptr->getOpPtrVector(), "MAT_ELASTIC",
615 "MAT_THERMAL", block_params, Sev::verbose);
616
618 field_eval_fe_ptr->getOpPtrVector(), {H1, HDIV});
619
620 field_eval_fe_ptr->getOpPtrVector().push_back(
622 field_eval_fe_ptr->getOpPtrVector().push_back(
624 field_eval_fe_ptr->getOpPtrVector().push_back(
626 field_eval_fe_ptr->getOpPtrVector().push_back(
628 dispGradPtr));
629 field_eval_fe_ptr->getOpPtrVector().push_back(
631 field_eval_fe_ptr->getOpPtrVector().push_back(
633 coeff_expansion_ptr, stressFieldPtr));
634 }
635
637}
638//! [Set up problem]
639
640//! [Boundary condition]
643
644 MOFEM_LOG("SYNC", Sev::noisy) << "bC";
646
648 auto bc_mng = mField.getInterface<BcManager>();
649
650 auto get_skin = [&]() {
651 Range body_ents;
652 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, body_ents);
653 Skinner skin(&mField.get_moab());
654 Range skin_ents;
655 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
656 return skin_ents;
657 };
658
659 auto filter_flux_blocks = [&](auto skin, bool temp_bc = false) {
660 auto remove_cubit_blocks = [&](auto c) {
662 for (auto m :
663
665
666 ) {
667 Range ents;
668 CHKERR mField.get_moab().get_entities_by_dimension(
669 m->getMeshset(), SPACE_DIM - 1, ents, true);
670 skin = subtract(skin, ents);
671 }
673 };
674
675 auto remove_named_blocks = [&](auto n) {
678 std::regex(
679
680 (boost::format("%s(.*)") % n).str()
681
682 ))
683
684 ) {
685 Range ents;
686 CHKERR mField.get_moab().get_entities_by_dimension(
687 m->getMeshset(), SPACE_DIM - 1, ents, true);
688 skin = subtract(skin, ents);
689 }
691 };
692 if (!temp_bc) {
693 CHK_THROW_MESSAGE(remove_cubit_blocks(NODESET | TEMPERATURESET),
694 "remove_cubit_blocks");
695 CHK_THROW_MESSAGE(remove_named_blocks("TEMPERATURE"),
696 "remove_named_blocks");
697 }
698 CHK_THROW_MESSAGE(remove_cubit_blocks(SIDESET | HEATFLUXSET),
699 "remove_cubit_blocks");
700 CHK_THROW_MESSAGE(remove_named_blocks("HEATFLUX"), "remove_named_blocks");
701 CHK_THROW_MESSAGE(remove_named_blocks("CONVECTION"), "remove_named_blocks");
702 CHK_THROW_MESSAGE(remove_named_blocks("RADIATION"), "remove_named_blocks");
703 return skin;
704 };
705
706 auto filter_true_skin = [&](auto skin) {
707 Range boundary_ents;
708 ParallelComm *pcomm =
709 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
710 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
711 PSTATUS_NOT, -1, &boundary_ents);
712 return boundary_ents;
713 };
714
715 auto remove_flux_ents = filter_true_skin(filter_flux_blocks(get_skin()));
716 auto remove_temp_bc_ents =
717 filter_true_skin(filter_flux_blocks(get_skin(), true));
718
719 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
720 remove_flux_ents);
721 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
722 remove_temp_bc_ents);
723
724 MOFEM_LOG("SYNC", Sev::noisy) << remove_flux_ents << endl;
726
727 MOFEM_LOG("SYNC", Sev::noisy) << remove_temp_bc_ents << endl;
729
730#ifndef NDEBUG
731
734 (boost::format("flux_remove_%d.vtk") % mField.get_comm_rank()).str(),
735 remove_flux_ents);
736
739 (boost::format("temp_bc_remove_%d.vtk") % mField.get_comm_rank()).str(),
740 remove_temp_bc_ents);
741
742#endif
743
744 CHKERR mField.getInterface<ProblemsManager>()->removeDofsOnEntities(
745 simple->getProblemName(), "FLUX", remove_flux_ents);
746 CHKERR mField.getInterface<ProblemsManager>()->removeDofsOnEntities(
747 simple->getProblemName(), "TBC", remove_temp_bc_ents);
748
749 auto set_init_temp = [](boost::shared_ptr<FieldEntity> field_entity_ptr) {
750 field_entity_ptr->getEntFieldData()[0] = init_temp;
751 return 0;
752 };
753 CHKERR mField.getInterface<FieldBlas>()->fieldLambdaOnEntities(set_init_temp,
754 "T");
755
756 CHKERR bc_mng->removeBlockDOFsOnEntities<DisplacementCubitBcData>(
757 simple->getProblemName(), "U");
758 CHKERR bc_mng->pushMarkDOFsOnEntities<HeatFluxCubitBcData>(
759 simple->getProblemName(), "FLUX", false);
760
762}
763//! [Boundary condition]
764
765//! [Push operators to pipeline]
768
769 MOFEM_LOG("SYNC", Sev::noisy) << "OPs";
771
772 auto pipeline_mng = mField.getInterface<PipelineManager>();
774 auto bc_mng = mField.getInterface<BcManager>();
775
776 auto boundary_marker =
777 bc_mng->getMergedBlocksMarker(vector<string>{"HEATFLUX"});
778
779 auto integration_rule = [](int, int, int approx_order) {
780 return 2 * approx_order;
781 };
782 CHKERR pipeline_mng->setDomainRhsIntegrationRule(integration_rule);
783 CHKERR pipeline_mng->setDomainLhsIntegrationRule(integration_rule);
784 CHKERR pipeline_mng->setBoundaryRhsIntegrationRule(integration_rule);
785 CHKERR pipeline_mng->setBoundaryLhsIntegrationRule(integration_rule);
786
787 auto block_params = boost::make_shared<BlockedParameters>();
788 auto mDPtr = block_params->getDPtr();
789 auto coeff_expansion_ptr = block_params->getCoeffExpansionPtr();
790 auto heat_conductivity_ptr = block_params->getHeatConductivityPtr();
791 auto heat_capacity_ptr = block_params->getHeatCapacityPtr();
792
793 // Default time scaling of BCs and sources, from command line arguments
794 auto time_scale =
795 boost::make_shared<TimeScale>("", false, [](const double) { return 1; });
796 auto def_time_scale = [time_scale](const double time) {
797 return (!time_scale->argFileScale) ? time : 1;
798 };
799 auto def_file_name = [time_scale](const std::string &&name) {
800 return (!time_scale->argFileScale) ? name : "";
801 };
802
803 // Files which define scaling for separate variables, if provided
804 auto time_bodyforce_scaling = boost::make_shared<TimeScale>(
805 def_file_name("bodyforce_scale.txt"), false, def_time_scale);
806 auto time_heatsource_scaling = boost::make_shared<TimeScale>(
807 def_file_name("heatsource_scale.txt"), false, def_time_scale);
808 auto time_temperature_scaling = boost::make_shared<TimeScale>(
809 def_file_name("temperature_bc_scale.txt"), false, def_time_scale);
810 auto time_displacement_scaling = boost::make_shared<TimeScale>(
811 def_file_name("displacement_bc_scale.txt"), false, def_time_scale);
812 auto time_flux_scaling = boost::make_shared<TimeScale>(
813 def_file_name("flux_bc_scale.txt"), false, def_time_scale);
814 auto time_force_scaling = boost::make_shared<TimeScale>(
815 def_file_name("force_bc_scale.txt"), false, def_time_scale);
816
817 auto add_domain_rhs_ops = [&](auto &pipeline) {
819 CHKERR addMatBlockOps(pipeline, "MAT_ELASTIC", "MAT_THERMAL", block_params,
820 Sev::inform);
822
823 auto mat_grad_ptr = boost::make_shared<MatrixDouble>();
824 auto mat_strain_ptr = boost::make_shared<MatrixDouble>();
825 auto mat_stress_ptr = boost::make_shared<MatrixDouble>();
826
827 auto vec_temp_ptr = boost::make_shared<VectorDouble>();
828 auto vec_temp_dot_ptr = boost::make_shared<VectorDouble>();
829 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
830 auto vec_temp_div_ptr = boost::make_shared<VectorDouble>();
831
832 pipeline.push_back(new OpCalculateScalarFieldValues("T", vec_temp_ptr));
833 pipeline.push_back(
834 new OpCalculateScalarFieldValuesDot("T", vec_temp_dot_ptr));
836 "FLUX", vec_temp_div_ptr));
837 pipeline.push_back(
838 new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", mat_flux_ptr));
839
841 "U", mat_grad_ptr));
842 pipeline.push_back(
843 new OpSymmetrizeTensor<SPACE_DIM>(mat_grad_ptr, mat_strain_ptr));
844 pipeline.push_back(new OpStressThermal(mat_strain_ptr, vec_temp_ptr, mDPtr,
845 coeff_expansion_ptr,
846 mat_stress_ptr));
847
848 pipeline.push_back(new OpInternalForceCauchy(
849 "U", mat_stress_ptr,
850 [](double, double, double) constexpr { return 1; }));
851
852 auto resistance = [heat_conductivity_ptr](const double, const double,
853 const double) {
854 return (1. / (*heat_conductivity_ptr));
855 };
856 // negative value is consequence of symmetric system
857 auto capacity = [heat_capacity_ptr](const double, const double,
858 const double) {
859 return -(*heat_capacity_ptr);
860 };
861 auto unity = [](const double, const double, const double) constexpr {
862 return -1.;
863 };
864 pipeline.push_back(new OpHdivFlux("FLUX", mat_flux_ptr, resistance));
865 pipeline.push_back(new OpHDivTemp("FLUX", vec_temp_ptr, unity));
866 pipeline.push_back(new OpBaseDivFlux("T", vec_temp_div_ptr, unity));
867 pipeline.push_back(new OpBaseDotT("T", vec_temp_dot_ptr, capacity));
868
869 // Set source terms
871 pipeline, mField, "T", {time_scale, time_heatsource_scaling},
872 "HEAT_SOURCE", Sev::inform);
874 pipeline, mField, "U", {time_scale, time_bodyforce_scaling},
875 "BODY_FORCE", Sev::inform);
877 pipeline, mField, "T", vec_temp_ptr, "SETTEMP", Sev::inform);
878
880 };
881
882 auto add_domain_lhs_ops = [&](auto &pipeline) {
884 CHKERR addMatBlockOps(pipeline, "MAT_ELASTIC", "MAT_THERMAL", block_params,
885 Sev::verbose);
887
888 pipeline.push_back(new OpKCauchy("U", "U", mDPtr));
889 pipeline.push_back(new ThermoElasticOps::OpKCauchyThermoElasticity(
890 "U", "T", mDPtr, coeff_expansion_ptr));
891
892 auto resistance = [heat_conductivity_ptr](const double, const double,
893 const double) {
894 return (1. / (*heat_conductivity_ptr));
895 };
896 auto capacity = [heat_capacity_ptr](const double, const double,
897 const double) {
898 return -(*heat_capacity_ptr);
899 };
900 pipeline.push_back(new OpHdivHdiv("FLUX", "FLUX", resistance));
901 pipeline.push_back(
902 new OpHdivT("FLUX", "T", []() constexpr { return -1; }, true));
903
904 auto op_capacity = new OpCapacity("T", "T", capacity);
905 op_capacity->feScalingFun = [](const FEMethod *fe_ptr) {
906 return fe_ptr->ts_a;
907 };
908 pipeline.push_back(op_capacity);
909
910 auto vec_temp_ptr = boost::make_shared<VectorDouble>();
911 pipeline.push_back(new OpCalculateScalarFieldValues("T", vec_temp_ptr));
913 pipeline, mField, "T", vec_temp_ptr, "SETTEMP", Sev::verbose);
914
916 };
917
918 auto add_boundary_rhs_ops = [&](auto &pipeline) {
920
922
924 pipeline, mField, "U", {time_scale, time_force_scaling}, "FORCE",
925 Sev::inform);
926
927 // Temperature BC
928
929 using OpTemperatureBC =
932 pipeline, mField, "FLUX", {time_scale, time_temperature_scaling},
933 "TEMPERATURE", Sev::inform);
934
935 // Note: fluxes for temperature should be aggregated. Here separate is
936 // NaturalMeshsetType<HEATFLUXSET>, we should add version with BLOCKSET,
937 // convection, see example tutorials/vec-0/src/NaturalBoundaryBC.hpp.
938 // and vec-0/elastic.cpp
939
940 using OpFluxBC =
943 pipeline, mField, "TBC", {time_scale, time_flux_scaling}, "FLUX",
944 Sev::inform);
945
947 using OpConvectionRhsBC =
948 T::OpFlux<ThermoElasticOps::ConvectionBcType<BLOCKSET>, 1, 1>;
949 using OpRadiationRhsBC =
950 T::OpFlux<ThermoElasticOps::RadiationBcType<BLOCKSET>, 1, 1>;
951 auto temp_bc_ptr = boost::make_shared<VectorDouble>();
952 pipeline.push_back(new OpCalculateScalarFieldValues("TBC", temp_bc_ptr));
953 T::AddFluxToPipeline<OpConvectionRhsBC>::add(
954 pipeline, mField, "TBC", temp_bc_ptr, "CONVECTION", Sev::inform);
955 T::AddFluxToPipeline<OpRadiationRhsBC>::add(
956 pipeline, mField, "TBC", temp_bc_ptr, "RADIATION", Sev::inform);
957
958 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
959 pipeline.push_back(
960 new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", mat_flux_ptr));
961
962 // This is temporary implementation. It be moved to LinearFormsIntegrators,
963 // however for hybridised case, what is goal of this changes, such function
964 // is implemented for fluxes in broken space. Thus ultimately this operator
965 // would be not needed.
966
967 struct OpTBCTimesNormalFlux
968 : public FormsIntegrators<BoundaryEleOp>::Assembly<PETSC>::OpBase {
969
971
972 OpTBCTimesNormalFlux(const std::string field_name,
973 boost::shared_ptr<MatrixDouble> vec,
974 boost::shared_ptr<Range> ents_ptr = nullptr)
975 : OP(field_name, field_name, OP::OPROW, ents_ptr), sourceVec(vec) {}
976
977 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data) {
980 // get integration weights
981 auto t_w = OP::getFTensor0IntegrationWeight();
982 // get base function values on rows
983 auto t_row_base = row_data.getFTensor0N();
984 // get normal vector
985 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
986 // get vector values
987 auto t_vec = getFTensor1FromMat<SPACE_DIM, 1>(*sourceVec);
988 // loop over integration points
989 for (int gg = 0; gg != OP::nbIntegrationPts; gg++) {
990 // take into account Jacobian
991 const double alpha = t_w * (t_vec(i) * t_normal(i));
992 // loop over rows base functions
993 int rr = 0;
994 for (; rr != OP::nbRows; ++rr) {
995 OP::locF[rr] += alpha * t_row_base;
996 ++t_row_base;
997 }
998 for (; rr < OP::nbRowBaseFunctions; ++rr)
999 ++t_row_base;
1000 ++t_w; // move to another integration weight
1001 ++t_vec;
1002 ++t_normal;
1003 }
1004 EntityType fe_type = OP::getNumeredEntFiniteElementPtr()->getEntType();
1005 if (fe_type == MBTRI) {
1006 OP::locF /= 2;
1007 }
1009 }
1010
1011 protected:
1012 boost::shared_ptr<MatrixDouble> sourceVec;
1013 };
1014 pipeline.push_back(new OpTBCTimesNormalFlux("TBC", mat_flux_ptr));
1015
1016 struct OpBaseNormalTimesTBC
1017 : public FormsIntegrators<BoundaryEleOp>::Assembly<PETSC>::OpBase {
1018
1020
1021 OpBaseNormalTimesTBC(const std::string field_name,
1022 boost::shared_ptr<VectorDouble> vec,
1023 boost::shared_ptr<Range> ents_ptr = nullptr)
1024 : OP(field_name, field_name, OP::OPROW, ents_ptr), sourceVec(vec) {}
1025
1026 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data) {
1029 // get integration weights
1030 auto t_w = OP::getFTensor0IntegrationWeight();
1031 // get base function values on rows
1032 auto t_row_base = row_data.getFTensor1N<3>();
1033 // get normal vector
1034 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1035 // get vector values
1036 auto t_vec = getFTensor0FromVec(*sourceVec);
1037 // loop over integration points
1038 for (int gg = 0; gg != OP::nbIntegrationPts; gg++) {
1039 // take into account Jacobian
1040 const double alpha = t_w * t_vec;
1041 // loop over rows base functions
1042 int rr = 0;
1043 for (; rr != OP::nbRows; ++rr) {
1044 OP::locF[rr] += alpha * (t_row_base(i) * t_normal(i));
1045 ++t_row_base;
1046 }
1047 for (; rr < OP::nbRowBaseFunctions; ++rr)
1048 ++t_row_base;
1049 ++t_w; // move to another integration weight
1050 ++t_vec;
1051 ++t_normal;
1052 }
1053 EntityType fe_type = OP::getNumeredEntFiniteElementPtr()->getEntType();
1054 if (fe_type == MBTRI) {
1055 OP::locF /= 2;
1056 }
1058 }
1059
1060 protected:
1061 boost::shared_ptr<VectorDouble> sourceVec;
1062 };
1063
1064 pipeline.push_back(new OpBaseNormalTimesTBC("FLUX", temp_bc_ptr));
1065
1067 };
1068
1069 auto add_boundary_lhs_ops = [&](auto &pipeline) {
1071
1073
1074 using T =
1075 NaturalBC<BoundaryEleOp>::template Assembly<PETSC>::BiLinearForm<GAUSS>;
1076 using OpConvectionLhsBC =
1077 T::OpFlux<ThermoElasticOps::ConvectionBcType<BLOCKSET>, 1, 1>;
1078 using OpRadiationLhsBC =
1079 T::OpFlux<ThermoElasticOps::RadiationBcType<BLOCKSET>, 1, 1>;
1080 auto temp_bc_ptr = boost::make_shared<VectorDouble>();
1081 pipeline.push_back(new OpCalculateScalarFieldValues("TBC", temp_bc_ptr));
1082 T::AddFluxToPipeline<OpConvectionLhsBC>::add(pipeline, mField, "TBC", "TBC",
1083 "CONVECTION", Sev::verbose);
1084 T::AddFluxToPipeline<OpRadiationLhsBC>::add(
1085 pipeline, mField, "TBC", "TBC", temp_bc_ptr, "RADIATION", Sev::verbose);
1086
1087 // This is temporary implementation. It be moved to LinearFormsIntegrators,
1088 // however for hybridised case, what is goal of this changes, such function
1089 // is implemented for fluxes in broken space. Thus ultimately this operator
1090 // would be not needed.
1091
1092 struct OpTBCTimesNormalFlux
1093 : public FormsIntegrators<BoundaryEleOp>::Assembly<PETSC>::OpBase {
1094
1096
1097 OpTBCTimesNormalFlux(const std::string row_field_name,
1098 const std::string col_field_name,
1099 boost::shared_ptr<Range> ents_ptr = nullptr)
1100 : OP(row_field_name, col_field_name, OP::OPROWCOL, ents_ptr) {
1101 this->sYmm = false;
1102 this->assembleTranspose = true;
1103 this->onlyTranspose = false;
1104 }
1105
1106 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data,
1107 EntitiesFieldData::EntData &col_data) {
1109
1111
1112 // get integration weights
1113 auto t_w = OP::getFTensor0IntegrationWeight();
1114 // get base function values on rows
1115 auto t_row_base = row_data.getFTensor0N();
1116 // get normal vector
1117 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1118 // loop over integration points
1119 for (int gg = 0; gg != OP::nbIntegrationPts; gg++) {
1120 // loop over rows base functions
1121 auto a_mat_ptr = &*OP::locMat.data().begin();
1122 int rr = 0;
1123 for (; rr != OP::nbRows; rr++) {
1124 // take into account Jacobian
1125 const double alpha = t_w * t_row_base;
1126 // get column base functions values at gauss point gg
1127 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
1128 // loop over columns
1129 for (int cc = 0; cc != OP::nbCols; cc++) {
1130 // calculate element of local matrix
1131 // using L2 norm of normal vector for convenient area calculation
1132 // for quads, tris etc.
1133 *a_mat_ptr += alpha * (t_col_base(i) * t_normal(i));
1134 ++t_col_base;
1135 ++a_mat_ptr;
1136 }
1137 ++t_row_base;
1138 }
1139 for (; rr < OP::nbRowBaseFunctions; ++rr)
1140 ++t_row_base;
1141 ++t_normal;
1142 ++t_w; // move to another integration weight
1143 }
1144 EntityType fe_type = OP::getNumeredEntFiniteElementPtr()->getEntType();
1145 if (fe_type == MBTRI) {
1146 OP::locMat /= 2;
1147 }
1149 }
1150 };
1151
1152 pipeline.push_back(new OpTBCTimesNormalFlux("TBC", "FLUX"));
1153
1155 };
1156
1157 // Set BCs by eliminating degrees of freedom
1158 auto get_bc_hook_rhs = [&]() {
1160 mField, pipeline_mng->getDomainRhsFE(),
1161 {time_scale, time_displacement_scaling});
1162 return hook;
1163 };
1164 auto get_bc_hook_lhs = [&]() {
1166 mField, pipeline_mng->getDomainLhsFE(),
1167 {time_scale, time_displacement_scaling});
1168 return hook;
1169 };
1170
1171 pipeline_mng->getDomainRhsFE()->preProcessHook = get_bc_hook_rhs();
1172 pipeline_mng->getDomainLhsFE()->preProcessHook = get_bc_hook_lhs();
1173
1174 CHKERR add_domain_rhs_ops(pipeline_mng->getOpDomainRhsPipeline());
1175 CHKERR add_domain_lhs_ops(pipeline_mng->getOpDomainLhsPipeline());
1176 CHKERR add_boundary_rhs_ops(pipeline_mng->getOpBoundaryRhsPipeline());
1177 CHKERR add_boundary_lhs_ops(pipeline_mng->getOpBoundaryLhsPipeline());
1178
1180}
1181//! [Push operators to pipeline]
1182
1183//! [Solve]
1186
1189 ISManager *is_manager = mField.getInterface<ISManager>();
1190
1191 auto dm = simple->getDM();
1192 auto solver = pipeline_mng->createTSIM();
1193 auto snes_ctx_ptr = getDMSnesCtx(dm);
1194
1195 auto set_section_monitor = [&](auto solver) {
1197 SNES snes;
1198 CHKERR TSGetSNES(solver, &snes);
1199 CHKERR SNESMonitorSet(snes,
1200 (MoFEMErrorCode(*)(SNES, PetscInt, PetscReal,
1201 void *))MoFEMSNESMonitorFields,
1202 (void *)(snes_ctx_ptr.get()), nullptr);
1204 };
1205
1206 auto create_post_process_elements = [&]() {
1207 auto block_params = boost::make_shared<BlockedParameters>();
1208 auto mDPtr = block_params->getDPtr();
1209 auto coeff_expansion_ptr = block_params->getCoeffExpansionPtr();
1210 auto u_ptr = boost::make_shared<MatrixDouble>();
1211 auto mat_grad_ptr = boost::make_shared<MatrixDouble>();
1212 auto mat_strain_ptr = boost::make_shared<MatrixDouble>();
1213 auto mat_stress_ptr = boost::make_shared<MatrixDouble>();
1214 auto vec_temp_ptr = boost::make_shared<VectorDouble>();
1215 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
1216
1217 auto push_domain_ops = [&](auto &pp_fe) {
1219 auto &pip = pp_fe->getOpPtrVector();
1220
1221 CHKERR addMatBlockOps(pip, "MAT_ELASTIC", "MAT_THERMAL", block_params,
1222 Sev::verbose);
1223
1225
1226 pip.push_back(new OpCalculateScalarFieldValues("T", vec_temp_ptr));
1227 pip.push_back(
1228 new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", mat_flux_ptr));
1229
1230 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
1232 "U", mat_grad_ptr));
1233 pip.push_back(
1234 new OpSymmetrizeTensor<SPACE_DIM>(mat_grad_ptr, mat_strain_ptr));
1235 pip.push_back(new OpStressThermal(mat_strain_ptr, vec_temp_ptr, mDPtr,
1236 coeff_expansion_ptr, mat_stress_ptr));
1238 };
1239
1240 auto push_post_proc_ops = [&](auto &pp_fe) {
1242 auto &pip = pp_fe->getOpPtrVector();
1244
1245 pip.push_back(
1246
1247 new OpPPMap(
1248
1249 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
1250
1251 {{"T", vec_temp_ptr}},
1252
1253 {{"U", u_ptr}, {"FLUX", mat_flux_ptr}},
1254
1255 {},
1256
1257 {{"STRAIN", mat_strain_ptr}, {"STRESS", mat_stress_ptr}}
1258
1259 )
1260
1261 );
1263 };
1264
1265 auto domain_post_proc = [&]() {
1266 if (do_output_domain == PETSC_FALSE)
1267 return boost::shared_ptr<PostProcEle>();
1268 auto pp_fe = boost::make_shared<PostProcEle>(mField);
1269 CHK_MOAB_THROW(push_domain_ops(pp_fe),
1270 "push domain ops to domain element");
1271 CHK_MOAB_THROW(push_post_proc_ops(pp_fe),
1272 "push post proc ops to domain element");
1273 return pp_fe;
1274 };
1275
1276 auto skin_post_proc = [&]() {
1277 if (do_output_skin == PETSC_FALSE)
1278 return boost::shared_ptr<SkinPostProcEle>();
1279 auto pp_fe = boost::make_shared<SkinPostProcEle>(mField);
1280 auto simple = mField.getInterface<Simple>();
1281 auto op_side = new OpLoopSide<SideEle>(mField, simple->getDomainFEName(),
1282 SPACE_DIM, Sev::verbose);
1283 CHK_MOAB_THROW(push_domain_ops(op_side),
1284 "push domain ops to side element");
1285 pp_fe->getOpPtrVector().push_back(op_side);
1286 CHK_MOAB_THROW(push_post_proc_ops(pp_fe),
1287 "push post proc ops to skin element");
1288 return pp_fe;
1289 };
1290
1291 return std::make_pair(domain_post_proc(), skin_post_proc());
1292 };
1293
1294 auto monitor_ptr = boost::make_shared<FEMethod>();
1295
1296 auto [domain_post_proc_fe, skin_post_proc_fe] =
1297 create_post_process_elements();
1298
1299 auto set_time_monitor = [&](auto dm, auto solver) {
1301 monitor_ptr->preProcessHook = [&]() {
1303
1304 if (save_every && (monitor_ptr->ts_step % save_every == 0)) {
1305 if (do_output_domain) {
1306 CHKERR DMoFEMLoopFiniteElements(dm, simple->getDomainFEName(),
1307 domain_post_proc_fe,
1308 monitor_ptr->getCacheWeakPtr());
1309 CHKERR domain_post_proc_fe->writeFile(
1310 "out_" + boost::lexical_cast<std::string>(monitor_ptr->ts_step) +
1311 ".h5m");
1312 }
1313 if (do_output_skin) {
1314 CHKERR DMoFEMLoopFiniteElements(dm, simple->getBoundaryFEName(),
1315 skin_post_proc_fe,
1316 monitor_ptr->getCacheWeakPtr());
1317 CHKERR skin_post_proc_fe->writeFile(
1318 "out_skin_" +
1319 boost::lexical_cast<std::string>(monitor_ptr->ts_step) + ".h5m");
1320 }
1321 }
1322
1323 if (doEvalField) {
1324
1325 if constexpr (SPACE_DIM == 3) {
1326 CHKERR mField.getInterface<FieldEvaluatorInterface>()
1327 ->evalFEAtThePoint3D(
1328 fieldEvalCoords.data(), 1e-12, simple->getProblemName(),
1329 simple->getDomainFEName(), fieldEvalData,
1330 mField.get_comm_rank(), mField.get_comm_rank(), nullptr,
1331 MF_EXIST, QUIET);
1332 } else {
1333 CHKERR mField.getInterface<FieldEvaluatorInterface>()
1334 ->evalFEAtThePoint2D(
1335 fieldEvalCoords.data(), 1e-12, simple->getProblemName(),
1336 simple->getDomainFEName(), fieldEvalData,
1337 mField.get_comm_rank(), mField.get_comm_rank(), nullptr,
1338 MF_EXIST, QUIET);
1339 }
1340
1341 if (atom_test) {
1342 auto eval_num_vec =
1343 createVectorMPI(mField.get_comm(), PETSC_DECIDE, 1);
1344 CHKERR VecZeroEntries(eval_num_vec);
1345 if (tempFieldPtr->size()) {
1346 CHKERR VecSetValue(eval_num_vec, 0, 1, ADD_VALUES);
1347 }
1348 CHKERR VecAssemblyBegin(eval_num_vec);
1349 CHKERR VecAssemblyEnd(eval_num_vec);
1350
1351 double eval_num;
1352 CHKERR VecSum(eval_num_vec, &eval_num);
1353 if (!(int)eval_num) {
1354 SETERRQ1(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1355 "atom test %d failed: did not find elements to evaluate "
1356 "the field, check the coordinates",
1357 atom_test);
1358 }
1359 }
1360
1361 if (tempFieldPtr->size()) {
1362 auto t_temp = getFTensor0FromVec(*tempFieldPtr);
1363 MOFEM_LOG("ThermoElasticSync", Sev::inform)
1364 << "Eval point T: " << t_temp;
1365 if (atom_test && fabs(monitor_ptr->ts_t - 10) < 1e-12) {
1366 if (atom_test <= 3 && fabs(t_temp - 554.48) > 1e-2) {
1367 SETERRQ1(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1368 "atom test %d failed: wrong temperature value",
1369 atom_test);
1370 }
1371 if (atom_test == 4 && fabs(t_temp - 250) > 1e-2) {
1372 SETERRQ1(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1373 "atom test %d failed: wrong temperature value",
1374 atom_test);
1375 }
1376 }
1377 }
1378 if (fluxFieldPtr->size1()) {
1380 auto t_flux = getFTensor1FromMat<SPACE_DIM>(*fluxFieldPtr);
1381 auto flux_mag = sqrt(t_flux(i) * t_flux(i));
1382 MOFEM_LOG("ThermoElasticSync", Sev::inform)
1383 << "Eval point FLUX magnitude: " << flux_mag;
1384 if (atom_test && fabs(monitor_ptr->ts_t - 10) < 1e-12) {
1385 if (atom_test <= 3 && fabs(flux_mag - 27008.0) > 2e1) {
1386 SETERRQ1(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1387 "atom test %d failed: wrong flux value", atom_test);
1388 }
1389 if (atom_test == 4 && fabs(flux_mag - 150e3) > 1e-1) {
1390 SETERRQ1(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1391 "atom test %d failed: wrong flux value", atom_test);
1392 }
1393 }
1394 }
1395 if (dispFieldPtr->size1()) {
1397 auto t_disp = getFTensor1FromMat<SPACE_DIM>(*dispFieldPtr);
1398 auto disp_mag = sqrt(t_disp(i) * t_disp(i));
1399 MOFEM_LOG("ThermoElasticSync", Sev::inform)
1400 << "Eval point U magnitude: " << disp_mag;
1401 if (atom_test && fabs(monitor_ptr->ts_t - 10) < 1e-12) {
1402 if (atom_test == 1 && fabs(disp_mag - 0.00345) > 1e-5) {
1403 SETERRQ1(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1404 "atom test %d failed: wrong displacement value",
1405 atom_test);
1406 }
1407 if ((atom_test == 2 || atom_test == 3) &&
1408 fabs(disp_mag - 0.00265) > 1e-5) {
1409 SETERRQ1(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1410 "atom test %d failed: wrong displacement value",
1411 atom_test);
1412 }
1413 }
1414 }
1415 if (strainFieldPtr->size1()) {
1417 auto t_strain =
1419 auto t_strain_trace = t_strain(i, i);
1420 if (atom_test && fabs(monitor_ptr->ts_t - 10) < 1e-12) {
1421 if (atom_test == 1 && fabs(t_strain_trace - 0.00679) > 1e-5) {
1422 SETERRQ1(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1423 "atom test %d failed: wrong strain value", atom_test);
1424 }
1425 if ((atom_test == 2 || atom_test == 3) &&
1426 fabs(t_strain_trace - 0.00522) > 1e-5) {
1427 SETERRQ1(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1428 "atom test %d failed: wrong strain value", atom_test);
1429 }
1430 }
1431 }
1432 if (stressFieldPtr->size1()) {
1433 auto t_stress =
1435 auto von_mises_stress = std::sqrt(
1436 0.5 *
1437 ((t_stress(0, 0) - t_stress(1, 1)) *
1438 (t_stress(0, 0) - t_stress(1, 1)) +
1439 (SPACE_DIM == 3 ? (t_stress(1, 1) - t_stress(2, 2)) *
1440 (t_stress(1, 1) - t_stress(2, 2))
1441 : 0) +
1442 (SPACE_DIM == 3 ? (t_stress(2, 2) - t_stress(0, 0)) *
1443 (t_stress(2, 2) - t_stress(0, 0))
1444 : 0) +
1445 6 * (t_stress(0, 1) * t_stress(0, 1) +
1446 (SPACE_DIM == 3 ? t_stress(1, 2) * t_stress(1, 2) : 0) +
1447 (SPACE_DIM == 3 ? t_stress(2, 0) * t_stress(2, 0) : 0))));
1448 MOFEM_LOG("ThermoElasticSync", Sev::inform)
1449 << "Eval point von Mises Stress: " << von_mises_stress;
1450 if (atom_test && fabs(monitor_ptr->ts_t - 10) < 1e-12) {
1451 if (atom_test == 1 && fabs(von_mises_stress - 523.0) > 5e-1) {
1452 SETERRQ1(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1453 "atom test %d failed: wrong von Mises stress value",
1454 atom_test);
1455 }
1456 if (atom_test == 2 && fabs(von_mises_stress - 16.3) > 5e-2) {
1457 SETERRQ1(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1458 "atom test %d failed: wrong von Mises stress value",
1459 atom_test);
1460 }
1461 if (atom_test == 3 && fabs(von_mises_stress - 14.9) > 5e-2) {
1462 SETERRQ1(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1463 "atom test %d failed: wrong von Mises stress value",
1464 atom_test);
1465 }
1466 }
1467 }
1468
1469 MOFEM_LOG_SYNCHRONISE(mField.get_comm());
1470 }
1471
1473 };
1474 auto null = boost::shared_ptr<FEMethod>();
1475 CHKERR DMMoFEMTSSetMonitor(dm, solver, simple->getDomainFEName(), null,
1476 monitor_ptr, null);
1478 };
1479
1480 auto set_fieldsplit_preconditioner = [&](auto solver) {
1482
1483 SNES snes;
1484 CHKERR TSGetSNES(solver, &snes);
1485 KSP ksp;
1486 CHKERR SNESGetKSP(snes, &ksp);
1487 PC pc;
1488 CHKERR KSPGetPC(ksp, &pc);
1489 PetscBool is_pcfs = PETSC_FALSE;
1490 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
1491
1492 // Setup fieldsplit (block) solver - optional: yes/no
1493 if (is_pcfs == PETSC_TRUE) {
1494 auto bc_mng = mField.getInterface<BcManager>();
1495 auto is_mng = mField.getInterface<ISManager>();
1496 auto name_prb = simple->getProblemName();
1497
1498 SmartPetscObj<IS> is_u;
1499 CHKERR is_mng->isCreateProblemFieldAndRank(name_prb, ROW, "U", 0,
1500 SPACE_DIM, is_u);
1501 SmartPetscObj<IS> is_flux;
1502 CHKERR is_mng->isCreateProblemFieldAndRank(name_prb, ROW, "FLUX", 0, 0,
1503 is_flux);
1504 SmartPetscObj<IS> is_T;
1505 CHKERR is_mng->isCreateProblemFieldAndRank(name_prb, ROW, "T", 0, 0,
1506 is_T);
1507 SmartPetscObj<IS> is_TBC;
1508 CHKERR is_mng->isCreateProblemFieldAndRank(name_prb, ROW, "TBC", 0, 0,
1509 is_TBC);
1510 IS is_tmp, is_tmp2;
1511 CHKERR ISExpand(is_T, is_flux, &is_tmp);
1512 CHKERR ISExpand(is_TBC, is_tmp, &is_tmp2);
1513 CHKERR ISDestroy(&is_tmp);
1514 auto is_TFlux = SmartPetscObj<IS>(is_tmp2);
1515
1516 CHKERR ISSort(is_u);
1517 CHKERR ISSort(is_TFlux);
1518 CHKERR PCFieldSplitSetIS(pc, PETSC_NULL, is_TFlux);
1519 CHKERR PCFieldSplitSetIS(pc, PETSC_NULL, is_u);
1520 }
1521
1523 };
1524
1525 auto D = createDMVector(dm);
1526 CHKERR DMoFEMMeshToLocalVector(dm, D, INSERT_VALUES, SCATTER_FORWARD);
1527 CHKERR TSSetSolution(solver, D);
1528 CHKERR TSSetFromOptions(solver);
1529
1530 CHKERR set_section_monitor(solver);
1531 CHKERR set_fieldsplit_preconditioner(solver);
1532 CHKERR set_time_monitor(dm, solver);
1533
1534 CHKERR TSSetUp(solver);
1535 CHKERR TSSolve(solver, NULL);
1536
1538}
1539//! [Solve]
1540
1541static char help[] = "...\n\n";
1542
1543int main(int argc, char *argv[]) {
1544
1545 // Initialisation of MoFEM/PETSc and MOAB data structures
1546 const char param_file[] = "param_file.petsc";
1547 MoFEM::Core::Initialize(&argc, &argv, param_file, help);
1548
1549 // Add logging channel for example
1550 auto core_log = logging::core::get();
1551 core_log->add_sink(
1553 LogManager::setLog("ThermoElastic");
1554 MOFEM_LOG_TAG("ThermoElastic", "ThermoElastic");
1555
1556 core_log->add_sink(
1557 LogManager::createSink(LogManager::getStrmSync(), "ThermoElasticSync"));
1558 LogManager::setLog("ThermoElasticSync");
1559 MOFEM_LOG_TAG("ThermoElasticSync", "ThermoElasticSync");
1560
1561 try {
1562
1563 //! [Register MoFEM discrete manager in PETSc]
1564 DMType dm_name = "DMMOFEM";
1565 CHKERR DMRegister_MoFEM(dm_name);
1566 //! [Register MoFEM discrete manager in PETSc
1567
1568 //! [Create MoAB]
1569 moab::Core mb_instance; ///< mesh database
1570 moab::Interface &moab = mb_instance; ///< mesh database interface
1571 //! [Create MoAB]
1572
1573 //! [Create MoFEM]
1574 MoFEM::Core core(moab); ///< finite element database
1575 MoFEM::Interface &m_field = core; ///< finite element database interface
1576 //! [Create MoFEM]
1577
1578 //! [Load mesh]
1579 Simple *simple = m_field.getInterface<Simple>();
1580 CHKERR simple->getOptions();
1581 CHKERR simple->loadFile();
1582 //! [Load mesh]
1583
1584 //! [ThermoElasticProblem]
1585 ThermoElasticProblem ex(m_field);
1586 CHKERR ex.runProblem();
1587 //! [ThermoElasticProblem]
1588 }
1590
1592}
static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin)
static auto get_skin(MoFEM::Interface &m_field, Range body_ents)
#define MOFEM_LOG_SEVERITY_SYNC(comm, severity)
Synchronise "SYNC" on curtain severity level.
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
#define MOFEM_TAG_AND_LOG(channel, severity, tag)
Tag and log in channel.
#define FTENSOR_INDEX(DIM, I)
Implementation of thermal convection bc.
Implementation of thermal radiation bc.
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
int main()
DomainEle::UserDataOperator DomainEleOp
Finire element operator type.
constexpr int SPACE_DIM
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
[Define dimension]
Kronecker Delta class symmetric.
@ QUIET
@ ROW
#define CATCH_ERRORS
Catch errors.
@ MF_EXIST
FieldApproximationBase
approximation base
Definition definitions.h:58
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base nme:nme847.
Definition definitions.h:60
@ DEMKOWICZ_JACOBI_BASE
Definition definitions.h:66
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
@ L2
field with C-1 continuity
Definition definitions.h:88
@ H1
continuous field
Definition definitions.h:85
@ NOSPACE
Definition definitions.h:83
@ HCURL
field with continuous tangents
Definition definitions.h:86
@ HDIV
field with continuous normal traction
Definition definitions.h:87
#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 ...
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
@ TEMPERATURESET
@ HEATFLUXSET
@ NODESET
@ SIDESET
@ MOFEM_ATOM_TEST_INVALID
Definition definitions.h:40
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
#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 ...
double bulk_modulus_K
double shear_modulus_G
auto integration_rule
constexpr auto t_kd
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode)
set local (or ghosted) vector values on mesh for partition only
Definition DMMoFEM.cpp:523
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:586
auto createDMVector(DM dm)
Get smart vector from DM.
Definition DMMoFEM.hpp:1099
static LoggerType & setLog(const std::string channel)
Set ans resset chanel logger.
#define MOFEM_LOG(channel, severity)
Log.
SeverityLevel
Severity levels.
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
MoFEMErrorCode getCubitMeshsetPtr(const int ms_id, const CubitBCType cubit_bc_type, const CubitMeshSets **cubit_meshset_ptr) const
get cubit meshset
FTensor::Index< 'i', SPACE_DIM > i
PetscBool doEvalField
const double c
speed of light (cm/ns)
double D
const double n
refractive index of diffusive medium
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
UBlasVector< double > VectorDouble
Definition Types.hpp:68
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
PetscErrorCode DMMoFEMTSSetMonitor(DM dm, TS ts, const std::string fe_name, boost::shared_ptr< MoFEM::FEMethod > method, boost::shared_ptr< MoFEM::BasicMethod > pre_only, boost::shared_ptr< MoFEM::BasicMethod > post_only)
Set Monitor To TS solver.
Definition DMMoFEM.cpp:1056
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
MoFEMErrorCode MoFEMSNESMonitorFields(SNES snes, PetscInt its, PetscReal fgnorm, SnesCtx *snes_ctx)
Sens monitor printing residual field by field.
Definition SnesCtx.cpp:232
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
PetscErrorCode PetscOptionsGetScalar(PetscOptions *, const char pre[], const char name[], PetscScalar *dval, PetscBool *set)
PetscErrorCode PetscOptionsGetRealArray(PetscOptions *, const char pre[], const char name[], PetscReal dval[], PetscInt *nmax, PetscBool *set)
auto createVectorMPI(MPI_Comm comm, PetscInt n, PetscInt N)
Create MPI Vector.
static FTensor::Ddg< FTensor::PackPtr< T *, 1 >, Tensor_Dim01, Tensor_Dim23 > getFTensor4DdgFromMat(ublas::matrix< T, L, A > &data)
Get symmetric tensor rank 4 on first two and last indices from form data matrix.
FTensor::Tensor1< FTensor::PackPtr< T *, S >, Tensor_Dim > getFTensor1FromMat(ublas::matrix< T, L, A > &data)
Get tensor rank 1 (vector) form data matrix.
static auto getFTensor2SymmetricFromMat(ublas::matrix< T, L, A > &data)
Get symmetric tensor rank 2 (matrix) form data matrix.
static auto getFTensor0FromVec(ublas::vector< T, A > &data)
Get tensor rank 0 (scalar) form data vector.
auto get_temp_meshset_ptr(moab::Interface &moab)
Create smart pointer to temporary meshset.
OpCalculateScalarFieldValuesFromPetscVecImpl< PetscData::CTX_SET_X_T > OpCalculateScalarFieldValuesDot
auto getDMSnesCtx(DM dm)
Get SNES context data structure used by DM.
Definition DMMoFEM.hpp:1127
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
double young_modulus
Young modulus.
Definition plastic.cpp:121
double poisson_ratio
Poisson ratio.
Definition plastic.cpp:122
constexpr auto size_symm
Definition plastic.cpp:42
ElementsAndOps< SPACE_DIM >::SideEle SideEle
Definition plastic.cpp:61
constexpr auto field_name
static constexpr int approx_order
OpBaseImpl< PETSC, EdgeEleOp > OpBase
Definition radiation.cpp:29
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, SPACE_DIM > OpMass
[Only used with Hooke equation (linear material model)]
Definition seepage.cpp:56
FTensor::Index< 'm', 3 > m
Add operators pushing bases from local to physical configuration.
Simple interface for fast problem set-up.
Definition BcManager.hpp:25
Managing BitRefLevels.
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:82
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
Definition Core.cpp:72
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Definition Core.cpp:112
Deprecated interface functions.
Definition of the displacement bc data structure.
Definition BCData.hpp:76
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.
FTensor::Tensor1< FTensor::PackPtr< double *, Tensor_Dim >, Tensor_Dim > getFTensor1N(FieldApproximationBase base)
Get base functions for Hdiv/Hcurl spaces.
Class (Function) to enforce essential constrains.
Definition Essential.hpp:25
structure for User Loop Methods on finite elements
Basic algebra on fields.
Definition FieldBlas.hpp:21
Field evaluator interface.
Definition of the heat flux bc data structure.
Definition BCData.hpp:427
Section manager is used to create indexes and sections.
Definition ISManager.hpp:23
static boost::shared_ptr< SinkType > createSink(boost::shared_ptr< std::ostream > stream_ptr, std::string comm_filter)
Create a sink object.
static boost::shared_ptr< std::ostream > getStrmWorld()
Get the strm world object.
static boost::shared_ptr< std::ostream > getStrmSync()
Get the strm sync object.
Interface for managing meshsets containing materials and boundary conditions.
Assembly methods.
Definition Natural.hpp:65
Natural boundary conditions.
Definition Natural.hpp:57
Get vector field for H-div approximation.
Calculate divergence of vector field.
Get value at integration points for scalar field.
Get field gradients at integration pts for scalar filed rank 0, i.e. vector field.
Get values at integration pts for tensor filed rank 1, i.e. vector field.
Enforce essential constrains on lhs.
Definition Essential.hpp:81
Enforce essential constrains on rhs.
Definition Essential.hpp:65
Element used to execute operators on side of the element.
Post post-proc data at points from hash maps.
PipelineManager interface.
Problem manager is used to build and partition problems.
Simple interface for fast problem set-up.
Definition Simple.hpp:27
intrusive_ptr for managing petsc objects
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
boost::shared_ptr< FieldEvaluatorInterface::SetPtsData > fieldEvalData
MoFEMErrorCode getCommandLineParameters()
[Run problem]
MoFEMErrorCode runProblem()
[Run problem]
boost::shared_ptr< MatrixDouble > fluxFieldPtr
boost::shared_ptr< VectorDouble > tempFieldPtr
std::array< double, SPACE_DIM > fieldEvalCoords
boost::shared_ptr< MatrixDouble > stressFieldPtr
MoFEM::Interface & mField
ThermoElasticProblem(MoFEM::Interface &m_field)
MoFEMErrorCode addMatBlockOps(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, std::string block_elastic_name, std::string block_thermal_name, boost::shared_ptr< BlockedParameters > blockedParamsPtr, Sev sev)
boost::shared_ptr< MatrixDouble > dispGradPtr
MoFEMErrorCode setupProblem()
add fields
boost::shared_ptr< MatrixDouble > dispFieldPtr
MoFEMErrorCode bC()
[Set up problem]
MoFEMErrorCode OPs()
[Boundary condition]
boost::shared_ptr< MatrixDouble > strainFieldPtr
MoFEMErrorCode tsSolve()
[Push operators to pipeline]
FormsIntegrators< DomainEleOp >::Assembly< A >::OpBase AssemblyDomainEleOp
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMixDivTimesScalar< SPACE_DIM > OpHdivT
Integrate Lhs div of base of flux time base of temperature (FLUX x T) and transpose of it,...
auto save_range
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpBaseTimesScalar< 1 > OpBaseDotT
Integrate Rhs base of temperature time heat capacity times heat rate (T)
static char help[]
[Solve]
PetscBool is_plane_strain
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpMixDivTimesU< 3, 1, SPACE_DIM > OpHDivTemp
Integrate Rhs div flux base times temperature (T)
int save_every
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpGradSymTensorGrad< 1, SPACE_DIM, SPACE_DIM, 0 > OpKCauchy
[Linear elastic problem]
int order_flux
int atom_test
#define EXECUTABLE_DIMENSION
constexpr int SPACE_DIM
double default_heat_capacity
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, 1 > OpCapacity
Integrate Lhs base of temperature times (heat capacity) times base of temperature (T x T)
int order_disp
double init_temp
double default_young_modulus
[Essential boundary conditions (Least square approach)]
PetscBool do_output_skin
double default_coeff_expansion
int order_temp
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpBaseTimesVector< 3, SPACE_DIM, 1 > OpHdivFlux
Integrating Rhs flux base (1/k) flux (FLUX)
PetscBool do_output_domain
double ref_temp
double default_heat_conductivity
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 3, SPACE_DIM > OpHdivHdiv
[Linear elastic problem]
OpBaseDotT OpBaseDivFlux
Integrate Rhs base of temperature times divergence of flux (T)
double default_poisson_ratio
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpGradTimesSymTensor< 1, SPACE_DIM, SPACE_DIM > OpInternalForceCauchy