16 #include "libmesh/parallel_algebra.h" 25 "Computes the residual and Jacobian contributions for the 'Lagrange Multiplier' " 26 "implementation of the thermal contact problem. For more information, see the " 27 "detailed description here: http://tinyurl.com/gmmhbe9");
28 params.
addParam<std::vector<UserObjectName>>(
"gap_flux_models",
29 "List of GapFluxModel user objects");
30 params.
addCoupledVar(
"displacements",
"Displacement variables");
32 MooseEnum gap_geometry_type(
"AUTO PLATE CYLINDER SPHERE",
"AUTO");
36 "Gap calculation type. The geometry type is used to compute " 37 "gap distances and scale fluxes to ensure energy balance. If AUTO is selected, the gap " 38 "geometry is automatically set via the mesh coordinate system.");
41 "Start point for line defining cylindrical axis");
43 "End point for line defining cylindrical axis");
54 "gap_geometry_type max_gap cylinder_axis_point_1 cylinder_axis_point_2 sphere_origin",
62 _gap_flux_model_names(getParam<
std::vector<UserObjectName>>(
"gap_flux_models")),
63 _disp_name(parameters.getVecMooseType(
"displacements")),
64 _n_disp(_disp_name.size()),
65 _disp_secondary(_n_disp),
66 _disp_primary(_n_disp),
69 _surface_integration_factor(1.0),
70 _p1(declareRestartableData<Point>(
"cylinder_axis_point_1", Point(0, 1, 0))),
71 _p2(declareRestartableData<Point>(
"cylinder_axis_point_2", Point(0, 0, 0))),
74 _max_gap(getParam<
Real>(
"max_gap")),
75 _adjusted_length(0.0),
76 _disp_x_var(getVar(
"displacements", 0)),
77 _disp_y_var(getVar(
"displacements", 1)),
78 _disp_z_var(_n_disp == 3 ? getVar(
"displacements", 2) : nullptr)
80 if (
_n_disp && !getParam<bool>(
"use_displaced_mesh"))
82 "You are coupling displacement variables but are evaluating the gap width on the " 83 "undisplaced mesh. This is probably a mistake.");
85 for (
unsigned int i = 0; i <
_n_disp; ++i)
92 const auto use_displaced_mesh = getParam<bool>(
"use_displaced_mesh");
96 const auto & gap_model = getUserObjectByName<GapFluxModelBase>(
name);
107 const auto & var_dependencies = gap_model.getMooseVariableDependencies();
108 for (
const auto & var : var_dependencies)
112 const auto & mat_dependencies = gap_model.getMatPropDependencies();
116 if (gap_model.parameters().get<
bool>(
"use_displaced_mesh") != use_displaced_mesh)
118 "use_displaced_mesh",
119 "The gap flux model '",
121 "' should operate on the same mesh (displaced/undisplaced) as the constraint object");
136 for (
auto subdomain : subdomainIDs)
138 mooseError(
"ModularGapConductanceConstraint requires all subdomains to have the same " 139 "coordinate system.");
150 unsigned int axisymmetric_radial_coord,
170 "cylinder_axis_point_1",
171 "Either specify both `cylinder_axis_point_1` and `cylinder_axis_point_2` or neither.");
179 "'gap_geometry_type = PLATE' cannot be used with models having a spherical " 180 "coordinate system.");
194 "For 'gap_geometry_type = CYLINDER' to be used with a Cartesian model in 3D, " 195 "'cylinder_axis_point_1' and 'cylinder_axis_point_2' must be specified.");
200 "ModularGapConductanceConstraint '",
name(),
"' deduced cylinder axis as ",
_p1,
_p2);
208 "The 'cylinder_axis_point_1' and 'cylinder_axis_point_2' cannot be specified " 209 "with axisymmetric models. The y-axis is used as the cylindrical axis of " 212 if (axisymmetric_radial_coord == 0)
214 _p1 = Point(0, 0, 0);
215 _p2 = Point(0, 1, 0);
219 _p1 = Point(0, 0, 0);
220 _p2 = Point(1, 0, 0);
225 "'gap_geometry_type = CYLINDER' cannot be used with models having a spherical " 226 "coordinate system.");
238 "ModularGapConductanceConstraint '",
name(),
"' deduced sphere origin as ",
_p1);
242 "For 'gap_geometry_type = SPHERE' to be used with an axisymmetric " 243 "model, 'sphere_origin' must be specified.");
249 "The 'sphere_origin' cannot be specified with spherical models. x=0 is used " 250 "as the spherical origin.");
251 _p1 = Point(0, 0, 0);
260 ADReal surface_integration_factor = 1.0;
267 return surface_integration_factor;
277 return std::min(denominator,
_max_gap);
282 return std::min(denominator,
_max_gap);
297 const Point p2p1(
_p2 -
_p1);
298 const Point p1pc(
_p1 - current_point);
299 const Real t = -(p1pc * p2p1) / p2p1.norm_sq();
302 const Point p(
_p1 + t * p2p1);
303 Point rad_vec(current_point - p);
304 Real rad = rad_vec.norm();
308 if (rad_dot_norm > 0)
311 _r2 = rad + gap_length;
314 else if (rad_dot_norm < 0)
316 _r1 = rad - gap_length;
321 mooseError(
"Issue with cylindrical flux calculation normals.\n");
325 const Point origin_to_curr_point(current_point -
_p1);
327 const Real curr_point_radius = origin_to_curr_point.norm();
330 _r1 = curr_point_radius;
331 _r2 = curr_point_radius + gap_length;
334 else if (normal_dot < 0)
336 _r1 = curr_point_radius - gap_length;
337 _r2 = curr_point_radius;
341 mooseError(
"Issue with spherical flux calculation normals. \n");
375 const auto & secondary_ip_lowerd_map =
379 std::array<ADReal, 3> primary_disp;
380 std::array<ADReal, 3> secondary_disp;
382 for (
unsigned int i = 0; i <
_n_disp; ++i)
392 for (
unsigned int i = 0; i <
_n_disp; ++i)
394 ad_phys_points_primary(i).derivatives() = primary_disp[i].derivatives();
395 ad_phys_points_secondary(i).derivatives() = secondary_disp[i].derivatives();
414 flux +=
model->computeFluxInternal(*
this);
435 std::unique_ptr<const Elem> side_ptr;
436 for (
auto [elem_id, side,
id] : bnd)
440 if (elem->processor_id() != my_pid)
444 elem->side_ptr(side_ptr, side);
447 const auto side_area = side_ptr->volume();
450 const auto side_position = side_ptr->true_centroid();
453 position += side_position * side_area;
466 "Unable to decuce cylinder axis automatically, please specify " 467 "'cylinder_axis_point_1' and 'cylinder_axis_point_2'.");
470 "Unable to decuce sphere origin automatically, please specify " 476 _p1 = position / area;
477 _p2 =
_p1 + Point(0, 0, 1);
const std::vector< Point > & _q_point
std::vector< const ADVariableValue * > _disp_primary
const VariableTestValue & _test_secondary
static InputParameters validParams()
const MooseVariable *const _disp_y_var
y-displacement variable
virtual Elem * elemPtr(const dof_id_type i)
std::vector< std::tuple< dof_id_type, unsigned short int, boundary_id_type > > buildActiveSideList() const
std::map< unsigned int, unsigned int > getPrimaryIpToLowerElementMap(const Elem &primary_elem, const Elem &primary_elem_ip, const Elem &lower_secondary_elem) const
const unsigned int _n_disp
void deduceGeometryParameters()
Automatically set up axis/center for 2D cartesian problems with cylindrical/spherical gap geometry...
ADReal _r1
Radii for quadrature points.
void mooseInfoRepeated(Args &&... args)
virtual ADReal computeQpResidual(Moose::MortarType mortar_type) override
Computes the residual for the LM equation, lambda = (k/l)*(T^(1) - PT^(2)).
const MooseArray< Point > & _phys_points_primary
Elem const *const & _lower_primary_elem
const Parallel::Communicator & _communicator
DualNumber< Real, DNDerivativeType, true > ADReal
const ADVariableValue & _lambda
registerMooseObject("HeatTransferApp", ModularGapConductanceConstraint)
virtual const std::string & name() const
const VariableTestValue & _test
Elem const *const & _lower_secondary_elem
ModularGapConductanceConstraint(const InputParameters ¶meters)
const AutomaticMortarGeneration & amg() const
static void trimInteriorNodeDerivatives(const std::map< unsigned int, unsigned int > &primary_ip_lowerd_map, const Variables &moose_var, DualNumbers &ad_vars, const bool is_secondary)
virtual unsigned int dimension() const
std::vector< const ADVariableValue * > _disp_secondary
std::vector< Point > _normals
GapGeometry
Gap geometry (user input or internally overwritten)
const std::vector< std::string > _disp_name
Displacement variables.
void computeGapRadii(const ADReal &gap_length)
Computes radii as a function of point and geometry.
std::vector< const GapFluxModelBase * > _gap_flux_models
Gap flux models.
virtual MooseVariable & getStandardVariable(const THREAD_ID tid, const std::string &var_name)=0
std::map< unsigned int, unsigned int > getSecondaryIpToLowerElementMap(const Elem &lower_secondary_elem) const
const MooseVariable *const _disp_x_var
x-displacement variable
void paramError(const std::string ¶m, Args... args) const
const MooseArray< Point > & _phys_points_secondary
const FEProblemBase & feProblem() const
const PertinentGeochemicalSystem model(database, {"H2O", "H+", "HCO3-", "O2(aq)", "Ca++", ">(s)FeOH", "radius_neg1", "radius_neg1.5"}, {"Calcite"}, {}, {"Calcite_asdf"}, {"CH4(aq)"}, {">(s)FeOCa+"}, "O2(aq)", "e-")
const BoundaryID _primary_id
virtual ADReal computeGapLength() const
void addMooseVariableDependency(MooseVariableFieldBase *var)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::vector< UserObjectName > _gap_flux_model_names
Gap flux model names.
virtual void setGapGeometryParameters(const InputParameters ¶ms, const Moose::CoordinateSystemType coord_sys, unsigned int axisymmetric_radial_coord, GapGeometry &gap_geometry_type)
void mooseError(Args &&... args) const
const InputParameters & _pars
Point & _p1
Points for geometric definitions.
enum ModularGapConductanceConstraint::GapGeometry _gap_geometry_type
This Constraint implements thermal contact using a "gap conductance" model in which the flux is repre...
static InputParameters validParams()
virtual void initialSetup() override
Moose::CoordinateSystemType getCoordSystem(SubdomainID sid) const
const MooseVariable *const _disp_z_var
z-displacement variable
virtual ADReal computeSurfaceIntegrationFactor() const
void paramWarning(const std::string ¶m, Args... args) const
ADReal _surface_integration_factor
Factor to preserve energy balance (due to mismatch in primary/secondary differential surface sizes) ...
processor_id_type processor_id() const
const VariableTestValue & _test_primary
std::unordered_set< unsigned int > _material_property_dependencies
const std::set< SubdomainID > & meshSubdomains() const
ADReal _gap_width
Gap width to pass into flux models.