Bubble screens¶
A bubble screen (also called an air curtain) is a row of nozzles on the bed of a waterway that releases a continuous stream of air bubbles. The rising plume entrains water and creates a vertical circulation that acts as a hydraulic barrier — for example, to limit salt intrusion through a lock, hold back sediment, or deter fish from entering a pump inlet.
In D-Flow FM, a bubble screen is declared in the new-format external forcings file
(ExtForceFileNew) as a [BubbleScreen] block. HYDROLIB-core exposes it as the
BubbleScreen model.
BubbleScreen is a new-format-only construct. There is no legacy
QUANTITY=…form for it, soextforce-convertdoes not produce or consumeBubbleScreenblocks.
Anatomy of a [BubbleScreen] block¶
Every block has four required pieces of information:
| Key | Type | Meaning |
|---|---|---|
id |
string | Unique identifier within the ext file |
| location | polyline | Where the screen sits, horizontally |
zLevel |
float | Depth of the nozzle row, in model vertical units |
discharge |
scalar / .bc filename / realtime |
Volumetric air-flow rate |
An optional name field gives a human-readable label.
The location can be specified in one of two equivalent ways:
1. Inline coordinates¶
The polyline is embedded directly in the ext file — you give the number of vertices and two arrays of coordinates.
[BubbleScreen]
id = bubbles1
numCoordinates = 4
xCoordinates = 450 450 550 550
yCoordinates = 550 650 650 550
zLevel = -5.0
discharge = bubble_discharge.bc
2. External polyline file¶
The polyline lives in a separate .pli file next to the ext file, and the block only
carries a filename reference.
[BubbleScreen]
id = bubbles1
locationFile = simple_bubbles.pli
zLevel = -5.0
discharge = bubble_discharge.bc
Both forms produce the same simulation. HYDROLIB-core preserves whichever form was read, so round-tripping an existing model does not silently rewrite it.
Exactly one of the two location styles must be present. A block with neither — or with mismatched
numCoordinatesvs. the actual coordinate list length — raises a validation error at load time.
Working with BubbleScreen in Python¶
Building a new block¶
from hydrolib.core.dflowfm.ext import BubbleScreen, ExtModel
screen = BubbleScreen(
id="bubbles1",
numcoordinates=4,
xcoordinates=[450.0, 450.0, 550.0, 550.0],
ycoordinates=[550.0, 650.0, 650.0, 550.0],
zlevel=-5.0,
discharge=1.0, # m3/s as a scalar; or a ForcingModel, or "realtime"
)
ext = ExtModel(bubblescreen=[screen])
ext.filepath = "forcings.ext"
ext.save()
Field names in Python are lowercased (xcoordinates, zlevel, …) but the Pydantic
aliases accept the CamelCase names from the INI file (xCoordinates, zLevel, …), so
both work when constructing a block from a dict.
Reading an existing ext file¶
from hydrolib.core.dflowfm.ext import ExtModel
# read the saved forcings.ext file saved above
ext = ExtModel("forcings.ext")
for screen in ext.bubblescreen:
print(screen.id, screen.zlevel, screen.discharge)
ExtModel.bubblescreen is a list; an ext file with no [BubbleScreen] blocks gives an
empty list, not None.
Using a .bc file for a time-varying discharge¶
discharge accepts three forms:
- a scalar
float(e.g.1.5m³/s, constant), - the literal string
"realtime"(the kernel supplies the value at run time), - a filename string or
ForcingModelpointing at a<name>.bcfile — HYDROLIB-core resolves it automatically.
The companion .bc file uses the quantity name bubblescreen_discharge, analogous to
sourcesink_discharge for source/sink blocks.
BubbleScreen vs. SourceSink¶
The two look similar — both are INI blocks with an id, a polyline/locationFile, and a
discharge — but they model different physics and have different field shapes:
BubbleScreen |
SourceSink |
|
|---|---|---|
| Models | Air-bubble curtain | Water / solute injection or extraction |
| Vertical placement | Single zLevel: float |
zSource and zSink, each scalar or 2-value range |
| Paired injector/extractor | No — nozzles are always sources of air | Yes — multi-point polyline pairs a source with a sink |
| Polyline carries z | No (plain .pli only) |
Yes — 3- or 5-column .pliz encodes vertical placement |
Legacy QUANTITY= form |
No — new format only | Yes: discharge_salinity_temperature_sorsin |
If your model previously used a SourceSink block to approximate a bubble screen, the
migration is straightforward: replace zSource with zLevel, drop any zSink, and
change the header to [BubbleScreen].
Validation behaviour¶
HYDROLIB-core's validator rules for a BubbleScreen block:
- Location specification is required. Either
locationFileor the tripletnumCoordinates+xCoordinates+yCoordinatesmust be present, otherwise the block raisesValueError. - Coordinate count consistency. When inline coordinates are used, both arrays must
have exactly
numCoordinatesentries. zLevelis required. UnlikeSourceSink.zSource,BubbleScreen.zLevelhas no default; omitting it raises aValidationError.dischargeis required. Same rule.
Known limitations¶
zLevelis currently a singlefloat. If a future kernel revision accepts a vertical range the waySourceSink.zSourcedoes, this field will need widening.
See also¶
BubbleScreen— API referenceSourceSink— sister block for water / solute sourcesExtModel— the new-format ext file model- External forcings file reference