You are not logged in. Click here to log in.

Application Lifecycle Management

Search In Project

Search inClear

Tags:  not added yet

OMS Modeling (DSL) Reference

Introduction

A domain specific language (DSL) is a mini-language focused on specific tasks within a problem domain, in thsi workshop case creating crop simulation models. The OMS DSL is based on Groovy, an "agile and dynamic language for the Java Virtual Machine." Trained OMS modelers understand the simplified OMS DSL, and do not have to know the more comprehensive general purpose Groovy.

The OMS model development framework provides a DSL for:

  • Performing unit tests on OMS science components
  • Connecting system and science components to build a model
  • Parameterizing and provisioning data for a model simultation
  • Running a model simulation with logging, statistics, and output visualization
  • Calibrating a model
  • Performing sensitivity and uncertainty analysis on a model

The OMS DSL contains elements and sub-elements, which are used to create simulation files. The term simulation is generic, applying to unit tests, basic simulations, calibrations, and analyses. All simulation files have the same formal structure:

// comment
<element>(<key:value>, <key:value>, ...) {
<element>(<properties like above>) {
// sub-elements..
}
<element>(<properties like above>) {
// sub-elements or just elements with value
<element> <value>
}
<element>(<properties like above>)
<element> {
<element ..
}
// more elements and subelements
}

Some useful things to know in general about the OMS DSL:

  • Each simulation file has one root element establishing the type of simulation.
  • Comments can be single lined ('// ...') or can span multiple lines ("/* ... */")
  • Elements can have properties in parentheses after the element name. If there are no properties the parentheses can be omitted.
  • Properties are a list of comma separated tuple of <key:value> pairs.
  • Multiple properties are separated by comma, and all properties are embedded in parentheses.
  • Elements can have sub elements within curly brackets. If there are no sub-elements, the curly brackets can be omitted.
  • Elements can have just a value following the element name separated by space.

Complete List of DSL Elements for Basic Simulation and Unit Testing

Here is a complete listing of DSL root elements and sub-elements for the simulation types sim, tests, and luca. Click on the DSL element or sub-elements in the table below to view their specification and examples of use.

Simulation Sub-Element 1 Sub-Element 2 Sub-Element 3 Simulation Sub-Element 1 Sub-Element 2
sim{} build tests{} resource
model{} components{} model{} parameter{}
connect{} logging{}
feedback{} test
parameter{}
logging{}
resource
outputstrategy
output
summary
efficiency
analysis{} timeseries{} x
y
calc{}
scatter{} x
y
calc{}
flowduration{} y
calc{}

DSL Elements for Component Unit Tests

DSL Element - tests

OMS modelers can perform unit tests on the science components they develop using the tests DSL element. The root element tests defines a set of tests for a single component. It has three first level sub-elements as shown in the following table. Click on the DSL element or sub-elements in the following table to view their specification and examples of use.

Root Element Level 1 Sub-Element Level 2 Sub-Element Occurences Allowed
tests{} one per test
resource one to many
model{} exactly one, required
parameter{} zero to many
logging{} one per test
test one or many

OMS creates a tests object, which has a property name to identify it and its purpose.

Property

Property Name Description Type Occurences Allowed
name name of the test set string zero or one, optional

Example

//create the unit test object
tests(name:"CSMLite Plant Growth Unit Test") {
     //add sub-elements...
     }

Unit testing is the concept of automated verification of individual software units. In OMS such units are components,the basic building blocks of simulation models. Unit testing support is part of the core OMS framework. It can be set up easily to efficiently test and verify individual components. Best model developing practice should embrace unit testing by complementing a scientific component with sufficient tests, hence assuring of its proper working and creating confidence.

Some fundamental rules for components tests apply and are consistent with general purpose testing frameworks. Tests are comprised of individual test cases, which are independent from each other. Each test case can run on its own.

