scrollbar |
---|
Latest update June 10, 2012: first version of this page.
Delwaq is the generic Deltares finite volume water quality and ecology solver that has been linked to 1D network models (like Deltares' own SOBEK model) as well as both structured and unstructured 2D and 3D models (like Delft3D, Telemac, ROMS and Untrim). The program has been able to flexibly couple to all these hydrodynamic solvers without any major architecture redesign for over 20 year by strict separation of geometry, topology, quantities and process formulations. In fact, delwaq itself doesn't know anything about the model geometry; although this has been a major advantage, the lack of geometry data on the delwaq binary output files is starting to limit the wider uptake and hence we're looking at options to enable geometry data on the output file without limiting bothering the computational core with irrelevant data on geometric differences between the various hydrodynamic models. A common generic geometric description would be best such that delwaq only has to call a single routine to copy it to the output file. For this purpose we have selected the new proposal for the CF standard CF unstructured grid proposal. What information do we need from the flow module?
...
For the generation of the boundary conditions we'll need one additional bit of information from the flow model, namely the names of all open boundaries as well as their location and (negative) boundary segment numbers associated them.Example of a netCDF file:
Below you will find a first example of a netCDF file with all information that delwaq graphical user interface needs for a simple case with volumes defined on the faces of the grid (e.g. Delft3D, D-FLOW Flexible Mesh, ROMS, Untrim).
New items in this listing are the aggregation tables for volumes and exchanges, the from-to pointer table, and the boundary names and indices. These items are to be identified by means of the new attribute delwaq_role
. This attribute has been introduced in agreement with the cf_role
attribute for quantities that probably can't be standardized beyond the scope of delwaq.
delwaq_role | description |
---|---|
segment_aggregation_table | For every flow volume the segment number of the corresponding delwaq schematisation. Note that this array may have length nNodes (for node centred flow codes like CG finite element codes like Telemac) or nFaces (for face centred flow codes like D-Flow Flexible Mesh and Untrim). This table indicates which grid cells are included in the delwaq computation and which grid cells have been merged. It does not indicate numbers of open boundary segments. |
exchange_aggregation_table | For every flow volume interface the exchange number of the corresponding delwaq schematisation; generally it will have length nEdges. This table indicates where the various exchanges are located on the grid for both internal and open boundary exchanges. Although it may be used to derive the associated from and to segment numbers, it does not indicate the (from/to) order or does it indicate the numbers of the open boundary segments. This table may be derived using the topological information of the flow grid, the segment_aggregation_table and the from_to_segment_table. |
from_to_segment_table | This table is size nExchanges x 2: for every delwaq exchange it indicates the from (1st value) and to (2nd value) segment numbers. This table may be expanded to include "from-1" and "to+1" segment indices as well. Note that this table implicitly defines positive flow direction for all exchanges as well as the open boundary segment numbers. |
boundary_name | For every open boundary its name. Note that a boundary is defined as one or more exchanges. |
boundary_exchange_index | For every open boundary the numbers (and order) of the exchanges that are associated with that boundary. |
Sketch of the flow (left) and delwaq (right) topologies used in the example below:
Code Block |
---|
dimensions:
nNodes = 12 ;
nEdges = 21 ;
nFaces = 10 ;
maxNumNodesPerFace = 5 ;
nSegments = 5 ;
nExchanges = 12 ;
nBoundaries = 4 ;
maxLenBndName = 5 ;
maxNumExchangesPerBnd = 2 ;
Two = 2 ;
variables:
// Mesh topology
integer Mesh ;
Mesh:cf_role = "mesh_topology" ;
Mesh:long_name = "Topology data of 2D unstructured mesh" ;
Mesh:dimension = 2 ;
Mesh:node_coordinates = "Mesh_node_x Mesh_node_y" ;
Mesh:face_node_connectivity = "Mesh_face_nodes" ;
Mesh:edge_node_connectivity = "Mesh_edge_nodes" ; // attribute required if variables will be defined on edges
Mesh:edge_coordinates = "Mesh_edge_x Mesh_edge_y" ; // optional attribute (requires edge_node_connectivity)
Mesh:face_coordinates = "Mesh_face_x Mesh_face_y" ; // optional attribute
Mesh:face_edge_connectivity = "Mesh_face_edges" ; // optional attribute (requires edge_node_connectivity)
Mesh:face_face_connectivity = "Mesh_face_links" ; // optional attribute
integer Mesh_face_nodes(nFaces, maxNumNodesPerFace) ;
Mesh_face_nodes:cf_role = "face_node_connectivity" ;
Mesh_face_nodes:long_name = "Maps every face to its corner nodes." ;
Mesh_face_nodes:_FillValue = 999999 ;
Mesh_face_nodes:start_index = 1 ;
integer Mesh_edge_nodes(nEdges, Two) ;
Mesh_edge_nodes:cf_role = "edge_node_connectivity" ;
Mesh_edge_nodes:long_name = "Maps every edge to the two nodes that it connects." ;
Mesh_edge_nodes:start_index = 1 ;
// Mesh node coordinates
double Mesh_node_x(nNodes) ;
Mesh_node_x:standard_name = "longitude" ;
Mesh_node_x:long_name = "Longitude of 2D mesh nodes." ;
Mesh_node_x:units = "degrees_east" ;
double Mesh_node_y(nNodes) ;
Mesh_node_y:standard_name = "latitude" ;
Mesh_node_y:long_name = "Latitude of 2D mesh nodes." ;
Mesh_node_y:units = "degrees_north" ;
// Optional mesh face and edge coordinate variables
double Mesh_face_x(nFaces) ;
Mesh_face_x:standard_name = "longitude" ;
Mesh_face_x:long_name = "Characteristics longitude of 2D mesh face." ;
Mesh_face_x:units = "degrees_east" ;
Mesh_face_x:bounds = "Mesh_face_xbnds" ;
double Mesh_face_y(nFaces) ;
Mesh_face_y:standard_name = "latitude" ;
Mesh_face_y:long_name = "Characteristics latitude of 2D mesh face." ;
Mesh_face_y:units = "degrees_north" ;
Mesh_face_y:bounds = "Mesh_face_ybnds" ;
double Mesh_face_xbnds(nFaces,maxNumNodesPerFace) ;
Mesh_face_xbnds:standard_name = "longitude" ;
Mesh_face_xbnds:long_name = "Longitude bounds of 2D mesh face (i.e. corner coordinates)." ;
Mesh_face_xbnds:units = "degrees_east" ;
Mesh_face_xbnds:_FillValue = 9.9692099683868690E36;
double Mesh_face_ybnds(nFaces,maxNumNodesPerFace) ;
Mesh_face_ybnds:standard_name = "latitude" ;
Mesh_face_ybnds:long_name = "Latitude bounds of 2D mesh face (i.e. corner coordinates)." ;
Mesh_face_ybnds:units = "degrees_north" ;
Mesh_face_ybnds:_FillValue = 9.9692099683868690E36;
double Mesh_edge_x(nEdges) ;
Mesh_edge_x:standard_name = "longitude" ;
Mesh_edge_x:long_name = "Characteristic longitude of 2D mesh edge (e.g. midpoint of the edge)." ;
Mesh_edge_x:units = "degrees_east" ;
double Mesh_edge_y(nEdges) ;
Mesh_edge_y:standard_name = "latitude" ;
Mesh_edge_y:long_name = "Characteristic latitude of 2D mesh edge (e.g. midpoint of the edge)." ;
Mesh_edge_y:units = "degrees_north" ;
// bounds variables for edges skipped
// Aggregation tables
integer Dlwq_volaggr(nFaces) ;
Dlwq_volaggr:delwaq_role = "segment_aggregation_table" ;
Dlwq_volaggr:long_name = "delwaq segment number for each face (flow volume)" ;
Dlwq_volaggr:mesh = "Mesh" ;
Dlwq_volaggr:location = "face" ;
Dlwq_volaggr:coordinates = "Mesh_face_x Mesh_face_y" ;
Dlwq_volaggr:_FillValue = 0;
integer Dlwq_flxaggr(nEdges) ;
Dlwq_flxaggr:delwaq_role = "exchange_aggregation_table" ;
Dlwq_flxaggr:long_name = "delwaq exchange number for each edge (flow boundary)" ;
Dlwq_flxaggr:mesh = "Mesh" ;
Dlwq_flxaggr:location = "edge" ;
Dlwq_flxaggr:coordinates = "Mesh_edge_x Mesh_edge_y" ;
Dlwq_flxaggr:_FillValue = 0;
integer Dlwq_fromto(nExchanges,Two) ;
Dlwq_fromto:delwaq_role = "from_to_segment_table" ;
Dlwq_fromto:long_name = "delwaq from/to table" ;
// Boundary information
char Bnd_name(nBoundaries, maxLenBndName) ;
Bnd_name:delwaq_role = "boundary_name" ;
Bnd_name:long_name = "boundary name for the delwaq user interface" ;
char Bnd_exch(nBoundaries, maxNumExchangesPerBnd) ;
Bnd_exch:delwaq_role = "boundary_exchange_index" ;
Bnd_exch:long_name = "indices of exchanges associated with the boundary" ;
Bnd_exch:_FillValue = 0;
data:
Mesh = 0 ; // dummy
Mesh_face_nodes =
1, 2, 5, 999999, 999999,
1, 5, 8, 999999, 999999,
5, 9, 8, 999999, 999999,
5, 6, 9, 999999, 999999,
2, 12, 5, 999999, 999999,
3, 4, 7, 6, 12,
6, 10, 9, 999999, 999999,
6, 7, 11, 10, 999999,
5, 12, 6, 999999, 999999,
2, 3, 12, 999999, 999999 ;
Mesh_edge_nodes =
1, 2,
2, 3,
3, 4,
1, 5,
2, 5,
5, 6,
6, 12,
6, 8,
4, 7,
1, 8,
5, 8,
5, 9,
6, 9,
6, 10,
7, 11,
8, 9,
9, 10,
10, 11,
2, 12,
5, 12,
3, 12 ;
Mesh_node_x = ... ; // data skipped
Mesh_node_y = ... ; // data skipped
Mesh_face_x = ... ; // data skipped
Mesh_face_y = ... ; // data skipped
Mesh_face_xbnds = ... ; // data skipped
Mesh_face_ybnds = ... ; // data skipped
Mesh_edge_x = ... ; // data skipped
Mesh_edge_y = ... ; // data skipped
Dlwq_volaggr =
1, 2, 2, 3, 1, 5, 3, 4, 1, 1 ;
Dlwq_flxaggr =
1, 0, 2, 3, 0, 0, 4, 5, 6, 7, 0, 8, 0, 10, 11, 0, 9, 12, 0, 0, 4 ;
Dlwq_fromto =
-1, 1,
-4, 5,
1, 2,
1, 5,
4, 5,
5, -6,
-2, 2,
2, 3,
-3, 9,
3, 4,
4, -7,
-5, 4 ;
Bnd_name =
"west ",
"north",
"east ",
"south" ;
Bnd_exch =
1, 7,
2, 0,
6, 11,
9, 12 ;
|
This data file may or may not contain the volume and flux data needed for the delwaq computational core
Code Block |
---|
dimensions:
timeVol = 100 ; //nTimeSteps for volumes
timeFlx = 99 ; //nTimeSteps for exchanges
variables:
// Volume and flux data on original flow grid
double Flow_volumes(timeVol, nFaces) ;
Flow_volumes:long_name = "volumes" ;
Flow_volumes:units = "m3" ;
Flow_volumes:mesh = "Mesh" ;
Flow_volumes:location = "face" ;
Flow_volumes:coordinates = "Mesh_face_x Mesh_face_y" ;
double Flow_fluxes(timeFlx, nEdges) ;
Flow_fluxes:long_name = "flux across edge" ;
Flow_fluxes:units = "m3 s-1" ;
Flow_fluxes:mesh = "Mesh"
Flow_fluxes:location = "edge" ;
Flow_fluxes:coordinates = "Mesh_edge_x Mesh_edge_y" ;
// or aggrgated data on delwaq topology
double Dlwq_volumes(timeVol, nSegments) ;
Dlwq_volumes:long_name = "volumes of segments" ;
Dlwq_volumes:units = "m3" ;
double Dlwq_fluxes(timeFlx, nExchanges) ;
Dlwq_fluxes:long_name = "exchanges between segments" ;
Dlwq_fluxes:units = "m3 s-1" ;
data:
Flow_volumes = ... ; // data skipped
Flow_fluxes = ... ; // data skipped
|