You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 19 Next »

Unable to render {include} The included page could not be found.

Implementation steps

We will implement running of Sobek through a dll using the following approach:

Extend fortran code to allow for setting model parameters and data (ie "setvalues")
In C# the module wlacces implements running of sobek models that are defined in a file.

setvalues will be defined in new interface (not in iwlaccess !)
fortran c / code will implement methods in interface

General structure of the Deltshell - Sobeksim interface

The sobeksim interface now consists of the projects:

  1. DelftModelApi.Net
  2. delft_model_api
  3. delft_model_data

furthermore a module called GUI_communication is added to the project kernel_sobek_f

In DelftModelApi.Net the static class modelApi is defined. This class contains functions to transfer data from C# to the SOBEKSIM kernel. The functions in class modelApi are implemented in delft_model_api.dll. In module modelApi the exported functions of delft_model_api.dll are defined. The relevant data is stored in ModelGlobalData. ModelGlobalData uses derived types which are defined in ModelTypes and NetworkTypes. ModelTypes contains the run-time parameters and model state variables, whereas NetworkTypes contains the derived types to define a network. The module GUI_communication transfers the data from ModelGlobalData to the data structure of Sobeksim.

DelftModelApi.Net and GUI_Communication are described in the next subsections

DelftModelApi.Net

DelftModelApi.net contains the static class ModelApi. ModelApi in its turn contains functions to transfer data from C# to the SOBEKSIM kernel.
Available functions are:

Name

Description

setUsePluginData

Sets the flag for the computational kernel to use the modelapi

NetworkSetDimensions

