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", WCNSLinearFVTwoPhaseMixturePhysics, "add_material");
19 registerMooseAction("NavierStokesApp", WCNSLinearFVTwoPhaseMixturePhysics, "check_integrity");
20 
23 {
24  // The parameters are mostly the same being the linear and nonlinear version
27  // The flow physics is obtained from the scalar transport base class
28  // The fluid heat transfer physics is retrieved even if unspecified
29  params.addParam<PhysicsName>(
30  "fluid_heat_transfer_physics",
31  "NavierStokesFV",
32  "WCNSLinearFVFluidHeatTransferPhysics generating the fluid energy equation");
34  params.addParamNamesToGroup("fluid_heat_transfer_physics", "Phase change");
35  params.addClassDescription("Define the additional terms for a mixture model for the two phase "
36  "weakly-compressible Navier Stokes equations using the linearized "
37  "segregated finite volume discretization");
38 
39  // This is added to match a nonlinear test result. If the underlying issue is fixed, remove it
40  params.addParam<bool>("add_gravity_term_in_slip_velocity",
41  true,
42  "Whether to add the gravity term in the slip velocity vector computation");
43  return params;
44 }
45 
47  const InputParameters & parameters)
49  _add_phase_equation(_has_scalar_equation),
50  _phase_1_fraction_name(getParam<MooseFunctorName>("phase_1_fraction_name")),
51  _phase_2_fraction_name(_passive_scalar_names[0]),
52  _phase_1_density(getParam<MooseFunctorName>("phase_1_density_name")),
53  _phase_1_viscosity(getParam<MooseFunctorName>("phase_1_viscosity_name")),
54  _phase_1_specific_heat(getParam<MooseFunctorName>("phase_1_specific_heat_name")),
55  _phase_1_thermal_conductivity(getParam<MooseFunctorName>("phase_1_thermal_conductivity_name")),
56  _phase_2_density(getParam<MooseFunctorName>("phase_2_density_name")),
57  _phase_2_viscosity(getParam<MooseFunctorName>("phase_2_viscosity_name")),
58  _phase_2_specific_heat(getParam<MooseFunctorName>("phase_2_specific_heat_name")),
59  _phase_2_thermal_conductivity(getParam<MooseFunctorName>("phase_2_thermal_conductivity_name")),
60  _use_external_mixture_properties(getParam<bool>("use_external_mixture_properties")),
61  _use_drift_flux(getParam<bool>("add_drift_flux_momentum_terms")),
62  _use_advection_slip(getParam<bool>("add_advection_slip_term"))
63 {
64  // Check that only one scalar was passed, as we are using vector parameters
65  if (_passive_scalar_names.size() > 1)
66  paramError("phase_fraction_name", "Only one phase fraction currently supported.");
67  if (_passive_scalar_inlet_functors.size() > 1)
68  paramError("phase_fraction_inlet_functors", "Only one phase fraction currently supported");
69 
70  // Retrieve the fluid energy equation if it exists
71  if (isParamValid("fluid_heat_transfer_physics"))
72  {
73  _fluid_energy_physics = getCoupledPhysics<WCNSLinearFVFluidHeatTransferPhysics>(
74  getParam<PhysicsName>("fluid_heat_transfer_physics"), true);
75  // Check for a missing parameter / do not support isolated physics for now
76  if (!_fluid_energy_physics &&
77  !getCoupledPhysics<const WCNSLinearFVFluidHeatTransferPhysics>(true).empty())
78  paramError(
79  "fluid_heat_transfer_physics",
80  "We currently do not support creating both a phase transport equation and fluid heat "
81  "transfer physics that are not coupled together");
83  _has_energy_equation = true;
84  else
85  _has_energy_equation = false;
86  }
87  else
88  {
89  _has_energy_equation = false;
90  _fluid_energy_physics = nullptr;
91  }
92 
93  // Check that the mixture parameters are correctly in use in the other physics
95  {
96  if (_fluid_energy_physics->densityName() != "rho_mixture")
97  mooseError(
98  "Density name for Physics '", _fluid_energy_physics->name(), "' should be 'rho_mixture'");
99  if (_fluid_energy_physics->getSpecificHeatName() != "cp_mixture")
100  mooseError("Specific heat name for Physics '",
102  "' should be 'cp_mixture'");
103  }
105  if (_flow_equations_physics->densityName() != "rho_mixture")
106  mooseError("Density name for Physics ,",
108  "' should be 'rho_mixture'");
109 
110  if (_verbose)
111  {
113  mooseInfoRepeated("Coupled to fluid flow physics " + _flow_equations_physics->name());
115  mooseInfoRepeated("Coupled to fluid heat transfer physics " + _fluid_energy_physics->name());
116  }
117 
118  // Parameter checking
119  // The two models are not consistent
120  if (isParamSetByUser("alpha_exchange") && getParam<bool>("add_phase_change_energy_term"))
121  paramError("alpha_exchange",
122  "A phase exchange coefficient cannot be specified if the phase change is handled "
123  "with a phase change heat loss model");
125  paramError("phase_1_fraction_name",
126  "First phase fraction name should be different from second phase fraction name");
128  paramError("add_drift_flux_momentum_terms",
129  "Drift flux model cannot be used at the same time as the advection slip model");
130  if (!getParam<bool>("add_drift_flux_momentum_terms"))
131  errorDependentParameter("add_drift_flux_momentum_terms", "true", {"density_interp_method"});
132  if (!getParam<bool>("use_dispersed_phase_drag_model"))
133  errorDependentParameter("use_dispersed_phase_drag_model", "true", {"particle_diameter"});
134 }
135 
136 void
138 {
140  mooseError("Expected a flow physics");
141 
142  // Check the mesh for unsupported sknewness + buoyancy
144  {
145  const auto tol = 1e-2;
146  if (_problem->mesh().allFaceInfo().empty())
147  _problem->mesh().setupFiniteVolumeMeshData();
148  for (const auto & fi : _problem->mesh().allFaceInfo())
149  {
150  if (fi.skewnessCorrectionVector().norm() > tol * fi.dCNMag())
151  mooseError("Face with centroid ",
152  fi.faceCentroid(),
153  " requires skewness correction. We currently do not support mixture flow with "
154  "buoyancy and mesh skewness. Please contact a MOOSE or Navier Stokes module "
155  "developer if you require this.");
156  }
157  }
158 }
159 
160 void
162 {
164 
165  if (_add_phase_equation && isParamSetByUser("alpha_exchange"))
167 
169  getParam<bool>("add_phase_change_energy_term"))
171 
176 }
177 
178 void
180 {
181  params.set<MooseFunctorName>("u_slip") = "vel_slip_x";
182  if (dimension() >= 2)
183  params.set<MooseFunctorName>("v_slip") = "vel_slip_y";
184  if (dimension() >= 3)
185  params.set<MooseFunctorName>("w_slip") = "vel_slip_z";
186 }
187 
188 void
190 {
191  // Recreate the phase interface term from existing kernels
192  {
193  auto params = getFactory().getValidParams("LinearFVReaction");
194  assignBlocks(params, _blocks);
195  params.set<LinearVariableName>("variable") = _phase_2_fraction_name;
196  params.set<MooseFunctorName>("coeff") = getParam<MooseFunctorName>(NS::alpha_exchange);
198  "LinearFVReaction", prefix() + "phase_interface_reaction", params);
199  }
200  {
201  auto params = getFactory().getValidParams("LinearFVSource");
202  assignBlocks(params, _blocks);
203  params.set<LinearVariableName>("variable") = _phase_2_fraction_name;
204  params.set<MooseFunctorName>("source_density") = _phase_1_fraction_name;
205  params.set<MooseFunctorName>("scaling_factor") = getParam<MooseFunctorName>(NS::alpha_exchange);
206  getProblem().addLinearFVKernel("LinearFVSource", prefix() + "phase_interface_source", params);
207  }
208 }
209 
210 void
212 {
213  mooseError("Phase change energy source not implemented at this time for linear finite volume");
214 }
215 
216 void
218 {
219  const std::vector<std::string> components = {"x", "y", "z"};
220  for (const auto dim : make_range(dimension()))
221  {
222  const auto object_type = "LinearWCNSFV2PMomentumDriftFlux";
223  auto params = getFactory().getValidParams(object_type);
224  assignBlocks(params, _blocks);
225  params.set<LinearVariableName>("variable") = _flow_equations_physics->getVelocityNames()[dim];
226  setSlipVelocityParams(params);
227  params.set<MooseFunctorName>("rho_d") = _phase_2_density;
228  params.set<MooseFunctorName>("fraction_dispersed") = _phase_2_fraction_name;
229  params.set<MooseEnum>("momentum_component") = components[dim];
230  params.set<MooseEnum>("density_interp_method") = getParam<MooseEnum>("density_interp_method");
231  params.set<UserObjectName>("rhie_chow_user_object") = _flow_equations_physics->rhieChowUOName();
232  getProblem().addLinearFVKernel(object_type, prefix() + "drift_flux_" + components[dim], params);
233  }
234 }
235 
236 void
238 {
239  mooseError("Phase advection slip not implemented at this time for linear finite volume");
240 }
241 
242 void
244 {
245  // Add the phase fraction variable, for output purposes mostly
246  if (!getProblem().hasFunctor(_phase_1_fraction_name, /*thread_id=*/0))
247  {
248  auto params = getFactory().getValidParams("ParsedFunctorMaterial");
249  assignBlocks(params, _blocks);
250  params.set<std::string>("expression") = "1 - " + _phase_2_fraction_name;
251  params.set<std::vector<std::string>>("functor_names") = {_phase_2_fraction_name};
252  params.set<std::string>("property_name") = _phase_1_fraction_name;
253  params.set<std::vector<std::string>>("output_properties") = {_phase_1_fraction_name};
254  params.set<std::vector<OutputName>>("outputs") = {"all"};
255  getProblem().addMaterial("ParsedFunctorMaterial", prefix() + "phase_1_fraction", params);
256 
257  // One of the phase fraction should exist though (either as a variable or set by a
258  // NSLiquidFractionAux)
259  if (!getProblem().hasFunctor(_phase_2_fraction_name, /*thread_id=*/0))
260  paramError("Phase 2 fraction should be defined as a variable or auxiliary variable");
261  }
262  if (!getProblem().hasFunctor(_phase_2_fraction_name, /*thread_id=*/0))
263  {
264  auto params = getFactory().getValidParams("ParsedFunctorMaterial");
265  assignBlocks(params, _blocks);
266  params.set<std::string>("expression") = "1 - " + _phase_1_fraction_name;
267  params.set<std::vector<std::string>>("functor_names") = {_phase_1_fraction_name};
268  params.set<std::string>("property_name") = _phase_2_fraction_name;
269  params.set<std::vector<std::string>>("output_properties") = {_phase_2_fraction_name};
270  params.set<std::vector<OutputName>>("outputs") = {"all"};
271  getProblem().addMaterial("ParsedFunctorMaterial", prefix() + "phase_2_fraction", params);
272  }
273 
274  // Compute mixture properties
276  {
277  auto params = getFactory().getValidParams("WCNSLinearFVMixtureFunctorMaterial");
278  assignBlocks(params, _blocks);
279  params.set<std::vector<MooseFunctorName>>("prop_names") = {
280  "rho_mixture", "mu_mixture", "cp_mixture", "k_mixture"};
281  // The phase_1 and phase_2 assignments are only local to this object.
282  // We use the phase 2 variable to save a functor evaluation as we expect
283  // the phase 2 variable to be a nonlinear variable in the phase transport equation
284  params.set<std::vector<MooseFunctorName>>("phase_2_names") = {_phase_1_density,
288  params.set<std::vector<MooseFunctorName>>("phase_1_names") = {_phase_2_density,
292  params.set<MooseFunctorName>("phase_1_fraction") = _phase_2_fraction_name;
293  if (getParam<bool>("output_all_properties"))
294  params.set<std::vector<OutputName>>("outputs") = {"all"};
295  params.set<bool>("limit_phase_fraction") = true;
297  "WCNSLinearFVMixtureFunctorMaterial", prefix() + "mixture_material", params);
298  }
299 
300  // Compute slip terms as functors, used by the drift flux kernels
302  {
303  mooseAssert(_flow_equations_physics, "We must have coupled to this");
304  const std::vector<std::string> vel_components = {"u", "v", "w"};
305  const std::vector<std::string> components = {"x", "y", "z"};
306  for (const auto dim : make_range(dimension()))
307  {
308  auto params = getFactory().getValidParams("WCNSFV2PSlipVelocityFunctorMaterial");
309  assignBlocks(params, _blocks);
310  params.set<MooseFunctorName>("slip_velocity_name") = "vel_slip_" + components[dim];
311  params.set<MooseEnum>("momentum_component") = components[dim];
312  for (const auto j : make_range(dimension()))
313  params.set<std::vector<VariableName>>(vel_components[j]) = {
315  params.set<MooseFunctorName>(NS::density) = _phase_1_density;
316  params.set<MooseFunctorName>(NS::mu) = "mu_mixture";
317  params.set<MooseFunctorName>("rho_d") = _phase_2_density;
318  if (getParam<bool>("add_gravity_term_in_slip_velocity"))
319  params.set<RealVectorValue>("gravity") = _flow_equations_physics->gravityVector();
320  if (isParamValid("slip_linear_friction_name"))
321  params.set<MooseFunctorName>("linear_coef_name") =
322  getParam<MooseFunctorName>("slip_linear_friction_name");
323  else if (getParam<bool>("use_dispersed_phase_drag_model"))
324  params.set<MooseFunctorName>("linear_coef_name") = "Darcy_coefficient";
325  else if (_flow_equations_physics)
326  {
328  params.set<MooseFunctorName>("linear_coef_name") =
330  else
331  params.set<MooseFunctorName>("linear_coef_name") = "0";
332  }
333  else
334  paramError("slip_linear_friction_name",
335  "WCNSFV2PSlipVelocityFunctorMaterial created by this Physics required a scalar "
336  "field linear friction factor.");
337  params.set<MooseFunctorName>("particle_diameter") =
338  getParam<MooseFunctorName>("particle_diameter");
339  if (getParam<bool>("output_all_properties"))
340  {
341  if (!isTransient())
342  params.set<std::vector<OutputName>>("outputs") = {"all"};
343  else
344  paramInfo("output_all_properties",
345  "Slip velocity functor material output currently unsupported in Physics "
346  "in transient conditions.");
347  }
349  "WCNSFV2PSlipVelocityFunctorMaterial", prefix() + "slip_" + components[dim], params);
350  }
351  }
352 
353  // Add a default drag model for a dispersed phase
354  if (getParam<bool>("use_dispersed_phase_drag_model"))
355  {
356  const std::vector<std::string> vel_components = {"u", "v", "w"};
357 
358  auto params = getFactory().getValidParams("NSFVDispersePhaseDragFunctorMaterial");
359  assignBlocks(params, _blocks);
360  params.set<MooseFunctorName>("drag_coef_name") = "Darcy_coefficient";
361  for (const auto j : make_range(dimension()))
362  params.set<MooseFunctorName>(vel_components[j]) = {
364  params.set<MooseFunctorName>(NS::density) = "rho_mixture";
365  params.set<MooseFunctorName>(NS::mu) = "mu_mixture";
366  params.set<MooseFunctorName>("particle_diameter") =
367  getParam<MooseFunctorName>("particle_diameter");
368  if (getParam<bool>("output_all_properties"))
369  params.set<std::vector<OutputName>>("outputs") = {"all"};
371  "NSFVDispersePhaseDragFunctorMaterial", prefix() + "dispersed_drag", params);
372  }
373 }
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 -> decltype(std::norm(Real()))
registerMooseAction("NavierStokesApp", WCNSLinearFVTwoPhaseMixturePhysics, "add_material")
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:33
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
virtual const std::string & name() const
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
bool isParamValid(const std::string &name) 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)
virtual UserObjectName rhieChowUOName() const =0
Return the name of the Rhie Chow user object.
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:123
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.
void paramError(const std::string &param, Args... args) const
static const std::string alpha_exchange
Definition: NS.h:150
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)
bool isParamSetByUser(const std::string &nm) const
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.
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")
void paramInfo(const std::string &param, Args... args) const
const WCNSFVFlowPhysicsBase * _flow_equations_physics
Flow physics.
const MooseFunctorName _phase_2_density
Name of the density of the other phase.
bool isTransient() const