Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migration of unmigrated content due to installation of a new plugin

...

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:

Image Added

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