Line data Source code
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 :
10 : #include "WCNSLinearFVTwoPhaseMixturePhysics.h"
11 : #include "WCNSFVTwoPhaseMixturePhysics.h"
12 : #include "WCNSFVFluidHeatTransferPhysics.h"
13 : #include "WCNSLinearFVFluidHeatTransferPhysics.h"
14 : #include "WCNSFVFlowPhysics.h"
15 :
16 : registerNavierStokesPhysicsBaseTasks("NavierStokesApp", WCNSLinearFVTwoPhaseMixturePhysics);
17 : registerWCNSFVScalarTransportBaseTasks("NavierStokesApp", WCNSLinearFVTwoPhaseMixturePhysics);
18 : registerMooseAction("NavierStokesApp", WCNSLinearFVTwoPhaseMixturePhysics, "add_material");
19 : registerMooseAction("NavierStokesApp", WCNSLinearFVTwoPhaseMixturePhysics, "check_integrity");
20 :
21 : InputParameters
22 40 : WCNSLinearFVTwoPhaseMixturePhysics::validParams()
23 : {
24 : // The parameters are mostly the same being the linear and nonlinear version
25 40 : InputParameters params = WCNSLinearFVScalarTransportPhysics::validParams();
26 40 : WCNSFVTwoPhaseMixturePhysics::renamePassiveScalarToMixtureParams(params);
27 : // The flow physics is obtained from the scalar transport base class
28 : // The fluid heat transfer physics is retrieved even if unspecified
29 80 : params.addParam<PhysicsName>(
30 : "fluid_heat_transfer_physics",
31 : "NavierStokesFV",
32 : "WCNSLinearFVFluidHeatTransferPhysics generating the fluid energy equation");
33 40 : params += WCNSFVTwoPhaseMixturePhysics::commonMixtureParams();
34 80 : params.addParamNamesToGroup("fluid_heat_transfer_physics", "Phase change");
35 40 : 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 80 : params.addParam<bool>("add_gravity_term_in_slip_velocity",
41 80 : true,
42 : "Whether to add the gravity term in the slip velocity vector computation");
43 40 : return params;
44 0 : }
45 :
46 40 : WCNSLinearFVTwoPhaseMixturePhysics::WCNSLinearFVTwoPhaseMixturePhysics(
47 40 : const InputParameters & parameters)
48 : : WCNSLinearFVScalarTransportPhysics(parameters),
49 40 : _add_phase_equation(_has_scalar_equation),
50 40 : _phase_1_fraction_name(getParam<MooseFunctorName>("phase_1_fraction_name")),
51 40 : _phase_2_fraction_name(_passive_scalar_names[0]),
52 40 : _phase_1_density(getParam<MooseFunctorName>("phase_1_density_name")),
53 40 : _phase_1_viscosity(getParam<MooseFunctorName>("phase_1_viscosity_name")),
54 40 : _phase_1_specific_heat(getParam<MooseFunctorName>("phase_1_specific_heat_name")),
55 40 : _phase_1_thermal_conductivity(getParam<MooseFunctorName>("phase_1_thermal_conductivity_name")),
56 40 : _phase_2_density(getParam<MooseFunctorName>("phase_2_density_name")),
57 40 : _phase_2_viscosity(getParam<MooseFunctorName>("phase_2_viscosity_name")),
58 40 : _phase_2_specific_heat(getParam<MooseFunctorName>("phase_2_specific_heat_name")),
59 40 : _phase_2_thermal_conductivity(getParam<MooseFunctorName>("phase_2_thermal_conductivity_name")),
60 80 : _use_external_mixture_properties(getParam<bool>("use_external_mixture_properties")),
61 80 : _use_drift_flux(getParam<bool>("add_drift_flux_momentum_terms")),
62 120 : _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 40 : if (_passive_scalar_names.size() > 1)
66 0 : paramError("phase_fraction_name", "Only one phase fraction currently supported.");
67 40 : if (_passive_scalar_inlet_functors.size() > 1)
68 0 : paramError("phase_fraction_inlet_functors", "Only one phase fraction currently supported");
69 :
70 : // Retrieve the fluid energy equation if it exists
71 80 : if (isParamValid("fluid_heat_transfer_physics"))
72 : {
73 80 : _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 80 : if (!_fluid_energy_physics &&
77 80 : !getCoupledPhysics<const WCNSLinearFVFluidHeatTransferPhysics>(true).empty())
78 0 : 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");
82 40 : if (_fluid_energy_physics && _fluid_energy_physics->hasEnergyEquation())
83 0 : _has_energy_equation = true;
84 : else
85 40 : _has_energy_equation = false;
86 : }
87 : else
88 : {
89 0 : _has_energy_equation = false;
90 0 : _fluid_energy_physics = nullptr;
91 : }
92 :
93 : // Check that the mixture parameters are correctly in use in the other physics
94 40 : if (_has_energy_equation)
95 : {
96 0 : if (_fluid_energy_physics->densityName() != "rho_mixture")
97 0 : mooseError(
98 : "Density name for Physics '", _fluid_energy_physics->name(), "' should be 'rho_mixture'");
99 0 : if (_fluid_energy_physics->getSpecificHeatName() != "cp_mixture")
100 0 : mooseError("Specific heat name for Physics '",
101 : _fluid_energy_physics->name(),
102 : "' should be 'cp_mixture'");
103 : }
104 40 : if (_flow_equations_physics)
105 40 : if (_flow_equations_physics->densityName() != "rho_mixture")
106 0 : mooseError("Density name for Physics ,",
107 0 : _flow_equations_physics->name(),
108 : "' should be 'rho_mixture'");
109 :
110 40 : if (_verbose)
111 : {
112 0 : if (_flow_equations_physics)
113 0 : mooseInfoRepeated("Coupled to fluid flow physics " + _flow_equations_physics->name());
114 0 : if (_has_energy_equation)
115 0 : mooseInfoRepeated("Coupled to fluid heat transfer physics " + _fluid_energy_physics->name());
116 : }
117 :
118 : // Parameter checking
119 : // The two models are not consistent
120 118 : if (isParamSetByUser("alpha_exchange") && getParam<bool>("add_phase_change_energy_term"))
121 0 : 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");
124 40 : if (_phase_1_fraction_name == _phase_2_fraction_name)
125 0 : paramError("phase_1_fraction_name",
126 : "First phase fraction name should be different from second phase fraction name");
127 40 : if (_use_drift_flux && _use_advection_slip)
128 0 : paramError("add_drift_flux_momentum_terms",
129 : "Drift flux model cannot be used at the same time as the advection slip model");
130 80 : if (!getParam<bool>("add_drift_flux_momentum_terms"))
131 42 : errorDependentParameter("add_drift_flux_momentum_terms", "true", {"density_interp_method"});
132 80 : if (!getParam<bool>("use_dispersed_phase_drag_model"))
133 0 : errorDependentParameter("use_dispersed_phase_drag_model", "true", {"particle_diameter"});
134 40 : }
135 :
136 : void
137 40 : WCNSLinearFVTwoPhaseMixturePhysics::checkIntegrity() const
138 : {
139 40 : if (!_flow_equations_physics)
140 0 : mooseError("Expected a flow physics");
141 :
142 : // Check the mesh for unsupported sknewness + buoyancy
143 40 : if (_flow_equations_physics->gravityVector().norm() > 0)
144 : {
145 : const auto tol = 1e-2;
146 2 : if (_problem->mesh().allFaceInfo().empty())
147 0 : _problem->mesh().setupFiniteVolumeMeshData();
148 4 : for (const auto & fi : _problem->mesh().allFaceInfo())
149 : {
150 4 : if (fi.skewnessCorrectionVector().norm() > tol * fi.dCNMag())
151 2 : 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 38 : }
159 :
160 : void
161 40 : WCNSLinearFVTwoPhaseMixturePhysics::addFVKernels()
162 : {
163 40 : WCNSLinearFVScalarTransportPhysics::addFVKernels();
164 :
165 120 : if (_add_phase_equation && isParamSetByUser("alpha_exchange"))
166 19 : addPhaseInterfaceTerm();
167 :
168 40 : if (_fluid_energy_physics && _fluid_energy_physics->hasEnergyEquation() &&
169 40 : getParam<bool>("add_phase_change_energy_term"))
170 0 : addPhaseChangeEnergySource();
171 :
172 40 : if (_flow_equations_physics && _flow_equations_physics->hasFlowEquations() && _use_drift_flux)
173 19 : addPhaseDriftFluxTerm();
174 40 : if (_flow_equations_physics && _flow_equations_physics->hasFlowEquations() && _use_advection_slip)
175 0 : addAdvectionSlipTerm();
176 40 : }
177 :
178 : void
179 78 : WCNSLinearFVTwoPhaseMixturePhysics::setSlipVelocityParams(InputParameters & params) const
180 : {
181 156 : params.set<MooseFunctorName>("u_slip") = "vel_slip_x";
182 78 : if (dimension() >= 2)
183 156 : params.set<MooseFunctorName>("v_slip") = "vel_slip_y";
184 78 : if (dimension() >= 3)
185 0 : params.set<MooseFunctorName>("w_slip") = "vel_slip_z";
186 78 : }
187 :
188 : void
189 19 : WCNSLinearFVTwoPhaseMixturePhysics::addPhaseInterfaceTerm()
190 : {
191 : // Recreate the phase interface term from existing kernels
192 : {
193 19 : auto params = getFactory().getValidParams("LinearFVReaction");
194 19 : assignBlocks(params, _blocks);
195 38 : params.set<LinearVariableName>("variable") = _phase_2_fraction_name;
196 38 : params.set<MooseFunctorName>("coeff") = getParam<MooseFunctorName>(NS::alpha_exchange);
197 38 : getProblem().addLinearFVKernel(
198 19 : "LinearFVReaction", prefix() + "phase_interface_reaction", params);
199 19 : }
200 : {
201 19 : auto params = getFactory().getValidParams("LinearFVSource");
202 19 : assignBlocks(params, _blocks);
203 38 : params.set<LinearVariableName>("variable") = _phase_2_fraction_name;
204 38 : params.set<MooseFunctorName>("source_density") = _phase_1_fraction_name;
205 38 : params.set<MooseFunctorName>("scaling_factor") = getParam<MooseFunctorName>(NS::alpha_exchange);
206 57 : getProblem().addLinearFVKernel("LinearFVSource", prefix() + "phase_interface_source", params);
207 19 : }
208 19 : }
209 :
210 : void
211 0 : WCNSLinearFVTwoPhaseMixturePhysics::addPhaseChangeEnergySource()
212 : {
213 0 : mooseError("Phase change energy source not implemented at this time for linear finite volume");
214 : }
215 :
216 : void
217 19 : WCNSLinearFVTwoPhaseMixturePhysics::addPhaseDriftFluxTerm()
218 : {
219 19 : const std::vector<std::string> components = {"x", "y", "z"};
220 76 : for (const auto dim : make_range(dimension()))
221 : {
222 : const auto object_type = "LinearWCNSFV2PMomentumDriftFlux";
223 38 : auto params = getFactory().getValidParams(object_type);
224 38 : assignBlocks(params, _blocks);
225 76 : params.set<LinearVariableName>("variable") = _flow_equations_physics->getVelocityNames()[dim];
226 38 : setSlipVelocityParams(params);
227 38 : params.set<MooseFunctorName>("rho_d") = _phase_2_density;
228 76 : params.set<MooseFunctorName>("fraction_dispersed") = _phase_2_fraction_name;
229 38 : params.set<MooseEnum>("momentum_component") = components[dim];
230 114 : params.set<MooseEnum>("density_interp_method") = getParam<MooseEnum>("density_interp_method");
231 76 : params.set<UserObjectName>("rhie_chow_user_object") = _flow_equations_physics->rhieChowUOName();
232 114 : getProblem().addLinearFVKernel(object_type, prefix() + "drift_flux_" + components[dim], params);
233 38 : }
234 19 : }
235 :
236 : void
237 0 : WCNSLinearFVTwoPhaseMixturePhysics::addAdvectionSlipTerm()
238 : {
239 0 : mooseError("Phase advection slip not implemented at this time for linear finite volume");
240 : }
241 :
242 : void
243 40 : WCNSLinearFVTwoPhaseMixturePhysics::addMaterials()
244 : {
245 : // Add the phase fraction variable, for output purposes mostly
246 40 : if (!getProblem().hasFunctor(_phase_1_fraction_name, /*thread_id=*/0))
247 : {
248 40 : auto params = getFactory().getValidParams("ParsedFunctorMaterial");
249 40 : assignBlocks(params, _blocks);
250 80 : params.set<std::string>("expression") = "1 - " + _phase_2_fraction_name;
251 120 : params.set<std::vector<std::string>>("functor_names") = {_phase_2_fraction_name};
252 40 : params.set<std::string>("property_name") = _phase_1_fraction_name;
253 120 : params.set<std::vector<std::string>>("output_properties") = {_phase_1_fraction_name};
254 120 : params.set<std::vector<OutputName>>("outputs") = {"all"};
255 160 : 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 40 : if (!getProblem().hasFunctor(_phase_2_fraction_name, /*thread_id=*/0))
260 0 : paramError("Phase 2 fraction should be defined as a variable or auxiliary variable");
261 40 : }
262 40 : if (!getProblem().hasFunctor(_phase_2_fraction_name, /*thread_id=*/0))
263 : {
264 0 : auto params = getFactory().getValidParams("ParsedFunctorMaterial");
265 0 : assignBlocks(params, _blocks);
266 0 : params.set<std::string>("expression") = "1 - " + _phase_1_fraction_name;
267 0 : params.set<std::vector<std::string>>("functor_names") = {_phase_1_fraction_name};
268 0 : params.set<std::string>("property_name") = _phase_2_fraction_name;
269 0 : params.set<std::vector<std::string>>("output_properties") = {_phase_2_fraction_name};
270 0 : params.set<std::vector<OutputName>>("outputs") = {"all"};
271 0 : getProblem().addMaterial("ParsedFunctorMaterial", prefix() + "phase_2_fraction", params);
272 0 : }
273 :
274 : // Compute mixture properties
275 40 : if (!_use_external_mixture_properties)
276 : {
277 40 : auto params = getFactory().getValidParams("WCNSLinearFVMixtureFunctorMaterial");
278 40 : assignBlocks(params, _blocks);
279 80 : params.set<std::vector<MooseFunctorName>>("prop_names") = {
280 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 80 : params.set<std::vector<MooseFunctorName>>("phase_2_names") = {_phase_1_density,
285 : _phase_1_viscosity,
286 : _phase_1_specific_heat,
287 280 : _phase_1_thermal_conductivity};
288 80 : params.set<std::vector<MooseFunctorName>>("phase_1_names") = {_phase_2_density,
289 : _phase_2_viscosity,
290 : _phase_2_specific_heat,
291 280 : _phase_2_thermal_conductivity};
292 40 : params.set<MooseFunctorName>("phase_1_fraction") = _phase_2_fraction_name;
293 80 : if (getParam<bool>("output_all_properties"))
294 120 : params.set<std::vector<OutputName>>("outputs") = {"all"};
295 40 : params.set<bool>("limit_phase_fraction") = true;
296 80 : getProblem().addMaterial(
297 40 : "WCNSLinearFVMixtureFunctorMaterial", prefix() + "mixture_material", params);
298 40 : }
299 :
300 : // Compute slip terms as functors, used by the drift flux kernels
301 40 : if (_use_advection_slip || _use_drift_flux || _add_phase_equation)
302 : {
303 : mooseAssert(_flow_equations_physics, "We must have coupled to this");
304 40 : const std::vector<std::string> vel_components = {"u", "v", "w"};
305 40 : const std::vector<std::string> components = {"x", "y", "z"};
306 160 : for (const auto dim : make_range(dimension()))
307 : {
308 80 : auto params = getFactory().getValidParams("WCNSFV2PSlipVelocityFunctorMaterial");
309 80 : assignBlocks(params, _blocks);
310 320 : params.set<MooseFunctorName>("slip_velocity_name") = "vel_slip_" + components[dim];
311 80 : params.set<MooseEnum>("momentum_component") = components[dim];
312 320 : for (const auto j : make_range(dimension()))
313 160 : params.set<std::vector<VariableName>>(vel_components[j]) = {
314 480 : _flow_equations_physics->getVelocityNames()[j]};
315 80 : params.set<MooseFunctorName>(NS::density) = _phase_1_density;
316 80 : params.set<MooseFunctorName>(NS::mu) = "mu_mixture";
317 80 : params.set<MooseFunctorName>("rho_d") = _phase_2_density;
318 160 : if (getParam<bool>("add_gravity_term_in_slip_velocity"))
319 80 : params.set<RealVectorValue>("gravity") = _flow_equations_physics->gravityVector();
320 160 : if (isParamValid("slip_linear_friction_name"))
321 76 : params.set<MooseFunctorName>("linear_coef_name") =
322 76 : getParam<MooseFunctorName>("slip_linear_friction_name");
323 84 : else if (getParam<bool>("use_dispersed_phase_drag_model"))
324 84 : params.set<MooseFunctorName>("linear_coef_name") = "Darcy_coefficient";
325 0 : else if (_flow_equations_physics)
326 : {
327 0 : if (!_flow_equations_physics->getLinearFrictionCoefName().empty())
328 0 : params.set<MooseFunctorName>("linear_coef_name") =
329 0 : _flow_equations_physics->getLinearFrictionCoefName();
330 : else
331 0 : params.set<MooseFunctorName>("linear_coef_name") = "0";
332 : }
333 : else
334 0 : paramError("slip_linear_friction_name",
335 : "WCNSFV2PSlipVelocityFunctorMaterial created by this Physics required a scalar "
336 : "field linear friction factor.");
337 160 : params.set<MooseFunctorName>("particle_diameter") =
338 80 : getParam<MooseFunctorName>("particle_diameter");
339 160 : if (getParam<bool>("output_all_properties"))
340 : {
341 80 : if (!isTransient())
342 114 : params.set<std::vector<OutputName>>("outputs") = {"all"};
343 : else
344 84 : paramInfo("output_all_properties",
345 : "Slip velocity functor material output currently unsupported in Physics "
346 : "in transient conditions.");
347 : }
348 240 : getProblem().addMaterial(
349 160 : "WCNSFV2PSlipVelocityFunctorMaterial", prefix() + "slip_" + components[dim], params);
350 80 : }
351 40 : }
352 :
353 : // Add a default drag model for a dispersed phase
354 80 : if (getParam<bool>("use_dispersed_phase_drag_model"))
355 : {
356 40 : const std::vector<std::string> vel_components = {"u", "v", "w"};
357 :
358 40 : auto params = getFactory().getValidParams("NSFVDispersePhaseDragFunctorMaterial");
359 40 : assignBlocks(params, _blocks);
360 80 : params.set<MooseFunctorName>("drag_coef_name") = "Darcy_coefficient";
361 160 : for (const auto j : make_range(dimension()))
362 80 : params.set<MooseFunctorName>(vel_components[j]) = {
363 160 : _flow_equations_physics->getVelocityNames()[j]};
364 80 : params.set<MooseFunctorName>(NS::density) = "rho_mixture";
365 40 : params.set<MooseFunctorName>(NS::mu) = "mu_mixture";
366 80 : params.set<MooseFunctorName>("particle_diameter") =
367 40 : getParam<MooseFunctorName>("particle_diameter");
368 80 : if (getParam<bool>("output_all_properties"))
369 120 : params.set<std::vector<OutputName>>("outputs") = {"all"};
370 80 : getProblem().addMaterial(
371 40 : "NSFVDispersePhaseDragFunctorMaterial", prefix() + "dispersed_drag", params);
372 40 : }
373 120 : }
|