17 #include "libmesh/parallel_algebra.h" 26 "Computes the residual and Jacobian contributions for the 'Lagrange Multiplier' " 27 "implementation of the thermal contact problem. For more information, see the " 28 "detailed description here: http://tinyurl.com/gmmhbe9");
29 params.
addParam<std::vector<UserObjectName>>(
"gap_flux_models",
30 "List of GapFluxModel user objects");
31 params.
addCoupledVar(
"displacements",
"Displacement variables");
33 MooseEnum gap_geometry_type(
"AUTO PLATE CYLINDER SPHERE",
"AUTO");
37 "Gap calculation type. The geometry type is used to compute " 38 "gap distances and scale fluxes to ensure energy balance. If AUTO is selected, the gap " 39 "geometry is automatically set via the mesh coordinate system.");
42 "Start point for line defining cylindrical axis");
44 "End point for line defining cylindrical axis");
55 "gap_geometry_type max_gap cylinder_axis_point_1 cylinder_axis_point_2 sphere_origin",
63 _gap_flux_model_names(getParam<
std::vector<UserObjectName>>(
"gap_flux_models")),
64 _disp_name(parameters.getVecMooseType(
"displacements")),
65 _n_disp(_disp_name.size()),
66 _disp_secondary(_n_disp),
67 _disp_primary(_n_disp),
70 _surface_integration_factor(1.0),
71 _p1(declareRestartableData<Point>(
"cylinder_axis_point_1", Point(0, 1, 0))),
72 _p2(declareRestartableData<Point>(
"cylinder_axis_point_2", Point(0, 0, 0))),
75 _max_gap(getParam<
Real>(
"max_gap")),
76 _adjusted_length(0.0),
77 _disp_x_var(getVar(
"displacements", 0)),
78 _disp_y_var(getVar(
"displacements", 1)),
79 _disp_z_var(_n_disp == 3 ? getVar(
"displacements", 2) : nullptr)
81 if (
_n_disp && !getParam<bool>(
"use_displaced_mesh"))
83 "You are coupling displacement variables but are evaluating the gap width on the " 84 "undisplaced mesh. This is probably a mistake.");
86 for (
unsigned int i = 0; i <
_n_disp; ++i)
93 const auto use_displaced_mesh = getParam<bool>(
"use_displaced_mesh");
97 const auto & gap_model = getUserObjectByName<GapFluxModelBase>(
name);
108 const auto & var_dependencies = gap_model.getMooseVariableDependencies();
109 for (
const auto & var : var_dependencies)
113 const auto & mat_dependencies = gap_model.getMatPropDependencies();
117 if (gap_model.parameters().get<
bool>(
"use_displaced_mesh") != use_displaced_mesh)
119 "use_displaced_mesh",
120 "The gap flux model '",
122 "' should operate on the same mesh (displaced/undisplaced) as the constraint object");
137 for (
auto subdomain : subdomainIDs)
139 mooseError(
"ModularGapConductanceConstraint requires all subdomains to have the same " 140 "coordinate system.");
151 unsigned int axisymmetric_radial_coord,
171 "cylinder_axis_point_1",
172 "Either specify both `cylinder_axis_point_1` and `cylinder_axis_point_2` or neither.");
180 "'gap_geometry_type = PLATE' cannot be used with models having a spherical " 181 "coordinate system.");
195 "For 'gap_geometry_type = CYLINDER' to be used with a Cartesian model in 3D, " 196 "'cylinder_axis_point_1' and 'cylinder_axis_point_2' must be specified.");
201 "ModularGapConductanceConstraint '",
name(),
"' deduced cylinder axis as ",
_p1,
_p2);
209 "The 'cylinder_axis_point_1' and 'cylinder_axis_point_2' cannot be specified " 210 "with axisymmetric models. The y-axis is used as the cylindrical axis of " 213 if (axisymmetric_radial_coord == 0)
215 _p1 = Point(0, 0, 0);
216 _p2 = Point(0, 1, 0);
220 _p1 = Point(0, 0, 0);
221 _p2 = Point(1, 0, 0);
226 "'gap_geometry_type = CYLINDER' cannot be used with models having a spherical " 227 "coordinate system.");
239 "ModularGapConductanceConstraint '",
name(),
"' deduced sphere origin as ",
_p1);
243 "For 'gap_geometry_type = SPHERE' to be used with an axisymmetric " 244 "model, 'sphere_origin' must be specified.");
250 "The 'sphere_origin' cannot be specified with spherical models. x=0 is used " 251 "as the spherical origin.");
252 _p1 = Point(0, 0, 0);
261 ADReal surface_integration_factor = 1.0;
268 return surface_integration_factor;
274 using std::log, std::min;
299 const Point p2p1(
_p2 -
_p1);
300 const Point p1pc(
_p1 - current_point);
301 const Real t = -(p1pc * p2p1) / p2p1.norm_sq();
304 const Point p(
_p1 + t * p2p1);
305 Point rad_vec(current_point - p);
306 Real rad = rad_vec.norm();
310 if (rad_dot_norm > 0)
313 _r2 = rad + gap_length;
316 else if (rad_dot_norm < 0)
318 _r1 = rad - gap_length;
323 mooseError(
"Issue with cylindrical flux calculation normals.\n");
327 const Point origin_to_curr_point(current_point -
_p1);
329 const Real curr_point_radius = origin_to_curr_point.norm();
332 _r1 = curr_point_radius;
333 _r2 = curr_point_radius + gap_length;
336 else if (normal_dot < 0)
338 _r1 = curr_point_radius - gap_length;
339 _r2 = curr_point_radius;
343 mooseError(
"Issue with spherical flux calculation normals. \n");
377 const auto & secondary_ip_lowerd_map =
381 std::array<ADReal, 3> primary_disp;
382 std::array<ADReal, 3> secondary_disp;
384 for (
unsigned int i = 0; i <
_n_disp; ++i)
394 for (
unsigned int i = 0; i <
_n_disp; ++i)
396 ad_phys_points_primary(i).derivatives() = primary_disp[i].derivatives();
397 ad_phys_points_secondary(i).derivatives() = secondary_disp[i].derivatives();
416 flux +=
model->computeFluxInternal(*
this);
437 std::unique_ptr<const Elem> side_ptr;
438 for (
auto [elem_id, side,
id] : bnd)
442 if (elem->processor_id() != my_pid)
446 elem->side_ptr(side_ptr, side);
449 const auto side_area = side_ptr->volume();
452 const auto side_position = side_ptr->true_centroid();
455 position += side_position * side_area;
468 "Unable to decuce cylinder axis automatically, please specify " 469 "'cylinder_axis_point_1' and 'cylinder_axis_point_2'.");
472 "Unable to decuce sphere origin automatically, please specify " 478 _p1 = position / area;
479 _p2 =
_p1 + Point(0, 0, 1);
const std::vector< Point > & _q_point
std::vector< const ADVariableValue * > _disp_primary
const VariableTestValue & _test_secondary
const InputParameters & _pars
static InputParameters validParams()
const MooseVariable *const _disp_y_var
y-displacement variable
void paramError(const std::string ¶m, Args... args) const
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)
const VariableTestValue & _test
Elem const *const & _lower_secondary_elem
const std::string & name() const
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
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
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
auto min(const L &left, const R &right)
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.