855 {"HEATFLUX"});
856
859 };
864
865 auto block_thermal_params = boost::make_shared<BlockedThermalParameters>();
866 auto heat_conductivity_ptr = block_thermal_params->getHeatConductivityPtr();
867 auto heat_capacity_ptr = block_thermal_params->getHeatCapacityPtr();
868
869 auto block_thermoelastic_params =
870 boost::make_shared<BlockedThermoElasticParameters>();
871 auto coeff_expansion_ptr = block_thermoelastic_params->getCoeffExpansionPtr();
872 auto ref_temp_ptr = block_thermoelastic_params->getRefTempPtr();
873
874
875 auto time_scale =
876 boost::make_shared<TimeScale>("", false, [](const double) { return 1; });
877 auto def_time_scale = [time_scale](const double time) {
878 return (!time_scale->argFileScale) ? time : 1;
879 };
880 auto def_file_name = [time_scale](const std::string &&name) {
881 return (!time_scale->argFileScale) ? name : "";
882 };
883
884
885 auto time_bodyforce_scaling = boost::make_shared<TimeScale>(
886 def_file_name("bodyforce_scale.txt"), false, def_time_scale);
887 auto time_heatsource_scaling = boost::make_shared<TimeScale>(
888 def_file_name("heatsource_scale.txt"), false, def_time_scale);
889 auto time_temperature_scaling = boost::make_shared<TimeScale>(
890 def_file_name("temperature_bc_scale.txt"), false, def_time_scale);
891 auto time_displacement_scaling = boost::make_shared<TimeScale>(
892 def_file_name("displacement_bc_scale.txt"), false, def_time_scale);
893 auto time_flux_scaling = boost::make_shared<TimeScale>(
894 def_file_name("flux_bc_scale.txt"), false, def_time_scale);
895 auto time_force_scaling = boost::make_shared<TimeScale>(
896 def_file_name("force_bc_scale.txt"), false, def_time_scale);
897
898 auto add_domain_rhs_ops = [&](auto &pipeline) {
901 Sev::inform);
903 block_thermoelastic_params, Sev::inform);
905
906 auto hencky_common_data_ptr =
907 HenckyOps::commonDataFactory<SPACE_DIM, IT, DomainEleOp>(
908 mField, pipeline,
"U",
"MAT_ELASTIC", Sev::inform);
909 auto mat_D_ptr = hencky_common_data_ptr->matDPtr;
910 auto mat_grad_ptr = hencky_common_data_ptr->matGradPtr;
911 auto mat_strain_ptr = boost::make_shared<MatrixDouble>();
912 auto mat_stress_ptr = boost::make_shared<MatrixDouble>();
913
914 auto vec_temp_ptr = boost::make_shared<VectorDouble>();
915 auto vec_temp_dot_ptr = boost::make_shared<VectorDouble>();
916 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
917 auto vec_temp_div_ptr = boost::make_shared<VectorDouble>();
918
920 pipeline.push_back(
923 "FLUX", vec_temp_div_ptr));
924 pipeline.push_back(
926
927 CHKERR opThermoElasticFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
928 mField, pipeline,
"U",
"MAT_ELASTIC",
"MAT_THERMAL",
929 "MAT_THERMOELASTIC", Sev::inform);
930
931 auto resistance = [heat_conductivity_ptr](
const double,
const double,
933 return (1. / (*heat_conductivity_ptr));
934 };
935
936 auto capacity = [heat_capacity_ptr](
const double,
const double,
938 return -(*heat_capacity_ptr);
939 };
941 return -1.;
942 };
943 pipeline.push_back(
944 new OpHdivFlux(
"FLUX", mat_flux_ptr, resistance, mat_grad_ptr));
945 pipeline.push_back(
new OpHDivTemp(
"FLUX", vec_temp_ptr, unity));
946 pipeline.push_back(
new OpBaseDivFlux(
"T", vec_temp_div_ptr, unity));
947 pipeline.push_back(
new OpBaseDotT(
"T", vec_temp_dot_ptr, capacity));
948
949
951 pipeline,
mField,
"T", {time_scale, time_heatsource_scaling},
952 "HEAT_SOURCE", Sev::inform);
954 pipeline,
mField,
"U", {time_scale, time_bodyforce_scaling},
955 "BODY_FORCE", Sev::inform);
957 pipeline,
mField,
"T", vec_temp_ptr,
"SETTEMP", Sev::inform);
958
960 };
961
962 auto add_domain_lhs_ops = [&](auto &pipeline) {
965 Sev::verbose);
967 block_thermoelastic_params,
968 Sev::verbose);
970
971 auto hencky_common_data_ptr =
972 HenckyOps::commonDataFactory<SPACE_DIM, IT, DomainEleOp>(
973 mField, pipeline,
"U",
"MAT_ELASTIC", Sev::inform, 1);
974 auto mat_D_ptr = hencky_common_data_ptr->matDPtr;
975 auto mat_grad_ptr = hencky_common_data_ptr->matGradPtr;
976
977 auto resistance = [heat_conductivity_ptr](
const double,
const double,
979 return (1. / (*heat_conductivity_ptr));
980 };
981 auto capacity = [heat_capacity_ptr](
const double,
const double,
983 return -(*heat_capacity_ptr);
984 };
985 pipeline.push_back(
986 new OpHdivHdiv(
"FLUX",
"FLUX", resistance, mat_grad_ptr));
987 pipeline.push_back(
988 new OpHdivT(
"FLUX",
"T", []()
constexpr {
return -1; },
true));
989
990 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
991 pipeline.push_back(
993
994 pipeline.push_back(
995 new OpHdivU(
"FLUX",
"U", mat_flux_ptr, resistance, mat_grad_ptr));
996
997 CHKERR opThermoElasticFactoryDomainLhs<SPACE_DIM, AT, IT, DomainEleOp>(
998 mField, pipeline,
"U",
"T",
"MAT_ELASTIC",
"MAT_THERMAL",
999 "MAT_THERMOELASTIC", Sev::inform);
1000
1001 auto op_capacity =
new OpCapacity(
"T",
"T", capacity);
1002 op_capacity->feScalingFun = [](
const FEMethod *fe_ptr) {
1003 return fe_ptr->ts_a;
1004 };
1005 pipeline.push_back(op_capacity);
1006
1007 auto vec_temp_ptr = boost::make_shared<VectorDouble>();
1010 pipeline,
mField,
"T", vec_temp_ptr,
"SETTEMP", Sev::verbose);
1011
1013 };
1014
1015 auto add_boundary_rhs_ops = [&](auto &pipeline) {
1017
1019
1021 pipeline,
mField,
"U", {time_scale, time_force_scaling},
"FORCE",
1022 Sev::inform);
1023
1024
1025
1029 pipeline,
mField,
"FLUX", {time_scale, time_temperature_scaling},
1030 "TEMPERATURE", Sev::inform);
1031
1032
1033
1034
1035
1036
1037 using OpFluxBC =
1040 pipeline,
mField,
"TBC", {time_scale, time_flux_scaling},
"FLUX",
1041 Sev::inform);
1042
1044 using OpConvectionRhsBC =
1045 T::OpFlux<ThermoElasticOps::ConvectionBcType<BLOCKSET>, 1, 1>;
1046 using OpRadiationRhsBC =
1047 T::OpFlux<ThermoElasticOps::RadiationBcType<BLOCKSET>, 1, 1>;
1048 auto temp_bc_ptr = boost::make_shared<VectorDouble>();
1050 T::AddFluxToPipeline<OpConvectionRhsBC>::add(
1051 pipeline,
mField,
"TBC", temp_bc_ptr,
"CONVECTION", Sev::inform);
1052 T::AddFluxToPipeline<OpRadiationRhsBC>::add(
1053 pipeline,
mField,
"TBC", temp_bc_ptr,
"RADIATION", Sev::inform);
1054
1055 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
1056 pipeline.push_back(
1058
1059
1060
1061
1062
1063
1064 struct OpTBCTimesNormalFlux
1066
1068
1069 OpTBCTimesNormalFlux(
const std::string
field_name,
1070 boost::shared_ptr<MatrixDouble> vec,
1071 boost::shared_ptr<Range> ents_ptr = nullptr)
1073
1077
1078 auto t_w = OP::getFTensor0IntegrationWeight();
1079
1081
1082 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1083
1084 auto t_vec = getFTensor1FromMat<SPACE_DIM, 1>(*sourceVec);
1085
1086 for (int gg = 0; gg != OP::nbIntegrationPts; gg++) {
1087
1088 const double alpha = t_w * (t_vec(
i) * t_normal(
i));
1089
1090 int rr = 0;
1091 for (; rr != OP::nbRows; ++rr) {
1092 OP::locF[rr] += alpha * t_row_base;
1093 ++t_row_base;
1094 }
1095 for (; rr < OP::nbRowBaseFunctions; ++rr)
1096 ++t_row_base;
1097 ++t_w;
1098 ++t_vec;
1099 ++t_normal;
1100 }
1101 EntityType fe_type = OP::getNumeredEntFiniteElementPtr()->getEntType();
1102 if (fe_type == MBTRI) {
1103 OP::locF /= 2;
1104 }
1106 }
1107
1108 protected:
1109 boost::shared_ptr<MatrixDouble> sourceVec;
1110 };
1111 pipeline.push_back(new OpTBCTimesNormalFlux("TBC", mat_flux_ptr));
1112
1113 struct OpBaseNormalTimesTBC
1115
1117
1118 OpBaseNormalTimesTBC(
const std::string
field_name,
1119 boost::shared_ptr<VectorDouble> vec,
1120 boost::shared_ptr<Range> ents_ptr = nullptr)
1122
1126
1127 auto t_w = OP::getFTensor0IntegrationWeight();
1128
1130
1131 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1132
1134
1135 for (int gg = 0; gg != OP::nbIntegrationPts; gg++) {
1136
1137 const double alpha = t_w * t_vec;
1138
1139 int rr = 0;
1140 for (; rr != OP::nbRows; ++rr) {
1141 OP::locF[rr] += alpha * (t_row_base(
i) * t_normal(
i));
1142 ++t_row_base;
1143 }
1144 for (; rr < OP::nbRowBaseFunctions; ++rr)
1145 ++t_row_base;
1146 ++t_w;
1147 ++t_vec;
1148 ++t_normal;
1149 }
1150 EntityType fe_type = OP::getNumeredEntFiniteElementPtr()->getEntType();
1151 if (fe_type == MBTRI) {
1152 OP::locF /= 2;
1153 }
1155 }
1156
1157 protected:
1158 boost::shared_ptr<VectorDouble> sourceVec;
1159 };
1160
1161 pipeline.push_back(new OpBaseNormalTimesTBC("FLUX", temp_bc_ptr));
1162
1164 };
1165
1166 auto add_boundary_lhs_ops = [&](auto &pipeline) {
1168
1170
1171 using T =
1173 using OpConvectionLhsBC =
1174 T::OpFlux<ThermoElasticOps::ConvectionBcType<BLOCKSET>, 1, 1>;
1175 using OpRadiationLhsBC =
1176 T::OpFlux<ThermoElasticOps::RadiationBcType<BLOCKSET>, 1, 1>;
1177 auto temp_bc_ptr = boost::make_shared<VectorDouble>();
1179 T::AddFluxToPipeline<OpConvectionLhsBC>::add(pipeline,
mField,
"TBC",
"TBC",
1180 "CONVECTION", Sev::verbose);
1181 T::AddFluxToPipeline<OpRadiationLhsBC>::add(
1182 pipeline,
mField,
"TBC",
"TBC", temp_bc_ptr,
"RADIATION", Sev::verbose);
1183
1184
1185
1186
1187
1188
1189 struct OpTBCTimesNormalFlux
1191
1193
1194 OpTBCTimesNormalFlux(const std::string row_field_name,
1195 const std::string col_field_name,
1196 boost::shared_ptr<Range> ents_ptr = nullptr)
1197 :
OP(row_field_name, col_field_name,
OP::OPROWCOL, ents_ptr) {
1198 this->sYmm = false;
1199 this->assembleTranspose = true;
1200 this->onlyTranspose = false;
1201 }
1202
1206
1208
1209
1210 auto t_w = OP::getFTensor0IntegrationWeight();
1211
1213
1214 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1215
1216 for (int gg = 0; gg != OP::nbIntegrationPts; gg++) {
1217
1218 auto a_mat_ptr = &*OP::locMat.data().begin();
1219 int rr = 0;
1220 for (; rr != OP::nbRows; rr++) {
1221
1222 const double alpha = t_w * t_row_base;
1223
1225
1226 for (int cc = 0; cc != OP::nbCols; cc++) {
1227
1228
1229
1230 *a_mat_ptr += alpha * (t_col_base(
i) * t_normal(
i));
1231 ++t_col_base;
1232 ++a_mat_ptr;
1233 }
1234 ++t_row_base;
1235 }
1236 for (; rr < OP::nbRowBaseFunctions; ++rr)
1237 ++t_row_base;
1238 ++t_normal;
1239 ++t_w;
1240 }
1241 EntityType fe_type = OP::getNumeredEntFiniteElementPtr()->getEntType();
1242 if (fe_type == MBTRI) {
1243 OP::locMat /= 2;
1244 }
1246 }
1247 };
1248
1249 pipeline.push_back(new OpTBCTimesNormalFlux("TBC", "FLUX"));
1250
1252 };
1253
1254
1255 auto get_bc_hook_rhs = [&]() {
1257 mField, pipeline_mng->getDomainRhsFE(),
1258 {time_scale, time_displacement_scaling});
1259 return hook;
1260 };
1261 auto get_bc_hook_lhs = [&]() {
1263 mField, pipeline_mng->getDomainLhsFE(),
1264 {time_scale, time_displacement_scaling});
1265 return hook;
1266 };
1267
1268 pipeline_mng->getDomainRhsFE()->preProcessHook = get_bc_hook_rhs();
1269 pipeline_mng->getDomainLhsFE()->preProcessHook = get_bc_hook_lhs();
1270
1271 CHKERR add_domain_rhs_ops(pipeline_mng->getOpDomainRhsPipeline());
1272 CHKERR add_domain_lhs_ops(pipeline_mng->getOpDomainLhsPipeline());
1273 CHKERR add_boundary_rhs_ops(pipeline_mng->getOpBoundaryRhsPipeline());
1274 CHKERR add_boundary_lhs_ops(pipeline_mng->getOpBoundaryLhsPipeline());
1275
1277}
1278
1279
1280
#define FTENSOR_INDEX(DIM, I)
@ HDIV
field with continuous normal traction
FTensor::Index< 'i', SPACE_DIM > i
static auto getFTensor0FromVec(ublas::vector< T, A > &data)
Get tensor rank 0 (scalar) form data vector.
OpCalculateScalarFieldValuesFromPetscVecImpl< PetscData::CTX_SET_X_T > OpCalculateScalarFieldValuesDot
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
constexpr auto field_name
static constexpr int approx_order
OpBaseImpl< PETSC, EdgeEleOp > OpBase
Add operators pushing bases from local to physical configuration.
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.
Structure for user loop methods on finite elements.
Natural boundary conditions.
Get vector field for H-div approximation.
Calculate divergence of vector field.
Specialization for double precision scalar field values calculation.
MoFEMErrorCode addMatThermalBlockOps(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, std::string block_name, boost::shared_ptr< BlockedThermalParameters > blockedParamsPtr, Sev sev)