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