The OMS unit testing implementation closely resembles concepts and strategies of related frameworks, such as JUnit or TestNG. This allows easy transitioning into OMS component testing if the modeler has previous unit testing knowledge.

The tests{} element supports the setup of many test cases for an individual component or whole model. Each individual test case for a component is described with the test element. Since components all adhere to a common layout, testing is straightforward. For a single test case the component is populated with data for all Input fields (@In), the execution method gets invoked (@Execute), and finally the produced output fields (@Out) can be checked. There are different ways to generate input, perform test execution and verify proper output. The oms3.prj.csm project contains several unit testing examples.

DSL Elements for Basic Model Simulation

DSL Element - sim{}

A basic simulation is the standard method to setup and run a model. The root DSL element is sim, and a sim file may contain instances of six sub-elements, as shown the following table. Click on the DSL element or sub-elements in the following table to view their specifications and examples of use.

Root Element Sub-Element Occurences Allowed
sim{}
build zero or one, optional
model{} exactly one, required
outputstrategy zero or one, optional
resource one or many
efficiency zero or many
output zero or one, optional
summary zero or many
analysis{} zero or many

OMS creates a sim object, which has a property name to identify it and its purpose.

Property

Property Name Description Type Occurences Allowed
name Name of the simulation string zero or one, optional

Example

//create the simulation object
sim(name:"CSMLite Basic Simulation for Workshop") {
     //add sub-elements...
     }

The oms3.prj.csm project provides simulation examples showing the use of the relevant DSL elements and sub-elements.

DSL Elements for Analysis (Calibration)

DSL Element - luca

The simulation element luca does model calibration via a shuffled complex evolution (SCE) process. (LUCA is an acronym for 'Let Us CAlibrate', developed originally by the U.S. Geological Survey). Click on the DSL element or sub-elements in the following table to view their specifications and examples of use.

Simulation Sub-Element 1 Sub-Element 2
luca{} model{} parameter{}
resource
outputstrategy
output
calibration_start
rounds
step{} parameter{}
objfunc{}

Example Calibration


luca(name: "EFC-luca") {

    // define output strategy: output base dir and
    // the strategy NUMBERED|SIMPLE|DATE
    outputstrategy(dir: "$oms_prj/output", scheme:SIMPLE)

    // define model for calibration
    model(classname:"model.PrmsDdJh") {
        // parameter
        parameter (file:"$oms_prj/data/params_lucatest.csv") {
            inputFile  "$oms_prj/data/data_lucatest.csv"
            outFile    "out.csv"
            sumFile    "basinsum.csv"
            out        "summary.txt"

            startTime "1980-10-01"
            endTime   "1984-09-30"
        }
    }

     output(time:"date", vars:"basin_cfs,runoff[0]", 
                 fformat="7.3f", file:"out1.csv")

//   output(time:"date", vars:"basin_cfs,", 
//                fformat="7.3f", file:"out1.csv")

    calibration_start "1981-10-01"         // calibration start date
    rounds 2                               // calibration rounds, default 1

    // step definitions
    step {                     
        parameter {
            jh_coef(lower:0.001, upper:0.02, strategy:MEAN)
        }
    
        objfunc(method:ABSDIF, timestep:DAILY) {
            simulated(file:"out1.csv", table:"EFC-luca", column:"basin_cfs")
            observed(file:"$oms_prj/data/data_lucatest.csv", table:"obs", 
                         column:"runoff[0]")
        }
        // can add more
    }

    step {                    
        parameter {
        //  ssrcoef_sq(lower:0.001, upper:0.4, strategy:MEAN)
            soil2gw_max(lower:0.001, upper:0.4, strategy:MEAN)
        }

        objfunc(method:ABSDIF, timestep:DAILY)  {        
           simulated(file:"out1.csv", table:"EFC-luca", column:"basin_cfs")
           observed(file:"$oms_prj/data/data_lucatest.csv", table:"obs",
                        column:"runoff[0]")
        }     
    }
}