8.4. Free surfaces and evaporation
The previous example had just a single liquid domain. When a liquid and a gas domain are in contact, a free surface emerges where evaporation can happen. Fluid-fluid interfaces in general (i.e. liquid-gas or liquid-liquid) are both covered by the MultiComponentNavierStokesInterface class in the multi-component flow framework of pyoomph. It takes the properties of the interface as required argument. Interface properties can be obtained from the material library by using the operator | on the bulk phase properties. When we hence have e.g. multi-component flow via the CompositionFlowEquations() in a "liquid" domain and either CompositionFlowEquations() (or CompositionDiffusionEquations() for pure diffusive transport) in a "gas" phase, the assembly of the equations could look like
temperature=20*celsius
# Bulk properites (pure water liquid and air with some vapor in the gas phase)
liquid=get_pure_liquid("water")
gas=Mixture(get_pure_gas("air")+20*percent*get_pure_gas("water"),quantity="relative_humidity",temperature=temperature)
# Get the interface properties
interface_props=liquid | gas
# Assembly of an equation system
eqs=CompositionFlowEquations(liquid)@"liquid"
eqs+=CompositionDiffusionEquations(gas)@"gas" # (alternatively CompositionFlowEquations)
# free surface should be added to the liquid side of the liquid-gas interface:
eqs+=MultiComponentNavierStokesInterface(interface_props)@"liquid/liquid_gas"
The properties of liquid-gas interfaces can be defined by hand, but it is not necessary: If there are no particular properties of an interface between a liquid and a gas phase are present in the material library, default properties will be constructed. To that end the default_surface_tension dict entry ["gas"] of the liquid bulk properties will be used as surface_tension:
# Access the surface tension
print("Surface tension function:",interface_props.surface_tension) # same as liquid.default_surface_tension["gas"]
sigma_at_T=liquid.evaluate_at_condition(interface_props.surface_tension,liquid.initial_condition,temperature=temperature)
print("Surface tension at temperature T",sigma_at_T)
If one, for whatever reason, want to modify properties of a particular liquid-gas interface in the material library, one can register a particular class for that to the library by inheriting from the LiquidGasInterfaceProperties class:
# Register a particular liquid-gas interface to the library
@MaterialProperties.register()
class CustomInterfacePropertiesWaterVsVaporAir(LiquidGasInterfaceProperties):
liquid_components = {"water"} # Components in the liquid phase
gas_components = {"water","air"} # components in the gas phase
def __init__(self,phaseA,phaseB,surfactants):
super(CustomInterfacePropertiesWaterVsVaporAir, self).__init__(phaseA,phaseB,surfactants)
self.surface_tension=50*milli*newton/meter # set a custom surface tension
# Get the interface properties
new_interface_props=liquid | gas
print("New surface tension",new_interface_props.surface_tension)
When one tries to determine the interface properties via the | operator, these properties will be used when one has a liquid phase consisting of "water" and a gas phase with the components "water" and "air". This is identified by the sets liquid_components and gas_components of the class.
However, if one only wants to change e.g. the surface tension, it is easier to just set it directly after getting the default interface properties. I.e. without defining and registering the particular class, but just overriding the property directly:
# Override interface properties by hand
interface_props.surface_tension=50*milli*newton/meter