The interface for fvModels has been modified to improve its application
to "proxy" equations. That is, equations that are not straightforward
statements of conservation laws in OpenFOAM's usual convention.
A standard conservation law typically takes the following form:
fvMatrix<scalar> psiEqn
(
fvm::ddt(alpha, rho, psi)
+ <fluxes>
==
<sources>
);
A proxy equation, on the other hand, may be a derivation or
rearrangement of a law like this, and may be linearised in terms of a
different variable.
The pressure equation is the most common example of a proxy equation. It
represents a statement of the conservation of volume or mass, but it is
a rearrangement of the original continuity equation, and it has been
linearised in terms of a different variable; the pressure. Another
example is that in the pre-predictor of a VoF solver the
phase-continuity equation is constructed, but it is linearised in terms
of volume fraction rather than density.
In these situations, fvModels sources are now applied by calling:
fvModels().sourceProxy(<conserved-fields ...>, <equation-field>)
Where <conserved-fields ...> are (alpha, rho, psi), (rho, psi), just
(psi), or are omitted entirely (for volume continuity), and the
<equation-field> is the field associated with the proxy equation. This
produces a source term identical in value to the following call:
fvModels().source(<conserved-fields ...>)
It is only the linearisation in terms of <equation-field> that differs
between these two calls.
This change permits much greater flexibility in the handling of mass and
volume sources than the previous name-based system did. All the relevant
fields are available, dimensions can be used in the logic to determine
what sources are being constructed, and sources relating to a given
conservation law all share the same function.
This commit adds the functionality for injection-type sources in the
compressibleVoF solver. A following commit will add a volume source
model for use in incompressible solvers.
This change makes multiphaseEuler more consistent with other modules and
makes its sub-libraries less inter-dependent. Some left-over references
to multiphaseEulerFoam have also been removed.
The previous implementation was dimensionally inconsistent and was
missing a factor of the VbyA field. This change will, in most cases,
reduce the total impingement pressure contribution.
The functions module now applies time-step restrictions from the
functions that are running, rather than from the sub-solver. The
sub-solver only exists to be constructed so that its data is available
to the functions. It should not affect the solution process in any way.
A cloud's volume fraction is now generated with parcelCloud::alpha, and
the mass fraction with parcelCloud::Y. This is consistent with the rest
of OpenFOAM.
requiring all parts of the moving phase solution algorithm to loop and operate
on the moving phases only making the code easier to understand and maintain.
The central coefficient part of the virtual-mass phase acceleration matrix is
now included in the phase velocity transport central coefficient + drag matrix
so that the all the phase contributions to each phase momentum equation are
handled implicitly and consistently without lagging contribution from the other
phases in either the pressure equation or phase momentum correctors.
This improves the conditioning of the pressure equation and convergence rate of
bubbly-flow cases.
Population balance size-group fraction 'f<index>.<phase>' fields are now
read from an 'fDefault.<phase>' field if they are not provided
explicitly. This is the same process as is applied to species fractions
or fvDOM rays. The sum-of-fs field 'f.<phase>' is no longer required.
The value of a fraction field and its boundary conditions must now be
specified in the corresponding field file. Value entries are no longer
given in the size group dictionaries in the constant/phaseProperties
file, and an error message will be generated if a value entry is found.
The fraction fields are now numbered programatically, rather than being
named. So, the size-group dictionaries do not require a name any more.
All of the above is also true for any 'kappa<index>.<phase>' fields that
are constructed and solved for as part of a fractal shape model.
The following is an example of a specification of a population balance
with two phases in it:
populationBalances (bubbles);
air1
{
type pureIsothermalPhaseModel;
diameterModel velocityGroup;
velocityGroupCoeffs
{
populationBalance bubbles;
shapeModel spherical;
sizeGroups
(
{ dSph 1e-3; } // Size-group #0: Fraction field f0.air1
{ dSph 2e-3; } // ...
{ dSph 3e-3; }
{ dSph 4e-3; }
{ dSph 5e-3; }
);
}
residualAlpha 1e-6;
}
air2
{
type pureIsothermalPhaseModel;
diameterModel velocityGroup;
velocityGroupCoeffs
{
populationBalance bubbles;
shapeModel spherical;
sizeGroups
(
{ dSph 6e-3; } // Size-group #5: Fraction field f5.air2
{ dSph 7e-3; } // ...
{ dSph 8e-3; }
{ dSph 9e-3; }
{ dSph 10e-3; }
{ dSph 11e-3; }
{ dSph 12e-3; }
);
}
residualAlpha 1e-6;
}
Previously a fraction field was constructed automatically using the
boundary condition types from the sum-of-fs field, and the value of both
the internal and boundary field was then overridden by the value setting
provided for the size-group. This procedure doesn't generalise to
boundary conditions other than basic types that store no additional
data, like zeroGradient and fixedValue. More complex boundary conditions
such as inletOutlet and uniformFixedValue are incompatible with this
approach.
This is arguably less convenient than the previous specification, where
the sizes and fractions appeared together in a table-like list in the
sizeGroups entry. In the event that a substantial proportion of the
size-groups have a non-zero initial fraction, writing out all the field
files manually is extremely tedious. To mitigate this somewhat, a
packaged function has been added to initialise the fields given a file
containing a size distribution (see the pipeBend tutorial for an example
of its usage). This function has the same limitations as the previous
code in that it requires all boundary conditions to be default
constructable.
Ultimately, the "correct" fix for the issue of how to set the boundary
conditions conveniently is to create customised inlet-outlet boundary
conditions that determine their field's position within the population
balance and evaluate a distribution to determine the appropriate inlet
value. This work is pending funding.
Now with the addition of the optional dependenciesModified() function classes
which depend on other classes which are re-read from file when modified are also
automatically updated via their read() function called by
objectRegistry::readModifiedObjects.
This significantly simplifies the update of the solutionControls and modular
solvers when either the controlDict or fvSolution dictionaries are modified at
run-time.
The momentum equation central coefficient and drag matrix is formulated,
inverted and used to eliminate the drag terms from each of the phase momentum
equations which are combined for formulate a drag-implicit pressure equation.
This eliminates the lagged drag terms from the previous formulation which
significantly improves convergence for small particle and Euler-VoF high-drag
cases.
It would also be possible to refactor the virtual-mass terms and include the
central coefficients of the phase acceleration terms in the drag matrix before
inversion to further improve the implicitness of the phase momentum-pressure
coupling for bubbly flows. This work is pending funding.
When the flow is stationary (e.g., at the beginning of a run) the
rDeltaT calculation now requires a maxDeltaT setting in the PIMPLE
sub-section of the fvSolution dictionary. This prevents floating point
errors associated with rDeltaT approaching zero.
The phase velocity mean adjustment was introduced for consistency with phase
flux mean adjustment which is necessary to ensure the mean flux divergence is
preserved. However for systems with very high drag it has proved preferable to
not adjust the velocity of the phases to conserve momentum rather than ensure
consistency with the fluxes.
The old fluid-specific rhoThermo has been split into a non-fluid
specific part which is still called rhoThermo, and a fluid-specific part
called rhoFluidThermo. The rhoThermo interface has been added to the
solidThermo model. This permits models and solvers that access the
density to operate on both solid and fluid thermophysical models.
Mixture classes (e.g., pureMixtrure, coefficientMulticomponentMixture),
now have no fvMesh or volScalarField dependence. They operate on
primitive values only. All the fvMesh-dependent functionality has been
moved into the base thermodynamic classes. The 'composition()' access
function has been removed from multi-component thermo models. Functions
that were once provided by composition base classes such as
basicSpecieMixture and basicCombustionMixture are now implemented
directly in the relevant multi-component thermo base class.
at Function1s of time.
Underlying this new functionObject is a generalisation of the handling of the
maximum time-step in the modular solvers to allow complex user-specification of
the maximum time-step used in a simulation, not just the time-dependency
provided by fluidMaxDeltaT but functions of anything in the simulation by
creating a specialised functionObject in which the maxDeltaT function is
defined.
The chemical and combustion time-scale functionObjects adjustTimeStepToChemistry
and adjustTimeStepToCombustion have been updated and simplified using the above
mechanism.
for the multiphaseEuler solver module, replacing the more specific
uniformFixedMultiphaseHeatFluxFvPatchScalarField as it provide equivalent
functionality if the heat-flux q is specified.
multiphaseExternalTemperatureFvPatchScalarField is derived from the refactored
and generalised externalTemperatureFvPatchScalarField, overriding the
getKappa member function to provide the multiphase equivalents of kappa and
other heat transfer properties. All controls for
multiphaseExternalTemperatureFvPatchScalarField are the same as for
externalTemperatureFvPatchScalarField:
Class
Foam::externalTemperatureFvPatchScalarField
Description
This boundary condition applies a heat flux condition to temperature
on an external wall. Heat flux can be specified in the following ways:
- Fixed power: requires \c Q
- Fixed heat flux: requires \c q
- Fixed heat transfer coefficient: requires \c h and \c Ta
where:
\vartable
Q | Power Function1 of time [W]
q | Heat flux Function1 of time [W/m^2]
h | Heat transfer coefficient Function1 of time [W/m^2/K]
Ta | Ambient temperature Function1 of time [K]
\endvartable
Only one of \c Q or \c q may be specified, if \c h and \c Ta are also
specified the corresponding heat-flux is added.
If the heat transfer coefficient \c h is specified an optional thin thermal
layer resistances can also be specified through thicknessLayers and
kappaLayers entries.
The patch thermal conductivity \c kappa is obtained from the region
thermophysicalTransportModel so that this boundary condition can be applied
directly to either fluid or solid regions.
Usage
\table
Property | Description | Required | Default value
Q | Power [W] | no |
q | Heat flux [W/m^2] | no |
h | Heat transfer coefficient [W/m^2/K] | no |
Ta | Ambient temperature [K] | if h is given |
thicknessLayers | Layer thicknesses [m] | no |
kappaLayers | Layer thermal conductivities [W/m/K] | no |
relaxation | Relaxation for the wall temperature | no | 1
emissivity | Surface emissivity for radiative flux to ambient | no | 0
qr | Name of the radiative field | no | none
qrRelaxation | Relaxation factor for radiative field | no | 1
\endtable
Example of the boundary condition specification:
\verbatim
<patchName>
{
type externalTemperature;
Ta constant 300.0;
h uniform 10.0;
thicknessLayers (0.1 0.2 0.3 0.4);
kappaLayers (1 2 3 4);
value $internalField;
}
\endverbatim
See also
Foam::mixedFvPatchScalarField
Foam::Function1
The mappedValueFvPatchField boundary condition is special in that it can
construct its own mapping information if none is provided by the
underlying patch. This means different fields can be mapped between the
same patches with different mapping strategies. It is quite flexible,
and is often used for recyling properties between boundaries in order to
fully develop their profiles. It provides the ability to set the mean
and similar in order to facilitate this sort of usage.
It is not intended to be used in situations in which patches are
physically connected; region interfaces and similar. These connections
are required to be defined in the underlying patches themselves, as they
relate more fundamentally to the configuration of the mesh rather than
just the boundary conditions of specific fields.
Boundary conditions that map across physical connections (e.g.,
coupledTemperature, mappedFilmPressure, ...) are therefore required to
apply to a mapped patch. The mapping in these situations is a property
of the mesh, not of the boundary condition. If these conditions are
applied to a non-mapped patch then they will fail.
This change formalises the above logic and removes a now unnecessary
base class which was previously being used to share
mappedValueFvPatchField's mapping construction behaviour with other
boundary conditions.
The mappedValueAndPatchInternalValue condition has also been removed, as
this was only previously used in film, and has been replaced by simpler
and more usable options.
Lagrangian's dependency set is simpler than it used to be. There is no
longer a need to maintain a separate library for models that depend on
the momentum transport modelling.