v0.15.4
Loading...
Searching...
No Matches
thermo_elastic.cpp
Go to the documentation of this file.
1/**
2 * \file thermo_elastic.cpp
3 * \example mofem/tutorials/adv-2/thermo_elastic.cpp
4 *
5 * Thermo plasticity
6 *
7 */
8
9#ifndef EXECUTABLE_DIMENSION
10 #define EXECUTABLE_DIMENSION 3
11#endif
12
13#ifndef FINITE_DEFORMATION_FLAG
14 #define FINITE_DEFORMATION_FLAG true
15#endif
16
17#include <MoFEM.hpp>
18#include <MatrixFunction.hpp>
19
20using namespace MoFEM;
21
22#include <ThermalConvection.hpp>
23#include <ThermalRadiation.hpp>
24
25constexpr int SPACE_DIM =
26 EXECUTABLE_DIMENSION; //< Space dimension of problem, mesh
27
28constexpr bool IS_LARGE_STRAINS =
29 FINITE_DEFORMATION_FLAG; //< Flag to turn off/on geometric nonlinearities
30
33using DomainEleOp = DomainEle::UserDataOperator;
36using BoundaryEleOp = BoundaryEle::UserDataOperator;
40
43
44constexpr AssemblyType AT = AssemblyType::PETSC; //< selected assembly type
46 IntegrationType::GAUSS; //< selected integration type
47
48//! [Linear elastic problem]
49#include <HenckyOps.hpp> // Include Hencky operators
50using namespace HenckyOps;
51//! [Linear elastic problem]
52
53// Include finite deformation operators
54#include <FiniteThermalOps.hpp> // Include operators for finite strain diffusion problem
55using namespace FiniteThermalOps;
56
57//! [Thermal problem]
58#include <ThermalOps.hpp> // Include operators for thermal problem which are agnostic to small/large strains
59using namespace ThermalOps;
60//! [Thermal problem]
61
62//! [Body and heat source]
71//! [Body and heat source]
72
73//! [Natural boundary conditions]
77
78//! [Natural boundary conditions]
79
80//! [Essential boundary conditions (Least square approach)]
83 GAUSS>::OpEssentialRhs<HeatFluxCubitBcData, 3, SPACE_DIM>;
86 GAUSS>::OpEssentialLhs<HeatFluxCubitBcData, 3, SPACE_DIM>;
87//! [Essential boundary conditions (Least square approach)]
88
89//! [Default input parameters]
92double default_ref_temp = 0.0;
93double default_init_temp = 0.0;
94
97 1; // Force / (time temperature ) or Power /
98 // (length temperature) // Time unit is hour. force unit kN
99double default_heat_capacity = 1; // length^2/(time^2 temperature) // length is
100 // millimeter time is hour
101
102int order_temp = 2; //< default approximation order for the temperature field
103int order_flux = 3; //< default approximation order for heat flux field
104int order_disp = 3; //< default approximation order for the displacement field
105
106int atom_test = 0;
107
108int save_every = 1; //< Save every n-th step
111//! [Default input parameters]
112
113#include <ThermoElasticOps.hpp> //< additional coupling operators
114using namespace ThermoElasticOps; //< name space of coupling operators
115
120
121auto save_range = [](moab::Interface &moab, const std::string name,
122 const Range r) {
124 auto out_meshset = get_temp_meshset_ptr(moab);
125 CHKERR moab.add_entities(*out_meshset, r);
126 CHKERR moab.write_file(name.c_str(), "VTK", "", out_meshset->get_ptr(), 1);
128};
129
131
133
135
136private:
138
139 PetscBool doEvalField;
140 std::array<double, 3> fieldEvalCoords = {0.0, 0.0, 0.0};
141 boost::shared_ptr<FieldEvaluatorInterface::SetPtsData> fieldEvalData;
142
143 boost::shared_ptr<VectorDouble> tempFieldPtr;
144 boost::shared_ptr<MatrixDouble> fluxFieldPtr;
145 boost::shared_ptr<MatrixDouble> dispFieldPtr;
146 boost::shared_ptr<MatrixDouble> dispGradPtr;
147 boost::shared_ptr<MatrixDouble> strainFieldPtr;
148 boost::shared_ptr<MatrixDouble> stressFieldPtr;
149
150 MoFEMErrorCode setupProblem(); ///< add fields
152 getCommandLineParameters(); //< read parameters from command line
153 MoFEMErrorCode bC(); //< read boundary conditions
154 MoFEMErrorCode OPs(); //< add operators to pipeline
155 MoFEMErrorCode tsSolve(); //< time solver
156
158 : public boost::enable_shared_from_this<BlockedThermalParameters> {
161
163 return boost::shared_ptr<double>(shared_from_this(), &heatConductivity);
164 }
165
166 inline auto getHeatCapacityPtr() {
167 return boost::shared_ptr<double>(shared_from_this(), &heatCapacity);
168 }
169 };
170
172 : public boost::enable_shared_from_this<BlockedThermoElasticParameters> {
174 double refTemp;
175
176 inline auto getCoeffExpansionPtr() {
177 return boost::shared_ptr<VectorDouble>(shared_from_this(),
179 }
180
181 inline auto getRefTempPtr() {
182 return boost::shared_ptr<double>(shared_from_this(), &refTemp);
183 }
184 };
185
187 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
188 std::string block_name,
189 boost::shared_ptr<BlockedThermalParameters> blockedParamsPtr, Sev sev);
190
192 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
193 std::string block_name,
194 boost::shared_ptr<BlockedThermoElasticParameters> blockedParamsPtr,
195 Sev sev);
196
197 template <int DIM, AssemblyType A, IntegrationType I, typename DomainEleOp>
199 MoFEM::Interface &m_field,
200 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
201 std::string field_name,
202 boost::shared_ptr<HenckyOps::CommonData> elastic_common_ptr,
203 boost::shared_ptr<ThermoElasticProblem::BlockedThermalParameters>
204 thermal_common_ptr,
205 boost::shared_ptr<ThermoElasticProblem::BlockedThermoElasticParameters>
206 thermoelastic_common_ptr,
207 Sev sev) {
209
210 using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
211 A>::template LinearForm<I>;
213 auto vec_temp_ptr = boost::make_shared<VectorDouble>();
214 pip.push_back(new OpCalculateScalarFieldValues("T", vec_temp_ptr));
215 auto coeff_expansion_ptr = thermoelastic_common_ptr->getCoeffExpansionPtr();
216 auto ref_temp_ptr = thermoelastic_common_ptr->getRefTempPtr();
217 pip.push_back(
218 new typename H::template OpCalculateHenckyThermalStress<DIM, I, 0>(
219 "U", vec_temp_ptr, elastic_common_ptr, coeff_expansion_ptr,
220 ref_temp_ptr));
222 typename B::template OpGradTimesTensor<1, DIM, DIM>;
223 pip.push_back(new OpInternalForcePiola(
224 "U", elastic_common_ptr->getMatFirstPiolaStress()));
225
227 }
228
229 template <int DIM, AssemblyType A, IntegrationType I, typename DomainEleOp>
231 MoFEM::Interface &m_field,
232 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
233 std::string field_name, std::string elastic_block_name,
234 std::string thermal_block_name, std::string thermoelastic_block_name,
235 Sev sev, double scale = 1) {
237
238 auto elastic_common_ptr = commonDataFactory<DIM, I, DomainEleOp>(
239 m_field, pip, field_name, elastic_block_name, sev, scale);
240 auto thermal_common_ptr = boost::make_shared<BlockedThermalParameters>();
241 CHKERR addMatThermalBlockOps(pip, thermal_block_name, thermal_common_ptr,
242 Sev::inform);
243 auto thermoelastic_common_ptr =
244 boost::make_shared<BlockedThermoElasticParameters>();
245 CHKERR addMatThermoElasticBlockOps(pip, thermoelastic_block_name,
246 thermoelastic_common_ptr, Sev::inform);
247 CHKERR opThermoElasticFactoryDomainRhs<DIM, A, I, DomainEleOp>(
248 m_field, pip, field_name, elastic_common_ptr, thermal_common_ptr,
249 thermoelastic_common_ptr, sev);
250
252 }
253
254 template <int DIM, AssemblyType A, IntegrationType I, typename DomainEleOp>
256 MoFEM::Interface &m_field,
257 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
258 std::string field_name, std::string coupled_field_name,
259 boost::shared_ptr<HenckyOps::CommonData> elastic_common_ptr,
260 boost::shared_ptr<ThermoElasticProblem::BlockedThermalParameters>
261 thermal_common_ptr,
262 boost::shared_ptr<ThermoElasticProblem::BlockedThermoElasticParameters>
263 thermoelastic_common_ptr,
264 Sev sev) {
266
267 using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
268 A>::template BiLinearForm<I>;
269 using OpKPiola = typename B::template OpGradTensorGrad<1, DIM, DIM, 1>;
270
272 auto vec_temp_ptr = boost::make_shared<VectorDouble>();
273 pip.push_back(new OpCalculateScalarFieldValues("T", vec_temp_ptr));
274 auto coeff_expansion_ptr = thermoelastic_common_ptr->getCoeffExpansionPtr();
275 auto ref_temp_ptr = thermoelastic_common_ptr->getRefTempPtr();
276 pip.push_back(
277 new typename H::template OpCalculateHenckyThermalStress<DIM, I, 0>(
278 "U", vec_temp_ptr, elastic_common_ptr, coeff_expansion_ptr,
279 ref_temp_ptr));
280 pip.push_back(new typename H::template OpHenckyTangent<DIM, I, 0>(
281 field_name, elastic_common_ptr));
282 pip.push_back(new OpKPiola(field_name, field_name,
283 elastic_common_ptr->getMatTangent()));
284 pip.push_back(new typename H::template OpCalculateHenckyThermalStressdT<
285 DIM, I, AssemblyDomainEleOp, 0>(
286 field_name, coupled_field_name, elastic_common_ptr,
287 coeff_expansion_ptr));
288
290 }
291
292 template <int DIM, AssemblyType A, IntegrationType I, typename DomainEleOp>
294 MoFEM::Interface &m_field,
295 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
296 std::string field_name, std::string coupled_field_name,
297 std::string elastic_block_name, std::string thermal_block_name,
298 std::string thermoelastic_block_name, Sev sev, double scale = 1) {
300
301 auto elastic_common_ptr = commonDataFactory<DIM, I, DomainEleOp>(
302 m_field, pip, field_name, elastic_block_name, sev, scale);
303 auto thermal_common_ptr = boost::make_shared<BlockedThermalParameters>();
304 CHKERR addMatThermalBlockOps(pip, thermal_block_name, thermal_common_ptr,
305 Sev::inform);
306 auto thermoelastic_common_ptr =
307 boost::make_shared<BlockedThermoElasticParameters>();
308 CHKERR addMatThermoElasticBlockOps(pip, thermoelastic_block_name,
309 thermoelastic_common_ptr, Sev::inform);
310 CHKERR opThermoElasticFactoryDomainLhs<DIM, A, I, DomainEleOp>(
311 m_field, pip, field_name, coupled_field_name, elastic_common_ptr,
312 thermal_common_ptr, thermoelastic_common_ptr, sev);
313
315 }
316};
317
319 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
320 std::string block_name,
321 boost::shared_ptr<BlockedThermalParameters> blockedParamsPtr, Sev sev) {
323
324 struct OpMatThermalBlocks : public DomainEleOp {
325 OpMatThermalBlocks(boost::shared_ptr<double> conductivity_ptr,
326 boost::shared_ptr<double> capacity_ptr,
327 MoFEM::Interface &m_field, Sev sev,
328 std::vector<const CubitMeshSets *> meshset_vec_ptr)
329 : DomainEleOp(NOSPACE, DomainEleOp::OPSPACE),
330 conductivityPtr(conductivity_ptr), capacityPtr(capacity_ptr) {
331 CHK_THROW_MESSAGE(extractThermalBlockData(m_field, meshset_vec_ptr, sev),
332 "Cannot get data from thermal block");
333 }
334
335 MoFEMErrorCode doWork(int side, EntityType type,
338
339 for (auto &b : blockData) {
340
341 if (b.blockEnts.find(getFEEntityHandle()) != b.blockEnts.end()) {
342 *conductivityPtr = b.conductivity;
343 *capacityPtr = b.capacity;
345 }
346 }
347
348 *conductivityPtr = default_heat_conductivity;
349 *capacityPtr = default_heat_capacity;
350
352 }
353
354 private:
355 struct BlockData {
356 double conductivity;
357 double capacity;
358 Range blockEnts;
359 };
360
361 std::vector<BlockData> blockData;
362
364 extractThermalBlockData(MoFEM::Interface &m_field,
365 std::vector<const CubitMeshSets *> meshset_vec_ptr,
366 Sev sev) {
368
369 for (auto m : meshset_vec_ptr) {
370 MOFEM_TAG_AND_LOG("WORLD", sev, "Mat Thermal Block") << *m;
371 std::vector<double> block_data;
372 CHKERR m->getAttributes(block_data);
373 if (block_data.size() < 2) {
374 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
375 "Expected that block has at least two attributes");
376 }
377 auto get_block_ents = [&]() {
378 Range ents;
379 CHKERR
380 m_field.get_moab().get_entities_by_handle(m->meshset, ents, true);
381 return ents;
382 };
383
384 MOFEM_TAG_AND_LOG("WORLD", sev, "Mat Thermal Block")
385 << m->getName() << ": conductivity = " << block_data[0]
386 << " capacity = " << block_data[1];
387
388 blockData.push_back({block_data[0], block_data[1], get_block_ents()});
389 }
390 MOFEM_LOG_CHANNEL("WORLD");
392 }
393
394 boost::shared_ptr<double> conductivityPtr;
395 boost::shared_ptr<double> capacityPtr;
396 };
397
398 pipeline.push_back(new OpMatThermalBlocks(
399 blockedParamsPtr->getHeatConductivityPtr(),
400 blockedParamsPtr->getHeatCapacityPtr(), mField, sev,
401
402 // Get blockset using regular expression
404
405 (boost::format("%s(.*)") % block_name).str()
406
407 ))
408
409 ));
410
412}
413
415 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
416 std::string block_name,
417 boost::shared_ptr<BlockedThermoElasticParameters> blockedParamsPtr,
418 Sev sev) {
420
421 struct OpMatThermoElasticBlocks : public DomainEleOp {
422 OpMatThermoElasticBlocks(boost::shared_ptr<VectorDouble> expansion_ptr,
423 boost::shared_ptr<double> ref_temp_ptr,
424 MoFEM::Interface &m_field, Sev sev,
425 std::vector<const CubitMeshSets *> meshset_vec_ptr)
426 : DomainEleOp(NOSPACE, DomainEleOp::OPSPACE),
427 expansionPtr(expansion_ptr), refTempPtr(ref_temp_ptr) {
429 extractThermoElasticBlockData(m_field, meshset_vec_ptr, sev),
430 "Cannot get data from thermoelastic block");
431 }
432
433 MoFEMErrorCode doWork(int side, EntityType type,
436
437 for (auto &b : blockData) {
438
439 if (b.blockEnts.find(getFEEntityHandle()) != b.blockEnts.end()) {
440 *expansionPtr = b.expansion;
441 *refTempPtr = b.ref_temp;
443 }
444 }
445
447 *refTempPtr = default_ref_temp;
448
450 }
451
452 private:
453 struct BlockData {
454 double ref_temp;
455 VectorDouble expansion;
456 Range blockEnts;
457 };
458
459 std::vector<BlockData> blockData;
460
461 MoFEMErrorCode extractThermoElasticBlockData(
462 MoFEM::Interface &m_field,
463 std::vector<const CubitMeshSets *> meshset_vec_ptr, Sev sev) {
465
466 for (auto m : meshset_vec_ptr) {
467 MOFEM_TAG_AND_LOG("WORLD", sev, "Mat Thermoelastic Block") << *m;
468 std::vector<double> block_data;
469 CHKERR m->getAttributes(block_data);
470 if (block_data.size() < 2) {
471 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
472 "Expected that block has at least two attributes");
473 }
474 auto get_block_ents = [&]() {
475 Range ents;
476 CHKERR
477 m_field.get_moab().get_entities_by_handle(m->meshset, ents, true);
478 return ents;
479 };
480
481 auto get_expansion = [&]() {
482 VectorDouble expansion(SPACE_DIM, block_data[1]);
483 if (block_data.size() > 2) {
484 expansion[1] = block_data[2];
485 }
486 if (SPACE_DIM == 3 && block_data.size() > 3) {
487 expansion[2] = block_data[3];
488 }
489 return expansion;
490 };
491
492 auto coeff_exp_vec = get_expansion();
493
494 MOFEM_TAG_AND_LOG("WORLD", sev, "Mat Thermoelastic Block")
495 << " ref_temp = " << block_data[0]
496 << " expansion = " << coeff_exp_vec;
497
498 blockData.push_back({block_data[0], coeff_exp_vec, get_block_ents()});
499 }
500 MOFEM_LOG_CHANNEL("WORLD");
502 }
503
504 boost::shared_ptr<VectorDouble> expansionPtr;
505 boost::shared_ptr<double> refTempPtr;
506 };
507
508 pipeline.push_back(new OpMatThermoElasticBlocks(
509 blockedParamsPtr->getCoeffExpansionPtr(),
510 blockedParamsPtr->getRefTempPtr(), mField, sev,
511
512 // Get blockset using regular expression
514
515 (boost::format("%s(.*)") % block_name).str()
516
517 ))
518
519 ));
520
522}
523
524//! [Run problem]
534//! [Run problem]
535
536//! [Get command line parameters]
539
540 auto get_command_line_parameters = [&]() {
542
543 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order", &order_temp,
544 PETSC_NULLPTR);
545 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order_temp", &order_temp,
546 PETSC_NULLPTR);
548 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order_flux", &order_flux,
549 PETSC_NULLPTR);
551 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order_disp", &order_disp,
552 PETSC_NULLPTR);
553 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-atom_test", &atom_test,
554 PETSC_NULLPTR);
555 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-save_every", &save_every,
556 PETSC_NULLPTR);
557
558 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-young_modulus",
559 &default_young_modulus, PETSC_NULLPTR);
560 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-poisson_ratio",
561 &default_poisson_ratio, PETSC_NULLPTR);
562 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-coeff_expansion",
563 &default_coeff_expansion, PETSC_NULLPTR);
564 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-ref_temp", &default_ref_temp,
565 PETSC_NULLPTR);
566 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-init_temp",
567 &default_init_temp, PETSC_NULLPTR);
568
569 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-capacity",
570 &default_heat_capacity, PETSC_NULLPTR);
571 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-conductivity",
572 &default_heat_conductivity, PETSC_NULLPTR);
573
574 if constexpr (SPACE_DIM == 2) {
575 do_output_domain = PETSC_TRUE;
576 do_output_skin = PETSC_FALSE;
577 } else {
578 do_output_domain = PETSC_FALSE;
579 do_output_skin = PETSC_TRUE;
580 }
581
582 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-output_domain",
583 &do_output_domain, PETSC_NULLPTR);
584 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-output_skin", &do_output_skin,
585 PETSC_NULLPTR);
586
587 MOFEM_LOG("ThermoElastic", Sev::inform)
588 << "Young's modulus " << default_young_modulus;
589 MOFEM_LOG("ThermoElastic", Sev::inform)
590 << "Poisson's ratio " << default_poisson_ratio;
591 MOFEM_LOG("ThermoElastic", Sev::inform)
592 << "Coeff of expansion " << default_coeff_expansion;
593 MOFEM_LOG("ThermoElastic", Sev::inform)
594 << "Default heat capacity " << default_heat_capacity;
595 MOFEM_LOG("ThermoElastic", Sev::inform)
596 << "Heat conductivity " << default_heat_conductivity;
597
598 MOFEM_LOG("ThermoElastic", Sev::inform)
599 << "Reference temperature " << default_ref_temp;
600 MOFEM_LOG("ThermoElastic", Sev::inform)
601 << "Initial temperature " << default_init_temp;
602
604 };
605
606 CHKERR get_command_line_parameters();
607
609}
610//! [Get command line parameters]
611
612//! [Set up problem]
616 // Add field
618 // Mechanical fields
620 CHKERR simple->addBoundaryField("U", H1, AINSWORTH_LEGENDRE_BASE, SPACE_DIM);
621 // Temperature
622 constexpr auto flux_space = (SPACE_DIM == 2) ? HCURL : HDIV;
623 CHKERR simple->addDomainField("T", L2, base, 1);
624 CHKERR simple->addDomainField("FLUX", flux_space, base, 1);
625 CHKERR simple->addBoundaryField("FLUX", flux_space, base, 1);
626 CHKERR simple->addBoundaryField("TBC", L2, base, 1);
627
628 CHKERR simple->setFieldOrder("U", order_disp);
629 CHKERR simple->setFieldOrder("FLUX", order_flux);
630 CHKERR simple->setFieldOrder("T", order_temp);
631 CHKERR simple->setFieldOrder("TBC", order_temp);
632
633 CHKERR simple->setUp();
634
635 int coords_dim = 3;
636 CHKERR PetscOptionsGetRealArray(NULL, NULL, "-field_eval_coords",
637 fieldEvalCoords.data(), &coords_dim,
638 &doEvalField);
639
640 tempFieldPtr = boost::make_shared<VectorDouble>();
641 fluxFieldPtr = boost::make_shared<MatrixDouble>();
642 dispFieldPtr = boost::make_shared<MatrixDouble>();
643 dispGradPtr = boost::make_shared<MatrixDouble>();
644 strainFieldPtr = boost::make_shared<MatrixDouble>();
645 stressFieldPtr = boost::make_shared<MatrixDouble>();
646
647 if (doEvalField) {
649 mField.getInterface<FieldEvaluatorInterface>()->getData<DomainEle>();
650
651 CHKERR mField.getInterface<FieldEvaluatorInterface>()->buildTree<SPACE_DIM>(
652 fieldEvalData, simple->getDomainFEName());
653
654 fieldEvalData->setEvalPoints(fieldEvalCoords.data(), 1);
655 auto no_rule = [](int, int, int) { return -1; };
656
657 auto field_eval_fe_ptr = fieldEvalData->feMethodPtr.lock();
658 field_eval_fe_ptr->getRuleHook = no_rule;
659
660 auto block_thermal_params = boost::make_shared<BlockedThermalParameters>();
661 auto block_thermoelastic_params =
662 boost::make_shared<BlockedThermoElasticParameters>();
663 auto coeff_expansion_ptr =
664 block_thermoelastic_params->getCoeffExpansionPtr();
665 auto ref_temp_ptr = block_thermoelastic_params->getRefTempPtr();
666
667 CHKERR addMatThermalBlockOps(field_eval_fe_ptr->getOpPtrVector(),
668 "MAT_THERMAL", block_thermal_params,
669 Sev::verbose);
671 field_eval_fe_ptr->getOpPtrVector(), "MAT_THERMOELASTIC",
672 block_thermoelastic_params, Sev::verbose);
673
675 field_eval_fe_ptr->getOpPtrVector(), {H1, HDIV});
676
677 auto hencky_common_data_ptr =
678 HenckyOps::commonDataFactory<SPACE_DIM, IT, DomainEleOp>(
679 mField, field_eval_fe_ptr->getOpPtrVector(), "U", "MAT_ELASTIC",
680 Sev::inform);
681 auto mat_D_ptr = hencky_common_data_ptr->matDPtr;
682 auto dispGradPtr = hencky_common_data_ptr->matGradPtr;
683 auto mat_stress_ptr = boost::make_shared<MatrixDouble>();
684
685 field_eval_fe_ptr->getOpPtrVector().push_back(
687 field_eval_fe_ptr->getOpPtrVector().push_back(
689 field_eval_fe_ptr->getOpPtrVector().push_back(
691 field_eval_fe_ptr->getOpPtrVector().push_back(
693 dispGradPtr));
694
696
697 field_eval_fe_ptr->getOpPtrVector().push_back(
698 new
699 typename H::template OpCalculateHenckyThermalStress<SPACE_DIM, IT, 0>(
700 "U", tempFieldPtr, hencky_common_data_ptr, coeff_expansion_ptr,
701 ref_temp_ptr));
702 if (!IS_LARGE_STRAINS) {
703 field_eval_fe_ptr->getOpPtrVector().push_back(
705 hencky_common_data_ptr->getMatFirstPiolaStress(),
707 field_eval_fe_ptr->getOpPtrVector().push_back(
709 } else {
710 field_eval_fe_ptr->getOpPtrVector().push_back(
711 new typename H::template OpCalculateLogC<SPACE_DIM, IT>(
712 "U", hencky_common_data_ptr));
713 stressFieldPtr = hencky_common_data_ptr->getMatFirstPiolaStress();
714 strainFieldPtr = hencky_common_data_ptr->getMatLogC();
715 };
716 }
717
719}
720//! [Set up problem]
721
722//! [Boundary condition]
725
726 MOFEM_LOG("SYNC", Sev::noisy) << "bC";
728
730 auto bc_mng = mField.getInterface<BcManager>();
731
732 auto get_skin = [&]() {
733 Range body_ents;
734 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, body_ents);
735 Skinner skin(&mField.get_moab());
736 Range skin_ents;
737 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
738 return skin_ents;
739 };
740
741 auto filter_flux_blocks = [&](auto skin, bool temp_bc = false) {
742 auto remove_cubit_blocks = [&](auto c) {
744 for (auto m :
745
746 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(c)
747
748 ) {
749 Range ents;
750 CHKERR mField.get_moab().get_entities_by_dimension(
751 m->getMeshset(), SPACE_DIM - 1, ents, true);
752 skin = subtract(skin, ents);
753 }
755 };
756
757 auto remove_named_blocks = [&](auto n) {
759 for (auto m : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
760 std::regex(
761
762 (boost::format("%s(.*)") % n).str()
763
764 ))
765
766 ) {
767 Range ents;
768 CHKERR mField.get_moab().get_entities_by_dimension(
769 m->getMeshset(), SPACE_DIM - 1, ents, true);
770 skin = subtract(skin, ents);
771 }
773 };
774 if (!temp_bc) {
775 CHK_THROW_MESSAGE(remove_cubit_blocks(NODESET | TEMPERATURESET),
776 "remove_cubit_blocks");
777 CHK_THROW_MESSAGE(remove_named_blocks("TEMPERATURE"),
778 "remove_named_blocks");
779 }
780 CHK_THROW_MESSAGE(remove_cubit_blocks(SIDESET | HEATFLUXSET),
781 "remove_cubit_blocks");
782 CHK_THROW_MESSAGE(remove_named_blocks("HEATFLUX"), "remove_named_blocks");
783 CHK_THROW_MESSAGE(remove_named_blocks("CONVECTION"), "remove_named_blocks");
784 CHK_THROW_MESSAGE(remove_named_blocks("RADIATION"), "remove_named_blocks");
785 return skin;
786 };
787
788 auto filter_true_skin = [&](auto skin) {
789 Range boundary_ents;
790 ParallelComm *pcomm =
791 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
792 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
793 PSTATUS_NOT, -1, &boundary_ents);
794 return boundary_ents;
795 };
796
797 auto remove_flux_ents = filter_true_skin(filter_flux_blocks(get_skin()));
798 auto remove_temp_bc_ents =
799 filter_true_skin(filter_flux_blocks(get_skin(), true));
800
801 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
802 remove_flux_ents);
803 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
804 remove_temp_bc_ents);
805
806 MOFEM_LOG("SYNC", Sev::noisy) << remove_flux_ents << endl;
808
809 MOFEM_LOG("SYNC", Sev::noisy) << remove_temp_bc_ents << endl;
811
812#ifndef NDEBUG
813
816 (boost::format("flux_remove_%d.vtk") % mField.get_comm_rank()).str(),
817 remove_flux_ents);
818
821 (boost::format("temp_bc_remove_%d.vtk") % mField.get_comm_rank()).str(),
822 remove_temp_bc_ents);
823
824#endif
825
826 CHKERR mField.getInterface<ProblemsManager>()->removeDofsOnEntities(
827 simple->getProblemName(), "FLUX", remove_flux_ents);
828 CHKERR mField.getInterface<ProblemsManager>()->removeDofsOnEntities(
829 simple->getProblemName(), "TBC", remove_temp_bc_ents);
830
831 auto set_init_temp = [](boost::shared_ptr<FieldEntity> field_entity_ptr) {
832 field_entity_ptr->getEntFieldData()[0] = default_init_temp;
833 return 0;
834 };
835 CHKERR mField.getInterface<FieldBlas>()->fieldLambdaOnEntities(set_init_temp,
836 "T");
837
838 CHKERR bc_mng->removeBlockDOFsOnEntities<DisplacementCubitBcData>(
839 simple->getProblemName(), "U");
840 CHKERR bc_mng->pushMarkDOFsOnEntities<HeatFluxCubitBcData>(
841 simple->getProblemName(), "FLUX", false);
842
844}
845//! [Boundary condition]
846
847//! [Push operators to pipeline]
850
851 MOFEM_LOG("SYNC", Sev::noisy) << "OPs";
853
854 auto pipeline_mng = mField.getInterface<PipelineManager>();
855 auto bc_mng = mField.getInterface<BcManager>();
856
857 auto boundary_marker =
858 bc_mng->getMergedBlocksMarker(vector<string>{"HEATFLUX"});
859
860 auto integration_rule = [](int, int, int approx_order) {
861 return 2 * approx_order;
862 };
864 CHKERR pipeline_mng->setDomainLhsIntegrationRule(integration_rule);
865 CHKERR pipeline_mng->setBoundaryRhsIntegrationRule(integration_rule);
866 CHKERR pipeline_mng->setBoundaryLhsIntegrationRule(integration_rule);
867
868 auto block_thermal_params = boost::make_shared<BlockedThermalParameters>();
869 auto heat_conductivity_ptr = block_thermal_params->getHeatConductivityPtr();
870 auto heat_capacity_ptr = block_thermal_params->getHeatCapacityPtr();
871
872 auto block_thermoelastic_params =
873 boost::make_shared<BlockedThermoElasticParameters>();
874 auto coeff_expansion_ptr = block_thermoelastic_params->getCoeffExpansionPtr();
875 auto ref_temp_ptr = block_thermoelastic_params->getRefTempPtr();
876
877 // Default time scaling of BCs and sources, from command line arguments
878 auto time_scale =
879 boost::make_shared<TimeScale>("", false, [](const double) { return 1; });
880 auto def_time_scale = [time_scale](const double time) {
881 return (!time_scale->argFileScale) ? time : 1;
882 };
883 auto def_file_name = [time_scale](const std::string &&name) {
884 return (!time_scale->argFileScale) ? name : "";
885 };
886
887 // Files which define scaling for separate variables, if provided
888 auto time_bodyforce_scaling = boost::make_shared<TimeScale>(
889 def_file_name("bodyforce_scale.txt"), false, def_time_scale);
890 auto time_heatsource_scaling = boost::make_shared<TimeScale>(
891 def_file_name("heatsource_scale.txt"), false, def_time_scale);
892 auto time_temperature_scaling = boost::make_shared<TimeScale>(
893 def_file_name("temperature_bc_scale.txt"), false, def_time_scale);
894 auto time_displacement_scaling = boost::make_shared<TimeScale>(
895 def_file_name("displacement_bc_scale.txt"), false, def_time_scale);
896 auto time_flux_scaling = boost::make_shared<TimeScale>(
897 def_file_name("flux_bc_scale.txt"), false, def_time_scale);
898 auto time_force_scaling = boost::make_shared<TimeScale>(
899 def_file_name("force_bc_scale.txt"), false, def_time_scale);
900 auto time_convection_temp_scaling = boost::make_shared<TimeScale>(
901 def_file_name("convection_temp_scale.txt"), false, def_time_scale);
902 auto time_radiation_temp_scaling = boost::make_shared<TimeScale>(
903 def_file_name("radiation_temp_scale.txt"), false, def_time_scale);
904
905 auto add_domain_rhs_ops = [&](auto &pipeline) {
907 CHKERR addMatThermalBlockOps(pipeline, "MAT_THERMAL", block_thermal_params,
908 Sev::inform);
909 CHKERR addMatThermoElasticBlockOps(pipeline, "MAT_THERMOELASTIC",
910 block_thermoelastic_params, Sev::inform);
912
913 auto hencky_common_data_ptr =
914 HenckyOps::commonDataFactory<SPACE_DIM, IT, DomainEleOp>(
915 mField, pipeline, "U", "MAT_ELASTIC", Sev::inform);
916 auto mat_D_ptr = hencky_common_data_ptr->matDPtr;
917 auto mat_grad_ptr = hencky_common_data_ptr->matGradPtr;
918 auto mat_strain_ptr = boost::make_shared<MatrixDouble>();
919 auto mat_stress_ptr = boost::make_shared<MatrixDouble>();
920
921 auto vec_temp_ptr = boost::make_shared<VectorDouble>();
922 auto vec_temp_dot_ptr = boost::make_shared<VectorDouble>();
923 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
924 auto vec_temp_div_ptr = boost::make_shared<VectorDouble>();
925
926 pipeline.push_back(new OpCalculateScalarFieldValues("T", vec_temp_ptr));
927 pipeline.push_back(
928 new OpCalculateScalarFieldValuesDot("T", vec_temp_dot_ptr));
930 "FLUX", vec_temp_div_ptr));
931 pipeline.push_back(
932 new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", mat_flux_ptr));
933
934 CHKERR opThermoElasticFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
935 mField, pipeline, "U", "MAT_ELASTIC", "MAT_THERMAL",
936 "MAT_THERMOELASTIC", Sev::inform);
937
938 auto resistance = [heat_conductivity_ptr](const double, const double,
939 const double) {
940 return (1. / (*heat_conductivity_ptr));
941 };
942 // negative value is consequence of symmetric system
943 auto capacity = [heat_capacity_ptr](const double, const double,
944 const double) {
945 return -(*heat_capacity_ptr);
946 };
947 auto unity = [](const double, const double, const double) constexpr {
948 return -1.;
949 };
950 pipeline.push_back(
951 new OpHdivFlux("FLUX", mat_flux_ptr, resistance, mat_grad_ptr));
952 pipeline.push_back(new OpHDivTemp("FLUX", vec_temp_ptr, unity));
953 pipeline.push_back(new OpBaseDivFlux("T", vec_temp_div_ptr, unity));
954 pipeline.push_back(new OpBaseDotT("T", vec_temp_dot_ptr, capacity));
955
956 // Set source terms
958 pipeline, mField, "T", {time_scale, time_heatsource_scaling},
959 "HEAT_SOURCE", Sev::inform);
961 pipeline, mField, "U", {time_scale, time_bodyforce_scaling},
962 "BODY_FORCE", Sev::inform);
964 pipeline, mField, "T", vec_temp_ptr, "SETTEMP", Sev::inform);
965
967 };
968
969 auto add_domain_lhs_ops = [&](auto &pipeline) {
971 CHKERR addMatThermalBlockOps(pipeline, "MAT_THERMAL", block_thermal_params,
972 Sev::verbose);
973 CHKERR addMatThermoElasticBlockOps(pipeline, "MAT_THERMOELASTIC",
974 block_thermoelastic_params,
975 Sev::verbose);
977
978 auto hencky_common_data_ptr =
979 HenckyOps::commonDataFactory<SPACE_DIM, IT, DomainEleOp>(
980 mField, pipeline, "U", "MAT_ELASTIC", Sev::inform, 1);
981 auto mat_D_ptr = hencky_common_data_ptr->matDPtr;
982 auto mat_grad_ptr = hencky_common_data_ptr->matGradPtr;
983
984 auto resistance = [heat_conductivity_ptr](const double, const double,
985 const double) {
986 return (1. / (*heat_conductivity_ptr));
987 };
988 auto capacity = [heat_capacity_ptr](const double, const double,
989 const double) {
990 return -(*heat_capacity_ptr);
991 };
992 pipeline.push_back(
993 new OpHdivHdiv("FLUX", "FLUX", resistance, mat_grad_ptr));
994 pipeline.push_back(
995 new OpHdivT("FLUX", "T", []() constexpr { return -1; }, true));
996
997 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
998 pipeline.push_back(
999 new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", mat_flux_ptr));
1000
1001 pipeline.push_back(
1002 new OpHdivU("FLUX", "U", mat_flux_ptr, resistance, mat_grad_ptr));
1003
1004 CHKERR opThermoElasticFactoryDomainLhs<SPACE_DIM, AT, IT, DomainEleOp>(
1005 mField, pipeline, "U", "T", "MAT_ELASTIC", "MAT_THERMAL",
1006 "MAT_THERMOELASTIC", Sev::inform);
1007
1008 auto op_capacity = new OpCapacity("T", "T", capacity);
1009 op_capacity->feScalingFun = [](const FEMethod *fe_ptr) {
1010 return fe_ptr->ts_a;
1011 };
1012 pipeline.push_back(op_capacity);
1013
1014 auto vec_temp_ptr = boost::make_shared<VectorDouble>();
1015 pipeline.push_back(new OpCalculateScalarFieldValues("T", vec_temp_ptr));
1017 pipeline, mField, "T", vec_temp_ptr, "SETTEMP", Sev::verbose);
1018
1020 };
1021
1022 auto add_boundary_rhs_ops = [&](auto &pipeline) {
1024
1026
1028 pipeline, mField, "U", {time_scale, time_force_scaling}, "FORCE",
1029 Sev::inform);
1030
1031 // Temperature BC
1032
1033 using OpTemperatureBC =
1036 pipeline, mField, "FLUX", {time_scale, time_temperature_scaling},
1037 "TEMPERATURE", Sev::inform);
1038
1039 // Note: fluxes for temperature should be aggregated. Here separate is
1040 // NaturalMeshsetType<HEATFLUXSET>, we should add version with BLOCKSET,
1041 // convection, see example tutorials/vec-0_elasticity/src/NaturalBoundaryBC.hpp.
1042 // and vec-0_elasticity/elastic.cpp
1043
1044 using OpFluxBC =
1047 pipeline, mField, "TBC", {time_scale, time_flux_scaling}, "FLUX",
1048 Sev::inform);
1049
1051 using OpConvectionRhsBC =
1052 T::OpFlux<ThermoElasticOps::ConvectionBcType<BLOCKSET>, 1, 1>;
1053 using OpRadiationRhsBC =
1054 T::OpFlux<ThermoElasticOps::RadiationBcType<BLOCKSET>, 1, 1>;
1055 auto temp_bc_ptr = boost::make_shared<VectorDouble>();
1056 pipeline.push_back(new OpCalculateScalarFieldValues("TBC", temp_bc_ptr));
1057 T::AddFluxToPipeline<OpConvectionRhsBC>::add(
1058 pipeline, mField, "TBC", temp_bc_ptr,
1059 {time_scale, time_convection_temp_scaling}, "CONVECTION", Sev::inform);
1060 T::AddFluxToPipeline<OpRadiationRhsBC>::add(
1061 pipeline, mField, "TBC", temp_bc_ptr,
1062 {time_scale, time_radiation_temp_scaling}, "RADIATION", Sev::inform);
1063
1064 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
1065 pipeline.push_back(
1066 new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", mat_flux_ptr));
1067
1068 // This is temporary implementation. It be moved to LinearFormsIntegrators,
1069 // however for hybridised case, what is goal of this changes, such function
1070 // is implemented for fluxes in broken space. Thus ultimately this operator
1071 // would be not needed.
1072
1073 struct OpTBCTimesNormalFlux
1074 : public FormsIntegrators<BoundaryEleOp>::Assembly<PETSC>::OpBase {
1075
1077
1078 OpTBCTimesNormalFlux(const std::string field_name,
1079 boost::shared_ptr<MatrixDouble> vec,
1080 boost::shared_ptr<Range> ents_ptr = nullptr)
1081 : OP(field_name, field_name, OP::OPROW, ents_ptr), sourceVec(vec) {}
1082
1083 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data) {
1086 // get integration weights
1087 auto t_w = OP::getFTensor0IntegrationWeight();
1088 // get base function values on rows
1089 auto t_row_base = row_data.getFTensor0N();
1090 // get normal vector
1091 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1092 // get vector values
1093 auto t_vec = getFTensor1FromMat<SPACE_DIM, 1>(*sourceVec);
1094 // loop over integration points
1095 for (int gg = 0; gg != OP::nbIntegrationPts; gg++) {
1096 // take into account Jacobian
1097 const double alpha = t_w * (t_vec(i) * t_normal(i));
1098 // loop over rows base functions
1099 int rr = 0;
1100 for (; rr != OP::nbRows; ++rr) {
1101 OP::locF[rr] += alpha * t_row_base;
1102 ++t_row_base;
1103 }
1104 for (; rr < OP::nbRowBaseFunctions; ++rr)
1105 ++t_row_base;
1106 ++t_w; // move to another integration weight
1107 ++t_vec;
1108 ++t_normal;
1109 }
1110 EntityType fe_type = OP::getNumeredEntFiniteElementPtr()->getEntType();
1111 if (fe_type == MBTRI) {
1112 OP::locF /= 2;
1113 }
1115 }
1116
1117 protected:
1118 boost::shared_ptr<MatrixDouble> sourceVec;
1119 };
1120 pipeline.push_back(new OpTBCTimesNormalFlux("TBC", mat_flux_ptr));
1121
1122 struct OpBaseNormalTimesTBC
1123 : public FormsIntegrators<BoundaryEleOp>::Assembly<PETSC>::OpBase {
1124
1126
1127 OpBaseNormalTimesTBC(const std::string field_name,
1128 boost::shared_ptr<VectorDouble> vec,
1129 boost::shared_ptr<Range> ents_ptr = nullptr)
1130 : OP(field_name, field_name, OP::OPROW, ents_ptr), sourceVec(vec) {}
1131
1132 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data) {
1135 // get integration weights
1136 auto t_w = OP::getFTensor0IntegrationWeight();
1137 // get base function values on rows
1138 auto t_row_base = row_data.getFTensor1N<3>();
1139 // get normal vector
1140 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1141 // get vector values
1142 auto t_vec = getFTensor0FromVec(*sourceVec);
1143 // loop over integration points
1144 for (int gg = 0; gg != OP::nbIntegrationPts; gg++) {
1145 // take into account Jacobian
1146 const double alpha = t_w * t_vec;
1147 // loop over rows base functions
1148 int rr = 0;
1149 for (; rr != OP::nbRows; ++rr) {
1150 OP::locF[rr] += alpha * (t_row_base(i) * t_normal(i));
1151 ++t_row_base;
1152 }
1153 for (; rr < OP::nbRowBaseFunctions; ++rr)
1154 ++t_row_base;
1155 ++t_w; // move to another integration weight
1156 ++t_vec;
1157 ++t_normal;
1158 }
1159 EntityType fe_type = OP::getNumeredEntFiniteElementPtr()->getEntType();
1160 if (fe_type == MBTRI) {
1161 OP::locF /= 2;
1162 }
1164 }
1165
1166 protected:
1167 boost::shared_ptr<VectorDouble> sourceVec;
1168 };
1169
1170 pipeline.push_back(new OpBaseNormalTimesTBC("FLUX", temp_bc_ptr));
1171
1173 };
1174
1175 auto add_boundary_lhs_ops = [&](auto &pipeline) {
1177
1179
1180 using T =
1181 NaturalBC<BoundaryEleOp>::template Assembly<PETSC>::BiLinearForm<GAUSS>;
1182 using OpConvectionLhsBC =
1183 T::OpFlux<ThermoElasticOps::ConvectionBcType<BLOCKSET>, 1, 1>;
1184 using OpRadiationLhsBC =
1185 T::OpFlux<ThermoElasticOps::RadiationBcType<BLOCKSET>, 1, 1>;
1186 auto temp_bc_ptr = boost::make_shared<VectorDouble>();
1187 pipeline.push_back(new OpCalculateScalarFieldValues("TBC", temp_bc_ptr));
1188 T::AddFluxToPipeline<OpConvectionLhsBC>::add(pipeline, mField, "TBC", "TBC",
1189 "CONVECTION", Sev::verbose);
1190 T::AddFluxToPipeline<OpRadiationLhsBC>::add(
1191 pipeline, mField, "TBC", "TBC", temp_bc_ptr, "RADIATION", Sev::verbose);
1192
1193 // This is temporary implementation. It be moved to LinearFormsIntegrators,
1194 // however for hybridised case, what is goal of this changes, such function
1195 // is implemented for fluxes in broken space. Thus ultimately this operator
1196 // would be not needed.
1197
1198 struct OpTBCTimesNormalFlux
1199 : public FormsIntegrators<BoundaryEleOp>::Assembly<PETSC>::OpBase {
1200
1202
1203 OpTBCTimesNormalFlux(const std::string row_field_name,
1204 const std::string col_field_name,
1205 boost::shared_ptr<Range> ents_ptr = nullptr)
1206 : OP(row_field_name, col_field_name, OP::OPROWCOL, ents_ptr) {
1207 this->sYmm = false;
1208 this->assembleTranspose = true;
1209 this->onlyTranspose = false;
1210 }
1211
1212 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data,
1213 EntitiesFieldData::EntData &col_data) {
1215
1217
1218 // get integration weights
1219 auto t_w = OP::getFTensor0IntegrationWeight();
1220 // get base function values on rows
1221 auto t_row_base = row_data.getFTensor0N();
1222 // get normal vector
1223 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1224 // loop over integration points
1225 for (int gg = 0; gg != OP::nbIntegrationPts; gg++) {
1226 // loop over rows base functions
1227 auto a_mat_ptr = &*OP::locMat.data().begin();
1228 int rr = 0;
1229 for (; rr != OP::nbRows; rr++) {
1230 // take into account Jacobian
1231 const double alpha = t_w * t_row_base;
1232 // get column base functions values at gauss point gg
1233 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
1234 // loop over columns
1235 for (int cc = 0; cc != OP::nbCols; cc++) {
1236 // calculate element of local matrix
1237 // using L2 norm of normal vector for convenient area calculation
1238 // for quads, tris etc.
1239 *a_mat_ptr += alpha * (t_col_base(i) * t_normal(i));
1240 ++t_col_base;
1241 ++a_mat_ptr;
1242 }
1243 ++t_row_base;
1244 }
1245 for (; rr < OP::nbRowBaseFunctions; ++rr)
1246 ++t_row_base;
1247 ++t_normal;
1248 ++t_w; // move to another integration weight
1249 }
1250 EntityType fe_type = OP::getNumeredEntFiniteElementPtr()->getEntType();
1251 if (fe_type == MBTRI) {
1252 OP::locMat /= 2;
1253 }
1255 }
1256 };
1257
1258 pipeline.push_back(new OpTBCTimesNormalFlux("TBC", "FLUX"));
1259
1261 };
1262
1263 // Set BCs by eliminating degrees of freedom
1264 auto get_bc_hook_rhs = [&]() {
1266 mField, pipeline_mng->getDomainRhsFE(),
1267 {time_scale, time_displacement_scaling});
1268 return hook;
1269 };
1270 auto get_bc_hook_lhs = [&]() {
1272 mField, pipeline_mng->getDomainLhsFE(),
1273 {time_scale, time_displacement_scaling});
1274 return hook;
1275 };
1276
1277 pipeline_mng->getDomainRhsFE()->preProcessHook = get_bc_hook_rhs();
1278 pipeline_mng->getDomainLhsFE()->preProcessHook = get_bc_hook_lhs();
1279
1280 CHKERR add_domain_rhs_ops(pipeline_mng->getOpDomainRhsPipeline());
1281 CHKERR add_domain_lhs_ops(pipeline_mng->getOpDomainLhsPipeline());
1282 CHKERR add_boundary_rhs_ops(pipeline_mng->getOpBoundaryRhsPipeline());
1283 CHKERR add_boundary_lhs_ops(pipeline_mng->getOpBoundaryLhsPipeline());
1284
1286}
1287//! [Push operators to pipeline]
1288
1289//! [Solve]
1292
1295 ISManager *is_manager = mField.getInterface<ISManager>();
1296
1297 auto dm = simple->getDM();
1298 auto solver = pipeline_mng->createTSIM();
1299 auto snes_ctx_ptr = getDMSnesCtx(dm);
1300
1301 auto set_section_monitor = [&](auto solver) {
1303 SNES snes;
1304 CHKERR TSGetSNES(solver, &snes);
1305 CHKERR SNESMonitorSet(snes,
1306 (MoFEMErrorCode(*)(SNES, PetscInt, PetscReal,
1307 void *))MoFEMSNESMonitorFields,
1308 (void *)(snes_ctx_ptr.get()), nullptr);
1310 };
1311
1312 auto create_post_process_elements = [&]() {
1313 auto block_thermal_params = boost::make_shared<BlockedThermalParameters>();
1314
1315 auto block_thermoelastic_params =
1316 boost::make_shared<BlockedThermoElasticParameters>();
1317 auto coeff_expansion_ptr =
1318 block_thermoelastic_params->getCoeffExpansionPtr();
1319 auto ref_temp_ptr = block_thermoelastic_params->getRefTempPtr();
1320
1321 auto u_ptr = boost::make_shared<MatrixDouble>();
1322 auto mat_grad_ptr = boost::make_shared<MatrixDouble>();
1323 auto mat_strain_ptr = boost::make_shared<MatrixDouble>();
1324 auto mat_stress_ptr = boost::make_shared<MatrixDouble>();
1325 auto vec_temp_ptr = boost::make_shared<VectorDouble>();
1326 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
1327
1328 auto push_domain_ops = [&](auto &pp_fe) {
1330 auto &pip = pp_fe->getOpPtrVector();
1331
1332 CHKERR addMatThermalBlockOps(pip, "MAT_THERMAL", block_thermal_params,
1333 Sev::verbose);
1335 pip, "MAT_THERMOELASTIC", block_thermoelastic_params, Sev::verbose);
1336
1338
1339 pip.push_back(new OpCalculateScalarFieldValues("T", vec_temp_ptr));
1340 pip.push_back(
1341 new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", mat_flux_ptr));
1342
1343 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
1345 "U", mat_grad_ptr));
1346 auto elastic_common_ptr = commonDataFactory<SPACE_DIM, IT, DomainEleOp>(
1347 mField, pip, "U", "MAT_ELASTIC", Sev::inform);
1349 pip.push_back(
1350 new
1351 typename H::template OpCalculateHenckyThermalStress<SPACE_DIM, IT, 0>(
1352 "U", vec_temp_ptr, elastic_common_ptr, coeff_expansion_ptr,
1353 ref_temp_ptr));
1354 if (!IS_LARGE_STRAINS) {
1355 pip.push_back(new OpSymmetrizeTensor<SPACE_DIM>(
1356 elastic_common_ptr->getMatFirstPiolaStress(), mat_stress_ptr));
1357 pip.push_back(
1358 new OpSymmetrizeTensor<SPACE_DIM>(mat_grad_ptr, mat_strain_ptr));
1359 } else {
1360 mat_stress_ptr = elastic_common_ptr->getMatFirstPiolaStress();
1361 mat_strain_ptr = elastic_common_ptr->getMatLogC();
1362 }
1363
1365 };
1366
1367 auto push_post_proc_ops = [&](auto &pp_fe) {
1369 auto &pip = pp_fe->getOpPtrVector();
1371
1372 if (!IS_LARGE_STRAINS) {
1373 pip.push_back(
1374
1375 new OpPPMap(
1376
1377 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
1378
1379 {{"T", vec_temp_ptr}},
1380
1381 {{"U", u_ptr}, {"FLUX", mat_flux_ptr}},
1382
1383 {},
1384
1385 {{"CAUCHY", mat_stress_ptr}, {"STRAIN", mat_strain_ptr}}
1386
1387 )
1388
1389 );
1390 } else {
1391 pip.push_back(
1392
1393 new OpPPMap(
1394
1395 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
1396
1397 {{"T", vec_temp_ptr}},
1398
1399 {{"U", u_ptr}, {"FLUX", mat_flux_ptr}},
1400
1401 {{"PIOLA", mat_stress_ptr}},
1402
1403 {{"HENCKY_STRAIN", mat_strain_ptr}}
1404
1405 )
1406
1407 );
1408 }
1409
1411 };
1412
1413 auto domain_post_proc = [&]() {
1414 if (do_output_domain == PETSC_FALSE)
1415 return boost::shared_ptr<PostProcEle>();
1416 auto pp_fe = boost::make_shared<PostProcEle>(mField);
1417 CHK_MOAB_THROW(push_domain_ops(pp_fe),
1418 "push domain ops to domain element");
1419 CHK_MOAB_THROW(push_post_proc_ops(pp_fe),
1420 "push post proc ops to domain element");
1421 return pp_fe;
1422 };
1423
1424 auto skin_post_proc = [&]() {
1425 if (do_output_skin == PETSC_FALSE)
1426 return boost::shared_ptr<SkinPostProcEle>();
1427 auto pp_fe = boost::make_shared<SkinPostProcEle>(mField);
1428 auto simple = mField.getInterface<Simple>();
1429 auto op_side = new OpLoopSide<SideEle>(mField, simple->getDomainFEName(),
1430 SPACE_DIM, Sev::verbose);
1431 CHK_MOAB_THROW(push_domain_ops(op_side),
1432 "push domain ops to side element");
1433 pp_fe->getOpPtrVector().push_back(op_side);
1434 CHK_MOAB_THROW(push_post_proc_ops(pp_fe),
1435 "push post proc ops to skin element");
1436 return pp_fe;
1437 };
1438
1439 return std::make_pair(domain_post_proc(), skin_post_proc());
1440 };
1441
1442 auto monitor_ptr = boost::make_shared<FEMethod>();
1443
1444 auto set_time_monitor = [&](auto dm, auto solver, auto domain_post_proc_fe,
1445 auto skin_post_proc_fe) {
1447 monitor_ptr->preProcessHook = [&]() {
1449
1450 if (save_every && (monitor_ptr->ts_step % save_every == 0)) {
1451 if (do_output_domain) {
1452 CHKERR DMoFEMLoopFiniteElements(dm, simple->getDomainFEName(),
1453 domain_post_proc_fe,
1454 monitor_ptr->getCacheWeakPtr());
1455 CHKERR domain_post_proc_fe->writeFile(
1456 "out_" + boost::lexical_cast<std::string>(monitor_ptr->ts_step) +
1457 ".h5m");
1458 }
1459 if (do_output_skin) {
1460 CHKERR DMoFEMLoopFiniteElements(dm, simple->getBoundaryFEName(),
1461 skin_post_proc_fe,
1462 monitor_ptr->getCacheWeakPtr());
1463 CHKERR skin_post_proc_fe->writeFile(
1464 "out_skin_" +
1465 boost::lexical_cast<std::string>(monitor_ptr->ts_step) + ".h5m");
1466 }
1467 }
1468
1469 struct AtomTestResult {
1470 bool fail = false;
1471 std::string msg = "";
1472 };
1473 AtomTestResult atom_test_result;
1474
1475 auto fail_atom_test = [&atom_test_result](const std::string &msg) {
1476 atom_test_result.fail = true;
1477 atom_test_result.msg = msg;
1478 };
1479
1480 struct AtomTestData{
1481 double expected = 0.0;
1482 double tol = 0.0;
1483 };
1484
1485 if (doEvalField) {
1486
1487 CHKERR mField.getInterface<FieldEvaluatorInterface>()
1488 ->evalFEAtThePoint<SPACE_DIM>(
1489 fieldEvalCoords.data(), 1e-12, simple->getProblemName(),
1490 simple->getDomainFEName(), fieldEvalData,
1491 mField.get_comm_rank(), mField.get_comm_rank(), nullptr,
1492 MF_EXIST, QUIET);
1493
1494 if (atom_test) {
1495 auto eval_num_vec =
1496 createVectorMPI(mField.get_comm(), PETSC_DECIDE, 1);
1497 CHKERR VecZeroEntries(eval_num_vec);
1498 if (tempFieldPtr->size()) {
1499 CHKERR VecSetValue(eval_num_vec, 0, 1, ADD_VALUES);
1500 }
1501 CHKERR VecAssemblyBegin(eval_num_vec);
1502 CHKERR VecAssemblyEnd(eval_num_vec);
1503
1504 double eval_num;
1505 CHKERR VecSum(eval_num_vec, &eval_num);
1506 if (!(int)eval_num) {
1507 fail_atom_test(
1508 "did not find elements to evaluate the field, check the "
1509 "coordinates");
1510 }
1511 }
1512
1513 if (tempFieldPtr->size()) {
1514 auto t_temp = getFTensor0FromVec(*tempFieldPtr);
1515 MOFEM_LOG("ThermoElasticSync", Sev::inform)
1516 << "Eval point T: " << t_temp;
1517 if (atom_test && fabs(monitor_ptr->ts_t - 10) < 1e-12) {
1518 AtomTestData atom_test_data;
1519 switch (atom_test) {
1520 case 1:
1521 case 2:
1522 case 3:
1523 atom_test_data = {554.48, 1e-2};
1524 break;
1525 case 4:
1526 atom_test_data = {250.0, 1e-2};
1527 break;
1528 case 5:
1529 atom_test_data = {1.0, 1e-2};
1530 break;
1531 default:
1532 fail_atom_test("unknown atom test number");
1533 }
1534 if (fabs(t_temp - atom_test_data.expected) > atom_test_data.tol) {
1535 fail_atom_test("wrong temperature value");
1536 }
1537 }
1538 }
1539 if (fluxFieldPtr->size1()) {
1541 auto t_flux = getFTensor1FromMat<SPACE_DIM>(*fluxFieldPtr);
1542 auto flux_mag = sqrt(t_flux(i) * t_flux(i));
1543 MOFEM_LOG("ThermoElasticSync", Sev::inform)
1544 << "Eval point FLUX magnitude: " << flux_mag;
1545 if (atom_test && fabs(monitor_ptr->ts_t - 10) < 1e-12) {
1546 AtomTestData atom_test_data;
1547 switch (atom_test) {
1548 case 1:
1549 case 2:
1550 case 3:
1551 atom_test_data = {27008.0, 2e1};
1552 break;
1553 case 4:
1554 atom_test_data = {150e3, 1e-1};
1555 break;
1556 case 5:
1557 atom_test_data = {0.0, 1e-6};
1558 break;
1559 default:
1560 fail_atom_test("unknown atom test number");
1561 }
1562 if (fabs(flux_mag - atom_test_data.expected) > atom_test_data.tol) {
1563 fail_atom_test("wrong flux value");
1564 }
1565 }
1566 }
1567 if (dispFieldPtr->size1()) {
1569 auto t_disp = getFTensor1FromMat<SPACE_DIM>(*dispFieldPtr);
1570 auto disp_mag = sqrt(t_disp(i) * t_disp(i));
1571 MOFEM_LOG("ThermoElasticSync", Sev::inform)
1572 << "Eval point U magnitude: " << disp_mag;
1573 if (atom_test && fabs(monitor_ptr->ts_t - 10) < 1e-12) {
1574 AtomTestData atom_test_data;
1575 switch (atom_test) {
1576 case 1:
1577 atom_test_data = {0.00345, 1e-5};
1578 break;
1579 case 2:
1580 case 3:
1581 atom_test_data = {0.00265, 1e-5};
1582 break;
1583 case 4:
1584 atom_test_data = {0.00061, 1e-5};
1585 break;
1586 case 5:
1587 atom_test_data = {std::sqrt(2) * (std::sqrt(std::exp(0.2)) - 1),
1588 1e-5};
1589 break;
1590 default:
1591 fail_atom_test("unknown atom test number");
1592 }
1593 if (fabs(disp_mag - atom_test_data.expected) > atom_test_data.tol) {
1594 fail_atom_test("wrong displacement value");
1595 }
1596 }
1597 }
1598 if (strainFieldPtr->size1()) {
1600 auto t_strain =
1601 getFTensor2SymmetricFromMat<SPACE_DIM>(*strainFieldPtr);
1602 auto t_strain_trace = t_strain(i, i);
1603 if (atom_test && fabs(monitor_ptr->ts_t - 10) < 1e-12) {
1604 AtomTestData atom_test_data;
1605 switch (atom_test) {
1606 case 1:
1607 atom_test_data = {0.00679, 1e-5};
1608 break;
1609 case 2:
1610 case 3:
1611 atom_test_data = {0.00522, 1e-5};
1612 break;
1613 case 4:
1614 atom_test_data = {-0.00085, 1e-5};
1615 break;
1616 case 5:
1617 atom_test_data = {0.2, 1e-5};
1618 break;
1619 default:
1620 fail_atom_test("unknown atom test number");
1621 }
1622 if (fabs(t_strain_trace - atom_test_data.expected) >
1623 atom_test_data.tol) {
1624 fail_atom_test("wrong strain value");
1625 }
1626 }
1627 }
1628 if (stressFieldPtr->size1()) {
1629 double von_mises_stress;
1630 auto getVonMisesStress = [&](auto t_stress) {
1632 von_mises_stress = std::sqrt(
1633 0.5 *
1634 ((t_stress(0, 0) - t_stress(1, 1)) *
1635 (t_stress(0, 0) - t_stress(1, 1)) +
1636 (SPACE_DIM == 3 ? (t_stress(1, 1) - t_stress(2, 2)) *
1637 (t_stress(1, 1) - t_stress(2, 2))
1638 : 0) +
1639 (SPACE_DIM == 3 ? (t_stress(2, 2) - t_stress(0, 0)) *
1640 (t_stress(2, 2) - t_stress(0, 0))
1641 : 0) +
1642 6 * (t_stress(0, 1) * t_stress(0, 1) +
1643 (SPACE_DIM == 3 ? t_stress(1, 2) * t_stress(1, 2) : 0) +
1644 (SPACE_DIM == 3 ? t_stress(2, 0) * t_stress(2, 0) : 0))));
1646 };
1647 if (!IS_LARGE_STRAINS) {
1648 auto t_stress =
1649 getFTensor2SymmetricFromMat<SPACE_DIM>(*stressFieldPtr);
1650 CHKERR getVonMisesStress(t_stress);
1651 } else {
1652 auto t_stress =
1653 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*stressFieldPtr);
1654 CHKERR getVonMisesStress(t_stress);
1655 }
1656 MOFEM_LOG("ThermoElasticSync", Sev::inform)
1657 << "Eval point von Mises Stress: " << von_mises_stress;
1658 if (atom_test && fabs(monitor_ptr->ts_t - 10) < 1e-12) {
1659 AtomTestData atom_test_data;
1660 switch (atom_test) {
1661 case 1:
1662 atom_test_data = {523.0, 5e-1};
1663 break;
1664 case 2:
1665 atom_test_data = {16.3, 5e-2};
1666 break;
1667 case 3:
1668 atom_test_data = {14.9, 5e-2};
1669 break;
1670 case 4:
1671 atom_test_data = {92.3, 2e-1};
1672 break;
1673 case 5:
1674 atom_test_data = {0.0, 5e-2};
1675 break;
1676 default:
1677 fail_atom_test("unknown atom test number");
1678 }
1679 if (fabs(von_mises_stress - atom_test_data.expected) >
1680 atom_test_data.tol) {
1681 fail_atom_test("wrong von Mises stress value");
1682 }
1683 }
1684 }
1685 MOFEM_LOG_SYNCHRONISE(mField.get_comm());
1686 }
1687
1688 if (atom_test_result.fail) {
1689 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
1690 "atom test %d failed: %s", atom_test,
1691 atom_test_result.msg.c_str());
1692 }
1693
1695 };
1696 auto null = boost::shared_ptr<FEMethod>();
1697 CHKERR DMMoFEMTSSetMonitor(dm, solver, simple->getDomainFEName(), null,
1698 monitor_ptr, null);
1700 };
1701
1702 auto set_fieldsplit_preconditioner = [&](auto solver) {
1704
1705 SNES snes;
1706 CHKERR TSGetSNES(solver, &snes);
1707 KSP ksp;
1708 CHKERR SNESGetKSP(snes, &ksp);
1709 PC pc;
1710 CHKERR KSPGetPC(ksp, &pc);
1711 PetscBool is_pcfs = PETSC_FALSE;
1712 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
1713
1714 // Setup fieldsplit (block) solver - optional: yes/no
1715 if (is_pcfs == PETSC_TRUE) {
1716 auto is_mng = mField.getInterface<ISManager>();
1717 auto name_prb = simple->getProblemName();
1718
1719 SmartPetscObj<IS> is_u;
1720 CHKERR is_mng->isCreateProblemFieldAndRank(name_prb, ROW, "U", 0,
1721 SPACE_DIM, is_u);
1722 SmartPetscObj<IS> is_flux;
1723 CHKERR is_mng->isCreateProblemFieldAndRank(name_prb, ROW, "FLUX", 0, 0,
1724 is_flux);
1725 SmartPetscObj<IS> is_T;
1726 CHKERR is_mng->isCreateProblemFieldAndRank(name_prb, ROW, "T", 0, 0,
1727 is_T);
1728 SmartPetscObj<IS> is_TBC;
1729 CHKERR is_mng->isCreateProblemFieldAndRank(name_prb, ROW, "TBC", 0, 0,
1730 is_TBC);
1731 IS is_tmp, is_tmp2;
1732 CHKERR ISExpand(is_T, is_flux, &is_tmp);
1733 CHKERR ISExpand(is_TBC, is_tmp, &is_tmp2);
1734 CHKERR ISDestroy(&is_tmp);
1735 auto is_TFlux = SmartPetscObj<IS>(is_tmp2);
1736
1737 CHKERR ISSort(is_u);
1738 CHKERR ISSort(is_TFlux);
1739 CHKERR PCFieldSplitSetIS(pc, PETSC_NULLPTR, is_TFlux);
1740 CHKERR PCFieldSplitSetIS(pc, PETSC_NULLPTR, is_u);
1741 }
1742
1744 };
1745
1746 auto B = createDMMatrix(dm);
1747 CHKERR TSSetIJacobian(solver, B, B, PETSC_NULLPTR, PETSC_NULLPTR);
1748 auto D = createDMVector(dm);
1749 CHKERR DMoFEMMeshToLocalVector(dm, D, INSERT_VALUES, SCATTER_FORWARD);
1750 CHKERR TSSetSolution(solver, D);
1751 CHKERR TSSetFromOptions(solver);
1752
1753 CHKERR set_section_monitor(solver);
1754 CHKERR set_fieldsplit_preconditioner(solver);
1755
1756 auto [domain_post_proc_fe, skin_post_proc_fe] =
1757 create_post_process_elements();
1758 CHKERR set_time_monitor(dm, solver, domain_post_proc_fe, skin_post_proc_fe);
1759
1760 CHKERR TSSetUp(solver);
1761 CHKERR TSSolve(solver, NULL);
1762
1764}
1765//! [Solve]
1766
1767static char help[] = "...\n\n";
1768
1769int main(int argc, char *argv[]) {
1770
1771 // Initialisation of MoFEM/PETSc and MOAB data structures
1772 const char param_file[] = "param_file.petsc";
1773 MoFEM::Core::Initialize(&argc, &argv, param_file, help);
1774
1775 // Add logging channel for example
1776 auto core_log = logging::core::get();
1777 core_log->add_sink(
1779 LogManager::setLog("ThermoElastic");
1780 MOFEM_LOG_TAG("ThermoElastic", "ThermoElastic");
1781
1782 core_log->add_sink(
1783 LogManager::createSink(LogManager::getStrmSync(), "ThermoElasticSync"));
1784 LogManager::setLog("ThermoElasticSync");
1785 MOFEM_LOG_TAG("ThermoElasticSync", "ThermoElasticSync");
1786
1787 try {
1788
1789 //! [Register MoFEM discrete manager in PETSc]
1790 DMType dm_name = "DMMOFEM";
1791 CHKERR DMRegister_MoFEM(dm_name);
1792 //! [Register MoFEM discrete manager in PETSc
1793
1794 //! [Create MoAB]
1795 moab::Core mb_instance; ///< mesh database
1796 moab::Interface &moab = mb_instance; ///< mesh database interface
1797 //! [Create MoAB]
1798
1799 //! [Create MoFEM]
1800 MoFEM::Core core(moab); ///< finite element database
1801 MoFEM::Interface &m_field = core; ///< finite element database interface
1802 //! [Create MoFEM]
1803
1804 //! [Load mesh]
1805 Simple *simple = m_field.getInterface<Simple>();
1807 CHKERR simple->loadFile();
1808 //! [Load mesh]
1809
1810 //! [ThermoElasticProblem]
1811 ThermoElasticProblem ex(m_field);
1812 CHKERR ex.runProblem();
1813 //! [ThermoElasticProblem]
1814 }
1816
1818}
static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin)
#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)
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
int main()
constexpr int SPACE_DIM
DomainEle::UserDataOperator DomainEleOp
Finire element operator type.
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
@ QUIET
@ ROW
#define CATCH_ERRORS
Catch errors.
@ MF_EXIST
FieldApproximationBase
approximation base
Definition definitions.h:58
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
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 ...
auto integration_rule
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode)
set local (or ghosted) vector values on mesh for partition only
Definition DMMoFEM.cpp: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
auto createDMVector(DM dm)
Get smart vector from DM.
Definition DMMoFEM.hpp:1234
auto createDMMatrix(DM dm)
Get smart matrix from DM.
Definition DMMoFEM.hpp:1191
IntegrationType
Form integrator integration types.
AssemblyType
[Storage and set boundary conditions]
@ GAUSS
Gaussian quadrature integration.
@ PETSC
Standard PETSc assembly.
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
double tol
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:1046
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
MoFEMErrorCode MoFEMSNESMonitorFields(SNES snes, PetscInt its, PetscReal fgnorm, SnesCtx *ctx)
Sens monitor printing residual field by field.
Definition SnesCtx.cpp:596
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 auto getFTensor0FromVec(ublas::vector< T, A > &data)
Get tensor rank 0 (scalar) form data vector.
OpCalculateScalarFieldValuesFromPetscVecImpl< PetscData::CTX_SET_X_T > OpCalculateScalarFieldValuesDot
auto get_temp_meshset_ptr(moab::Interface &moab)
Create smart pointer to temporary meshset.
auto getDMSnesCtx(DM dm)
Get SNES context data structure used by DM.
Definition DMMoFEM.hpp:1262
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMixDivTimesScalar< SPACE_DIM > OpHdivT
Integrate Lhs div of base of flux times base of temperature (FLUX x T) and transpose of it,...
OpHdivHdivImpl< SPACE_DIM, IS_LARGE_STRAINS > OpHdivHdiv
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)
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpBaseTimesScalar< 1 > OpBaseDotT
Integrate Rhs base of temperature time heat capacity times heat rate (T)
OpBaseDotT OpBaseDivFlux
Integrate Rhs base of temperature times divergence of flux (T)
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpMixDivTimesU< 3, 1, SPACE_DIM > OpHDivTemp
Integrate Rhs div flux base times temperature (T)
OpCalculateQdotQLhs_dU< SPACE_DIM, GAUSS, AssemblyDomainEleOp, IS_LARGE_STRAINS > OpHdivU
Integrate Lhs of flux term coupled to displacement field.
OpHdivFluxImpl< SPACE_DIM, IS_LARGE_STRAINS > OpHdivFlux
FormsIntegrators< DomainEleOp >::Assembly< A >::LinearForm< I >::OpGradTimesTensor< 1, FIELD_DIM, SPACE_DIM > OpGradTimesTensor
constexpr IntegrationType I
constexpr AssemblyType A
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
constexpr auto field_name
static constexpr int approx_order
OpBaseImpl< PETSC, EdgeEleOp > OpBase
Definition radiation.cpp:29
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpGradTimesTensor< 1, SPACE_DIM, SPACE_DIM > OpInternalForcePiola
Definition seepage.cpp:65
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpGradTensorGrad< 1, SPACE_DIM, SPACE_DIM, 1 > OpKPiola
[Only used for dynamics]
Definition seepage.cpp:63
FTensor::Index< 'm', 3 > m
Add operators pushing bases from local to physical configuration.
Boundary condition manager for finite element problem setup.
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:118
Deprecated interface functions.
Definition of the displacement bc data structure.
Definition BCData.hpp:72
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:423
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.
Specialization for double precision scalar field values calculation.
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Specialization for double precision vector field values calculation.
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.
Operator for symmetrizing tensor fields.
Template struct for dimension-specific finite element types.
PipelineManager interface.
MoFEMErrorCode setDomainRhsIntegrationRule(RuleHookFun rule)
Set integration rule for domain right-hand side finite element.
Problem manager is used to build and partition problems.
Simple interface for fast problem set-up.
Definition Simple.hpp:27
MoFEMErrorCode addDomainField(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_ZERO, int verb=-1)
Add field on domain.
Definition Simple.cpp:261
MoFEMErrorCode getOptions()
get options
Definition Simple.cpp:180
intrusive_ptr for managing petsc objects
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
MoFEMErrorCode getCommandLineParameters()
[Run problem]
MoFEMErrorCode runProblem()
[Run problem]
boost::shared_ptr< MatrixDouble > dispFieldPtr
boost::shared_ptr< MatrixDouble > strainFieldPtr
ThermoElasticProblem(MoFEM::Interface &m_field)
std::array< double, 3 > fieldEvalCoords
boost::shared_ptr< VectorDouble > tempFieldPtr
boost::shared_ptr< MatrixDouble > fluxFieldPtr
MoFEMErrorCode opThermoElasticFactoryDomainRhs(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string field_name, boost::shared_ptr< HenckyOps::CommonData > elastic_common_ptr, boost::shared_ptr< ThermoElasticProblem::BlockedThermalParameters > thermal_common_ptr, boost::shared_ptr< ThermoElasticProblem::BlockedThermoElasticParameters > thermoelastic_common_ptr, Sev sev)
MoFEM::Interface & mField
MoFEMErrorCode setupProblem()
add fields
MoFEMErrorCode bC()
[Set up problem]
boost::shared_ptr< MatrixDouble > stressFieldPtr
MoFEMErrorCode OPs()
[Boundary condition]
MoFEMErrorCode tsSolve()
[Push operators to pipeline]
MoFEMErrorCode opThermoElasticFactoryDomainLhs(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string field_name, std::string coupled_field_name, std::string elastic_block_name, std::string thermal_block_name, std::string thermoelastic_block_name, Sev sev, double scale=1)
MoFEMErrorCode opThermoElasticFactoryDomainLhs(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string field_name, std::string coupled_field_name, boost::shared_ptr< HenckyOps::CommonData > elastic_common_ptr, boost::shared_ptr< ThermoElasticProblem::BlockedThermalParameters > thermal_common_ptr, boost::shared_ptr< ThermoElasticProblem::BlockedThermoElasticParameters > thermoelastic_common_ptr, Sev sev)
MoFEMErrorCode addMatThermalBlockOps(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, std::string block_name, boost::shared_ptr< BlockedThermalParameters > blockedParamsPtr, Sev sev)
MoFEMErrorCode addMatThermoElasticBlockOps(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, std::string block_name, boost::shared_ptr< BlockedThermoElasticParameters > blockedParamsPtr, Sev sev)
boost::shared_ptr< MatrixDouble > dispGradPtr
MoFEMErrorCode opThermoElasticFactoryDomainRhs(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string field_name, std::string elastic_block_name, std::string thermal_block_name, std::string thermoelastic_block_name, Sev sev, double scale=1)
boost::shared_ptr< FieldEvaluatorInterface::SetPtsData > fieldEvalData
double scale
Definition plastic.cpp:123
double H
Hardening.
Definition plastic.cpp:128
ElementsAndOps< SPACE_DIM >::SideEle SideEle
Definition plastic.cpp:61
#define FINITE_DEFORMATION_FLAG
constexpr AssemblyType AT
constexpr IntegrationType IT
static char help[]
[Solve]
int save_every
int order_flux
constexpr bool IS_LARGE_STRAINS
int atom_test
#define EXECUTABLE_DIMENSION
constexpr int SPACE_DIM
double default_ref_temp
double default_heat_capacity
int order_disp
double default_young_modulus
[Essential boundary conditions (Least square approach)]
PetscBool do_output_skin
double default_coeff_expansion
int order_temp
auto save_range
PetscBool do_output_domain
double default_heat_conductivity
double default_init_temp
double default_poisson_ratio
auto save_range
int save_every
int order_flux
constexpr bool IS_LARGE_STRAINS
int atom_test
constexpr int SPACE_DIM
double default_ref_temp
double default_heat_capacity
int order_disp
double default_young_modulus
[Essential boundary conditions (Least square approach)]
PetscBool do_output_skin
double default_coeff_expansion
int order_temp
PetscBool do_output_domain
double default_heat_conductivity
double default_init_temp
double default_poisson_ratio