https://mooseframework.inl.gov
WCNSLinearFVTwoPhaseMixturePhysics.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
14 #include "WCNSFVFlowPhysics.h"
15 
18 registerMooseAction("NavierStokesApp",
20  "add_interpolation_method_physics");
21 registerMooseAction("NavierStokesApp", WCNSLinearFVTwoPhaseMixturePhysics, "add_material");
22 registerMooseAction("NavierStokesApp", WCNSLinearFVTwoPhaseMixturePhysics, "check_integrity");
23 
26 {
27  // The parameters are mostly the same being the linear and nonlinear version
30  // The flow physics is obtained from the scalar transport base class
31  // The fluid heat transfer physics is retrieved even if unspecified
32  params.addParam<PhysicsName>(
33  "fluid_heat_transfer_physics",
34  "NavierStokesFV",
35  "WCNSLinearFVFluidHeatTransferPhysics generating the fluid energy equation");
37  params.addParamNamesToGroup("fluid_heat_transfer_physics", "Phase change");
38  params.addClassDescription("Define the additional terms for a mixture model for the two phase "
39  "weakly-compressible Navier Stokes equations using the linearized "
40  "segregated finite volume discretization");
41 
42  // This is added to match a nonlinear test result. If the underlying issue is fixed, remove it
43  params.addParam<bool>("add_gravity_term_in_slip_velocity",
44  true,
45  "Whether to add the gravity term in the slip velocity vector computation");
46  return params;
47 }
48 
50  const InputParameters & parameters)
52  _add_phase_equation(_has_scalar_equation),
53  _phase_1_fraction_name(getParam<MooseFunctorName>("phase_1_fraction_name")),
54  _phase_2_fraction_name(_passive_scalar_names[0]),
55  _phase_1_density(getParam<MooseFunctorName>("phase_1_density_name")),
56  _phase_1_viscosity(getParam<MooseFunctorName>("phase_1_viscosity_name")),
57  _phase_1_specific_heat(getParam<MooseFunctorName>("phase_1_specific_heat_name")),
58  _phase_1_thermal_conductivity(getParam<MooseFunctorName>("phase_1_thermal_conductivity_name")),
59  _phase_2_density(getParam<MooseFunctorName>("phase_2_density_name")),
60  _phase_2_viscosity(getParam<MooseFunctorName>("phase_2_viscosity_name")),
61  _phase_2_specific_heat(getParam<MooseFunctorName>("phase_2_specific_heat_name")),
62  _phase_2_thermal_conductivity(getParam<MooseFunctorName>("phase_2_thermal_conductivity_name")),
63  _use_external_mixture_properties(getParam<bool>("use_external_mixture_properties")),
64  _use_drift_flux(getParam<bool>("add_drift_flux_momentum_terms")),
65  _use_advection_slip(getParam<bool>("add_advection_slip_term"))
66 {
67  // Check that only one scalar was passed, as we are using vector parameters
68  if (_passive_scalar_names.size() > 1)
69  paramError("phase_fraction_name", "Only one phase fraction currently supported.");
70  if (_passive_scalar_inlet_functors.size() > 1)
71  paramError("phase_fraction_inlet_functors", "Only one phase fraction currently supported");
72 
73  // Retrieve the fluid energy equation if it exists
74  if (isParamValid("fluid_heat_transfer_physics"))
75  {
76  _fluid_energy_physics = getCoupledPhysics<WCNSLinearFVFluidHeatTransferPhysics>(
77  getParam<PhysicsName>("fluid_heat_transfer_physics"), true);
78  // Check for a missing parameter / do not support isolated physics for now
79  if (!_fluid_energy_physics &&
80  !getCoupledPhysics<const WCNSLinearFVFluidHeatTransferPhysics>(true).empty())
81  paramError(
82  "fluid_heat_transfer_physics",
83  "We currently do not support creating both a phase transport equation and fluid heat "
84  "transfer physics that are not coupled together");
86  _has_energy_equation = true;
87  else
88  _has_energy_equation = false;
89  }
90  else
91  {
92  _has_energy_equation = false;
93  _fluid_energy_physics = nullptr;
94  }
95 
96  // Check that the mixture parameters are correctly in use in the other physics
98  {
99  if (_fluid_energy_physics->densityName() != "rho_mixture")
100  mooseError(
101  "Density name for Physics '", _fluid_energy_physics->name(), "' should be 'rho_mixture'");
102  if (_fluid_energy_physics->getSpecificHeatName() != "cp_mixture")
103  mooseError("Specific heat name for Physics '",
105  "' should be 'cp_mixture'");
106  }
108  if (_flow_equations_physics->densityName() != "rho_mixture")
109  mooseError("Density name for Physics ,",
111  "' should be 'rho_mixture'");
112 
113  if (_verbose)
114  {
116  mooseInfoRepeated("Coupled to fluid flow physics " + _flow_equations_physics->name());
118  mooseInfoRepeated("Coupled to fluid heat transfer physics " + _fluid_energy_physics->name());
119  }
120 
121  // Parameter checking
122  // The two models are not consistent
123  if (isParamSetByUser("alpha_exchange") && getParam<bool>("add_phase_change_energy_term"))
124  paramError("alpha_exchange",
125  "A phase exchange coefficient cannot be specified if the phase change is handled "
126  "with a phase change heat loss model");
128  paramError("phase_1_fraction_name",
129  "First phase fraction name should be different from second phase fraction name");
131  paramError("add_drift_flux_momentum_terms",
132  "Drift flux model cannot be used at the same time as the advection slip model");
133  if (!getParam<bool>("add_drift_flux_momentum_terms"))
134  errorDependentParameter("add_drift_flux_momentum_terms", "true", {"density_interp_method"});
135  if (!getParam<bool>("use_dispersed_phase_drag_model"))
136  errorDependentParameter("use_dispersed_phase_drag_model", "true", {"particle_diameter"});
137 }
138 
139 void
141 {
143  mooseError("Expected a flow physics");
144 
145  // Check the mesh for unsupported sknewness + buoyancy
147  {
148  const auto tol = 1e-2;
149  if (_problem->mesh().allFaceInfo().empty())
150  _problem->mesh().setupFiniteVolumeMeshData();
151  for (const auto & fi : _problem->mesh().allFaceInfo())
152  {
153  if (fi.skewnessCorrectionVector().norm() > tol * fi.dCNMag())
154  mooseError("Face with centroid ",
155  fi.faceCentroid(),
156  " requires skewness correction. We currently do not support mixture flow with "
157  "buoyancy and mesh skewness. Please contact a MOOSE or Navier Stokes module "
158  "developer if you require this.");
159  }
160  }
161 }
162 
163 void
165 {
167 
168  if (_add_phase_equation && isParamSetByUser("alpha_exchange"))
170 
172  getParam<bool>("add_phase_change_energy_term"))
174 
179 }
180 
181 void
183 {
184  params.set<MooseFunctorName>("u_slip") = "vel_slip_x";
185  if (dimension() >= 2)
186  params.set<MooseFunctorName>("v_slip") = "vel_slip_y";
187  if (dimension() >= 3)
188  params.set<MooseFunctorName>("w_slip") = "vel_slip_z";
189 }
190 
191 void
193 {
194  // Recreate the phase interface term from existing kernels
195  {
196  auto params = getFactory().getValidParams("LinearFVReaction");
197  assignBlocks(params, _blocks);
198  params.set<LinearVariableName>("variable") = _phase_2_fraction_name;
199  params.set<MooseFunctorName>("coeff") = getParam<MooseFunctorName>(NS::alpha_exchange);
201  "LinearFVReaction", prefix() + "phase_interface_reaction", params);
202  }
203  {
204  auto params = getFactory().getValidParams("LinearFVSource");
205  assignBlocks(params, _blocks);
206  params.set<LinearVariableName>("variable") = _phase_2_fraction_name;
207  params.set<MooseFunctorName>("source_density") = _phase_1_fraction_name;
208  params.set<MooseFunctorName>("scaling_factor") = getParam<MooseFunctorName>(NS::alpha_exchange);
209  getProblem().addLinearFVKernel("LinearFVSource", prefix() + "phase_interface_source", params);
210  }
211 }
212 
213 void
215 {
216  mooseError("Phase change energy source not implemented at this time for linear finite volume");
217 }
218 
219 void
221 {
222  const std::vector<std::string> components = {"x", "y", "z"};
223  for (const auto dim : make_range(dimension()))
224  {
225  const auto object_type = "LinearWCNSFV2PMomentumDriftFlux";
226  auto params = getFactory().getValidParams(object_type);
227  assignBlocks(params, _blocks);
228  params.set<LinearVariableName>("variable") = _flow_equations_physics->getVelocityNames()[dim];
229  setSlipVelocityParams(params);
230  params.set<MooseFunctorName>("rho_d") = _phase_2_density;
231  params.set<MooseFunctorName>("fraction_dispersed") = _phase_2_fraction_name;
232  params.set<MooseEnum>("momentum_component") = components[dim];
233  params.set<MooseEnum>("density_interp_method") = getParam<MooseEnum>("density_interp_method");
234  params.set<UserObjectName>("rhie_chow_user_object") = _flow_equations_physics->rhieChowUOName();
235  getProblem().addLinearFVKernel(object_type, prefix() + "drift_flux_" + components[dim], params);
236  }
237 }
238 
239 void
241 {
242  mooseError("Phase advection slip not implemented at this time for linear finite volume");
243 }
244 
245 void
247 {
248  // Add the phase fraction variable, for output purposes mostly
249  if (!getProblem().hasFunctor(_phase_1_fraction_name, /*thread_id=*/0))
250  {
251  auto params = getFactory().getValidParams("ParsedFunctorMaterial");
252  assignBlocks(params, _blocks);
253  params.set<std::string>("expression") = "1 - " + _phase_2_fraction_name;
254  params.set<std::vector<std::string>>("functor_names") = {_phase_2_fraction_name};
255  params.set<std::string>("property_name") = _phase_1_fraction_name;
256  params.set<std::vector<std::string>>("output_properties") = {_phase_1_fraction_name};
257  params.set<std::vector<OutputName>>("outputs") = {"all"};
258  getProblem().addMaterial("ParsedFunctorMaterial", prefix() + "phase_1_fraction", params);
259 
260  // One of the phase fraction should exist though (either as a variable or set by a
261  // NSLiquidFractionAux)
262  if (!getProblem().hasFunctor(_phase_2_fraction_name, /*thread_id=*/0))
263  paramError("Phase 2 fraction should be defined as a variable or auxiliary variable");
264  }
265  if (!getProblem().hasFunctor(_phase_2_fraction_name, /*thread_id=*/0))
266  {
267  auto params = getFactory().getValidParams("ParsedFunctorMaterial");
268  assignBlocks(params, _blocks);
269  params.set<std::string>("expression") = "1 - " + _phase_1_fraction_name;
270  params.set<std::vector<std::string>>("functor_names") = {_phase_1_fraction_name};
271  params.set<std::string>("property_name") = _phase_2_fraction_name;
272  params.set<std::vector<std::string>>("output_properties") = {_phase_2_fraction_name};
273  params.set<std::vector<OutputName>>("outputs") = {"all"};
274  getProblem().addMaterial("ParsedFunctorMaterial", prefix() + "phase_2_fraction", params);
275  }
276 
277  // Compute mixture properties
279  {
280  auto params = getFactory().getValidParams("WCNSLinearFVMixtureFunctorMaterial");
281  assignBlocks(params, _blocks);
282  params.set<std::vector<MooseFunctorName>>("prop_names") = {
283  "rho_mixture", "mu_mixture", "cp_mixture", "k_mixture"};
284  // The phase_1 and phase_2 assignments are only local to this object.
285  // We use the phase 2 variable to save a functor evaluation as we expect
286  // the phase 2 variable to be a nonlinear variable in the phase transport equation
287  params.set<std::vector<MooseFunctorName>>("phase_2_names") = {_phase_1_density,
291  params.set<std::vector<MooseFunctorName>>("phase_1_names") = {_phase_2_density,
295  params.set<MooseFunctorName>("phase_1_fraction") = _phase_2_fraction_name;
296  if (getParam<bool>("output_all_properties"))
297  params.set<std::vector<OutputName>>("outputs") = {"all"};
298  params.set<bool>("limit_phase_fraction") = true;
300  "WCNSLinearFVMixtureFunctorMaterial", prefix() + "mixture_material", params);
301  }
302 
303  // Compute slip terms as functors, used by the drift flux kernels
305  {
306  mooseAssert(_flow_equations_physics, "We must have coupled to this");
307  const std::vector<std::string> vel_components = {"u", "v", "w"};
308  const std::vector<std::string> components = {"x", "y", "z"};
309  for (const auto dim : make_range(dimension()))
310  {
311  auto params = getFactory().getValidParams("WCNSFV2PSlipVelocityFunctorMaterial");
312  assignBlocks(params, _blocks);
313  params.set<MooseFunctorName>("slip_velocity_name") = "vel_slip_" + components[dim];
314  params.set<MooseEnum>("momentum_component") = components[dim];
315  for (const auto j : make_range(dimension()))
316  params.set<std::vector<VariableName>>(vel_components[j]) = {
318  params.set<MooseFunctorName>(NS::density) = _phase_1_density;
319  params.set<MooseFunctorName>(NS::mu) = "mu_mixture";
320  params.set<MooseFunctorName>("rho_d") = _phase_2_density;
321  if (getParam<bool>("add_gravity_term_in_slip_velocity"))
322  params.set<RealVectorValue>("gravity") = _flow_equations_physics->gravityVector();
323  if (isParamValid("slip_linear_friction_name"))
324  params.set<MooseFunctorName>("linear_coef_name") =
325  getParam<MooseFunctorName>("slip_linear_friction_name");
326  else if (getParam<bool>("use_dispersed_phase_drag_model"))
327  params.set<MooseFunctorName>("linear_coef_name") = "Darcy_coefficient";
328  else if (_flow_equations_physics)
329  {
331  params.set<MooseFunctorName>("linear_coef_name") =
333  else
334  params.set<MooseFunctorName>("linear_coef_name") = "0";
335  }
336  else
337  paramError("slip_linear_friction_name",
338  "WCNSFV2PSlipVelocityFunctorMaterial created by this Physics required a scalar "
339  "field linear friction factor.");
340  params.set<MooseFunctorName>("particle_diameter") =
341  getParam<MooseFunctorName>("particle_diameter");
342  if (getParam<bool>("output_all_properties"))
343  {
344  if (!isTransient())
345  params.set<std::vector<OutputName>>("outputs") = {"all"};
346  else
347  paramInfo("output_all_properties",
348  "Slip velocity functor material output currently unsupported in Physics "
349  "in transient conditions.");
350  }
352  "WCNSFV2PSlipVelocityFunctorMaterial", prefix() + "slip_" + components[dim], params);
353  }
354  }
355 
356  // Add a default drag model for a dispersed phase
357  if (getParam<bool>("use_dispersed_phase_drag_model"))
358  {
359  const std::vector<std::string> vel_components = {"u", "v", "w"};
360 
361  auto params = getFactory().getValidParams("NSFVDispersePhaseDragFunctorMaterial");
362  assignBlocks(params, _blocks);
363  params.set<MooseFunctorName>("drag_coef_name") = "Darcy_coefficient";
364  for (const auto j : make_range(dimension()))
365  params.set<MooseFunctorName>(vel_components[j]) = {
367  params.set<MooseFunctorName>(NS::density) = "rho_mixture";
368  params.set<MooseFunctorName>(NS::mu) = "mu_mixture";
369  params.set<MooseFunctorName>("particle_diameter") =
370  getParam<MooseFunctorName>("particle_diameter");
371  if (getParam<bool>("output_all_properties"))
372  params.set<std::vector<OutputName>>("outputs") = {"all"};
374  "NSFVDispersePhaseDragFunctorMaterial", prefix() + "dispersed_drag", params);
375  }
376 }
std::string prefix() const
bool hasFlowEquations() const
Whether the physics is actually creating the flow equations.
const std::vector< std::string > & getVelocityNames() const
To interface with other Physics.
void assignBlocks(InputParameters &params, const std::vector< SubdomainName > &blocks) const
Factory & getFactory()
auto norm() const
void paramError(const std::string &param, Args... args) const
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const double tol
unsigned int dim
const bool _use_advection_slip
Whether to add the advection slip term to each component of the momentum equation.
virtual void addMaterial(const std::string &material_name, const std::string &name, InputParameters &parameters)
const MooseFunctorName _phase_1_thermal_conductivity
Name of the thermal conductivity of the first phase.
T & set(const std::string &name, bool quiet_mode=false)
const MooseFunctorName _phase_1_specific_heat
Name of the specific heat of the first phase.
static const std::string density
Definition: NS.h:34
InputParameters getValidParams(const std::string &name) const
void mooseInfoRepeated(Args &&... args)
const bool _add_phase_equation
Convenience boolean to keep track of whether the phase transport equation is requested.
Creates all the objects needed to solve the Navier Stokes scalar transport equations using the linear...
std::vector< NonlinearVariableName > _passive_scalar_names
Names of the passive scalar variables.
virtual MooseFunctorName getLinearFrictionCoefName() const =0
Get the name of the linear friction coefficient. Returns an empty string if no friction.
const bool _verbose
std::vector< SubdomainName > _blocks
unsigned int dimension() const
registerWCNSFVScalarTransportBaseTasks("NavierStokesApp", WCNSLinearFVTwoPhaseMixturePhysics)
const MooseFunctorName & densityName() const
Return the name of the density functor.
const MooseFunctorName _phase_2_thermal_conductivity
Name of the thermal conductivity of the other phase.
const MooseFunctorName _phase_1_fraction_name
Name of the first phase fraction (usually, liquid)
bool _has_energy_equation
Convenience boolean to keep track of whether the fluid energy equation is present.
void errorDependentParameter(const std::string &param1, const std::string &value_not_set, const std::vector< std::string > &dependent_params) const
std::vector< std::vector< MooseFunctorName > > _passive_scalar_inlet_functors
Functors describing the inlet boundary values. See passive_scalar_inlet_types for what the functors a...
const MooseFunctorName _phase_1_density
Name of the density of the first phase.
virtual FEProblemBase & getProblem()
WCNSLinearFVTwoPhaseMixturePhysics(const InputParameters &parameters)
const MooseFunctorName _phase_2_fraction_name
Name of the second phase fraction (usually, dispersed or advected by the liquid)
const std::string & name() const
void addPhaseInterfaceTerm()
Functions adding kernels for the other physics.
const MooseFunctorName & getSpecificHeatName() const
Get the name of the specific heat material property.
RealVectorValue gravityVector() const
Return the gravity vector.
bool hasEnergyEquation() const
Whether the physics is actually creating the heat equation.
static const std::string mu
Definition: NS.h:127
static InputParameters commonMixtureParams()
const bool _use_drift_flux
Whether to add the drift flux momentum terms to each component momentum equation. ...
const MooseFunctorName _phase_2_viscosity
Name of the dynamic viscosity of the other phase.
static const std::string alpha_exchange
Definition: NS.h:154
const MooseFunctorName _phase_1_viscosity
Name of the dynamic viscosity of the first phase.
const WCNSLinearFVFluidHeatTransferPhysics * _fluid_energy_physics
Fluid heat transfer physics.
virtual void addLinearFVKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
static void renamePassiveScalarToMixtureParams(InputParameters &params)
const bool _use_external_mixture_properties
Whether to define the mixture model internally or use fluid properties instead.
Creates all the objects needed to solve the mixture model for the weakly-compressible and incompressi...
const MooseFunctorName _phase_2_specific_heat
Name of the specific heat of the other phase.
const UserObjectName & rhieChowUOName() const
Return the name of the Rhie Chow user object.
IntRange< T > make_range(T beg, T end)
registerNavierStokesPhysicsBaseTasks("NavierStokesApp", WCNSLinearFVTwoPhaseMixturePhysics)
void mooseError(Args &&... args) const
virtual void setSlipVelocityParams(InputParameters &params) const override
Adds the slip velocity parameters.
std::shared_ptr< FEProblemBase > & _problem
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
registerMooseAction("NavierStokesApp", WCNSLinearFVTwoPhaseMixturePhysics, "add_interpolation_method_physics")
bool isParamValid(const std::string &name) const
bool isParamSetByUser(const std::string &name) const
const WCNSFVFlowPhysicsBase * _flow_equations_physics
Flow physics.
const MooseFunctorName _phase_2_density
Name of the density of the other phase.
bool isTransient() const
void paramInfo(const std::string &param, Args... args) const