Sets the dimensions of the network (number of branches, nodes, cross sections, ...

NetworkSetNode

Define a new node in the network

NetworkSetBranch

Define a new branch in the network

NetworkGetBranch

Get a branch

NetworkSetQBoundary

Set a Q-boundary at an end node of the network (limitation: at this time only constant boundary conditions are allowed)

NetworkSetHBoundary

Set an H-boundary at an end node of the network (limitation: at this time only constant boundary conditions are allowed)

NetworkSetTabCrossSection

Define a cross section in terms of widths with respect to height

NetworkSetCS

connect a cross section definition to a branch (limitation: Momentarily only one cross section per branch is allowed)

ModelInitialize

Start the SOBEK initialisation

ModelSetSimulationTimes

Set the simulation times for the model

ModelFinalize

Close/terminate the simulation

ModelGetCurrentTime

Gets the SOBEK current simulation time

ModelPerformTimeStep

Perform one time step

GUI_communication

In GUI_communication the datastructure of Sobeksim is filled. Since the initialisation of the arrays is performed at different locations in Sobeksim, there is a number of subroutines that perform a part of the initialisation, namely setValues, setValuesinMempool, getcsnam, setFlsData, setIds and setArrays.

Subroutine dumppool of GUI_Communication can be used for debugging purposes. Because dumppool writes the datastructure of sobeksim to file.

Examples

In this example a network with three branches is defined.

        [Test]
        public void RunABitLessSimpleModel()
        {
            int modelHandle = 0;
            int numSteps = 0;

            string workingDirectory = @"..\..\..\..\testdata\ModelApiTest\Simple\CMTWORK\";
            Environment.CurrentDirectory = workingDirectory;

            // set current directory to output so that it will be the only one place where sobeksim writes data
            // the directory for now already contains files produced by parsen.exe
            // format for date is YYYYMMDD and for time HHMMSS
            int startDate = 19960101;
            int startTime = 10000;
            int endDate = 19960102;
            int endtTime = 150000;

            // time steps are given in seconds
            int timeStep = 300;
            int outputTimeStep = 3600;
            ModelApi.ModelSetSimulationTimes(ref startDate, ref startTime, ref endDate, ref endtTime,
                ref timeStep, ref outputTimeStep);

            // Define the dimensions of the model. In terms of number of Branches, number of nodes and number of cross
            // sections
            int branchesCount = 3;
            int nodesCount = 4;
            int crossSectionsCount = 3;
            float deltaX = 10.0f;
            ModelApi.NetworkSetDimensions(ref branchesCount, ref nodesCount, ref crossSectionsCount, ref deltaX);

            // ----------------------------------------------------
            // set branch1, node1, node2, crs1, crs2, etc to model

            // A node has an ID, which must be a uniqe (key), a name (a description of the node) and coordinates, which 
            // define the location of the node. The coordinates are used to calculate the length of a branch
            string id = "1";
            string name = "  ";
            double[] coor = new double[2];
            coor[0] = -400;
            coor[1] = 0;
            ModelApi.NetworkSetNode(id, name, coor);
            id = "2";
            name = "  ";
            coor[0] = 200;
            coor[1] = 200;
            ModelApi.NetworkSetNode(id, name, coor);
            id = "3";
            name = "  ";
            coor[0] = 200;
            coor[1] = -200;
            ModelApi.NetworkSetNode(id, name, coor);
            id = "4";
            name = "  ";
            coor[0] = -9.967;
            coor[1] = 16.56;
            ModelApi.NetworkSetNode(id, name, coor);

            // Define the branches, using a from node and a to node. Length can be used to override 
            // the length, defined by the distance between  the fromNode and toNode. If length > 0,
            // this length is used.
            // With deltaX the A global value for the complete network is defined by DeltaX given in 
            id = "1";
            name = "";
            int fromNode = 1;
            int toNode = 4;
            deltaX = 0.0f;
            float length = 0;
            ModelApi.NetworkSetBranch(id, name, ref fromNode, ref toNode, ref length, ref deltaX);
            id = "2";
            name = "";
            fromNode = 4;
            toNode = 2;
            deltaX = 0.0f;
            length = 0;
            ModelApi.NetworkSetBranch(id, name, ref fromNode, ref toNode, ref length, ref deltaX);
            id = "3";
            name = "";
            fromNode = 4;
            toNode = 3;
            deltaX = 0.0f;
            length = 0;
            ModelApi.NetworkSetBranch(id, name, ref fromNode, ref toNode, ref length, ref deltaX);

            // Set boundary conditions. Boundary conditions may only be set on nodes, that have only
            // one connection. NodeId is not the name of the id, but the sequence number, id = 1 is 
            // the first node that is defined by the call NetworkSetNode.
            int nodeId = 1;
            double value = 2.0;
            ModelApi.NetworkSetQBoundary(ref nodeId, ref value);
            nodeId = 2;
            ModelApi.NetworkSetHBoundary(ref nodeId, ref value);
            nodeId = 3;
            value = 1.9;
            ModelApi.NetworkSetHBoundary(ref nodeId, ref value);

            // Define a cross section with two levels
            int levelCount = 2;
            double [] levels = new double[levelCount];
            levels[0] = 0.0;
            levels[1] = 5.0;
            double [] flowWidth = new double[levelCount];
            flowWidth[0] = 5.0;
            flowWidth[1] = 5.0;
            double [] storWidth = new double[levelCount];
            storWidth[0] = 6.0;
            storWidth[1] = 10.0;
            int iref = ModelApi.NetworkSetTabCrossSection(ref levelCount, levels, flowWidth, storWidth);

            // Connect the cross section to the various branches
            int branch = 1;
            double location= 196.086;
            double bottomLevel = 0;
            double surfaceLevel = 2.0;
            int bedFrictionType = (int) Friction.ChezyConstant;
            int groundFrictionType = (int) Friction.WhiteColebrook;
            double bedFriction = 45.0;
            double groundFriction = 0.003;
            int storageType = 0;
            ModelApi.NetworkSetCS(ref branch, ref location, ref iref, ref bottomLevel, ref surfaceLevel,
                  ref bedFrictionType, ref bedFriction, ref groundFrictionType,
                  ref groundFriction, ref storageType);
            branch = 2;
            location = 139.364;
            bedFrictionType = (int)Friction.Mannings;
            bedFriction = 0.025;
            ModelApi.NetworkSetCS(ref branch, ref location, ref iref, ref bottomLevel, ref surfaceLevel,
                  ref bedFrictionType, ref bedFriction, ref groundFrictionType,
                  ref groundFriction, ref storageType);
            branch = 3;
            location = 160.33;
            bedFrictionType = (int)Friction.WhiteColebrook;
            bedFriction = 0.2;
            ModelApi.NetworkSetCS(ref branch, ref location, ref iref, ref bottomLevel, ref surfaceLevel,
                  ref bedFrictionType, ref bedFriction, ref groundFrictionType,
                  ref groundFriction, ref storageType);

            
            // Initialize SOBEKSIM
            ModelApi.ModelInitialize(ref modelHandle, ref numSteps);
            for (int step = 0; step <= numSteps; step++)
            {   
                // Perform one time step
                ModelApi.ModelPerformTimeStep(ref modelHandle, ref step);
            }
            // End the simulation
            ModelApi.ModelFinalize();
        }

Notes

  1. Sobek OpenMI module: 
    Useful function for initialising and performing one or more timesteps and finalizing.
    •  'SE_OpenMI.f90' communicates with OEM buffer.
    • 'SE_OpenMI.f90' has calls to module OMI_CF_control in (OMI_CF_control.f90), which in turn calls directly sobeksim subroutines
  1. Present SOBEK reads nefis files during initialisation (using m_nefisinput.mod). Nefis is used in subroutines: read_initial_values_strpar_etc, soedef, sogetm and wetcrs.

SOBEK variables read from NEFIS

      integer                         :: nnode         ! nr of sobek nodes
      integer                         :: nbran         ! nr of branches
      integer                         :: nstdb
      integer                         :: nstru         ! number of structures
      integer                         :: ntrigr        ! number of triggers
      integer                         :: ncontr        ! number of controllers
      integer                         :: ntcrel        ! number of trigger-controller relations
      integer                         :: ncsrel        ! number of controller-structure relations
      integer                         :: nqlat         ! number of lateral inflows
      integer                         :: ngrid         ! nr of sobek points
      integer                         :: nboun         ! number of open boundaries
      integer                         :: nhstat        ! number of 1D waterlevel boundaries
      integer                         :: nqstat        ! number of 1D discharge boundaries
      integer                         :: ntabm
      integer                         :: maxtab
      integer                         :: maxlev
      integer                         :: ncross
      integer                         :: nevents
      integer                         :: mxstrpar      ! leading dimension of strpar
      integer                         :: mxistrtyp     ! leading dimension of istrtyp
      integer                         :: mxstrmu       !
      integer                         :: mxcross
      integer                         :: mxqltpar
      integer                         :: mxtriger      ! leading dimension of triger
      integer                         :: mxcontrl      ! leading dimension of contrl
      integer                         :: mxconhis = 5  ! leading dimension of conhis
      integer                         :: mxconhis      ! leading dimension of conhis
      integer                         :: mxtrcnrl      ! leading dimension of trcnrl
      integer                         :: mxcnstrl      ! leading dimension of cnstrl = 2
      integer                         :: mxengpar      ! dimension of engpar
      integer                         :: mxbranch      ! lead dim of branch
      integer                         :: nupt           
      integer                         :: msect
      integer                         :: lcnvmax

      real   , allocatable            :: strpar (:,:)  ! structure parameters          (mxstrpar,nstru)
      real   , allocatable            :: strmu  (:,:)  ! structure mu                  (mxstrmu,nstru)
      integer, allocatable            :: istrtyp(:,:)  ! structure type                (mxistrtyp,nstru)
      character(len=40), allocatable  :: contrnam(:)   ! names of controllers          (ncontr)
      character(len=40), allocatable  :: trigrnam(:)   ! names of triggers             (ntrigr)
      character(len=40), allocatable  :: qlatnm(:)     ! ids of qlats                  (nqlat)
      real   , allocatable            :: qlat  (:)     ! lateral inflow                (nqlat)
      real   , allocatable            :: qltpar(:,:)   ! lateral inflow parameters     (mxqltpar,nqlat)
      integer, allocatable            :: node(:,:)     ! sobek node administration     (nnode)
      integer, allocatable            :: branch(:,:)   ! sobek branch admin            (mxbranch,nbran)
      integer, allocatable            :: triger(:,:)   ! trigger data                  (mxtriger,ntrigr)
      real   , allocatable            :: contrl(:,:)   ! controller data               (mxcontrl,ncontr)
      integer, allocatable            :: trcnrl(:,:)   ! trigger controller relation   (mxtrcnrl,ntcrel)
      integer, allocatable            :: cnstrl(:,:)   ! controller structure relation (mxcnstrl,ncsrel)
      integer, allocatable            :: hbdpar(:,:)   ! integer parameters (3,*), 1=?, 2=iopt, 3=itab (3,nhstat)
      integer, allocatable            :: qbdpar(:,:)   ! integer parameters (3,*), 1=?, 2=iopt, 3=itab (3,nqstat)
      real   , allocatable            :: engpar(:)     ! Engelund-Hansen parameters    (mxengpar)
      real   , allocatable            :: hpack(:)      ! s0 voor sobek points          (ngrid)
      real   , allocatable            :: qpack(:)      ! q  voor sobek points          (ngrid)
      double precision, allocatable   :: xycoor(:,:)   ! (2,ngrid) x,y coordinates for sobek points (2,ngrid)
      integer,  allocatable           :: nlevu   (:)   !                               (nupt)
      real,     allocatable           :: chan_hu (:,:) !                               (ngrid)
      real,     allocatable           :: chan_af (:,:,:)    !                          (nupt,lcnvmax,msect)
      real,     allocatable           :: chan_wf (:,:,:)    !                          (nupt,lcnvmax,msect)
      real,     allocatable           :: chan_pf (:,:,:)    !                          (nupt,lcnvmax,msect)
      real,     allocatable           :: chan_co (:,:,:)    !                          (nupt,lcnvmax,msect)
      real,     allocatable           :: chan_cn (:,:,:)    !                          (nupt,lcnvmax,msect)
      real,     allocatable           :: chan_cz1(:,:,:)    !                          (nupt,lcnvmax,msect)
      real,     allocatable           :: chan_cz2(:,:,:)    !                          (nupt,lcnvmax,msect)
      integer, allocatable            :: nlevh   (:)        !                          (nupt,lcnvmax,msect)
      real,    allocatable            :: chan_hh (:,:)      !                          (ngrid,lcnvmax)
      real,    allocatable            :: chan_at (:,:)      !                          (ngrid,lcnvmax)
      real,    allocatable            :: chan_wt (:,:)      !                          (ngrid,lcnvmax)
      character(len=CharLen ), allocatable, save :: nodenm                 !           (nnode)
      character(len=CharLen ), allocatable, save :: gridnnm                !           (ngrid)

Q1: What is relation trigger-contoller, contoller-structure

  integer, allocatable            :: trcnrl(:,:)   ! trigger controller relation   (mxtrcnrl,ntcrel)
  integer, allocatable            :: cnstrl(:,:)   ! controller structure relation (mxcnstrl,ncsrel)

Q2: Engelund-Hansen parameters - isn't it morphology? is it required for flow

Q3: Give definition of a structure, controller, trigger and give full list of their parameter names.

Q4: Cross-section type currently of two types - describe them

  • free form
  • wetted-perimeter formula
  • No labels