As part of the Muk3D Simulation module, a link to GoldSim is provided.
This tutorial shows a very basic linkage between Muk3D and GoldSim. It requires Muk3D v2019.4.1 or higher to run. Download the example project for the GoldSim tutorials here.
This tutorial also requires GoldSim, if you want to create the model from scratch. If you don't have GoldSim, you can still follow along for most of the tutorial using the GoldSim player and the player file (model.gsp in the project directory).
It is assumed that users are familiar with GoldSim.
Open the Muk3D project and set base/Storage_curve as the working directory.
Defining the interface
In this step we'll define the GoldSim interface. This means specifying the inputs and outputs for the interface. Run the command Simulation/Define GoldSim interface.
|Model name||Simple_pond||The name of the GoldSim interface file to create.|
|Length||1||The length of the data array to get. For Double types, this should be 1, but if you're expecting a vector from GoldSim, then this would be the length of the vector.|
|Type||Double||A single double precision number.|
|Name||Pond volume||What the data represents.|
Switch to the Outputs tab.
|Length (row 1)||1||The length of the array to return. If the type is Double, then this should be 1.|
|Length (row 2)||1|
|Type (row 1)||Double||The data type to return.|
|Type (row 2)||Double|
|Name (row 1)||Pond_elevation||What the data represents.|
|Name (row 2)||Surface_area|
Hit OK and the definition file will be created in the working directory. The file will be called simple_pond.gs_definition.
Creating the GoldSim project
The next step is to create the GoldSim project files. This currently means unzipping some required files into the working directory. Run the command Simulation/Create GoldSim project.
The files created are:
- GoldSimDLL - directory containing the GoldSim interface files.
- GoldSim_model_definition.pdf - Information about the interface which helps you set up the DLL in GoldSim.
- model.gsm - an empty GoldSim model.
- Simple_pond.py - the skeleton of the GoldSim interface in Python.
About the GoldSim script
The boilerplate script created is shown below. There is a main class called GSMacro which has several methods that the user can override. The primary one will be the execute method, which runs code each time GoldSim calls the model. Others are:
- setup: Called when a GoldSim realization is initialized.
- get_input_data: Called at the start of the entire simulation and allows for user entered data to be gathered.
- cleanup: Called at the end of each realization.
- get_test_inputs: Can be used to debug the script without having to run GoldSim each time.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
class GSMacro(GoldSimFunction): """ """ def setup(self, user_parameters): # called when the GoldSim each GoldSim realisation is initialised # initialise any global variables here. # user_parameters is a dict of values collected from the user in the # function get_input_data(). Empty if no data was gathered # from the user. pass def get_input_data(self, form): # shows a form to get input data from a user. # Form will only be shown if return value is True # form.add_file('My file', default_value='something', select_existing=True, filters=['*.mgrid', '*.mcurve']) # form.add_int('My integer', default_value=1) # form.add_float('My float', default_value=1.2) return False def execute(self, inputs, user_parameters): # called at each timestep. Goldsim inputs are contained in the # inputs variable and is a list. # must return Outputs Pond_volume = inputs Outputs =  # Outputs = Pond_elevation # Outputs = Surface_area # This must be the return value. return Outputs def cleanup(self, user_parameters): # executed at the end of the realization or the end of the model run. pass def get_test_inputs(self): # return a time series of inputs. Inputs =  # e.g. # TimeStep1 = [1,2,3,4,5] # Inputs.append(TimeStep1) # TimeStep2 = [4,5,6,4,4] # Inputs.append(TimeStep2) return Inputs
Setting up the GoldSim model
|If you don't have GoldSim and want to use the GoldSim player file, skip this section.|
Now we'll set up a simple GoldSim project to work with. This example is going to use a single Stochastic element that will generate a random pond volume on each day of the simulation. Add a new Stochastic element and call it Pond_volume. For the mode, check the Resampled option and click the Resample... button.
Since we want to resample it each timestep set the triggering type to be On Changed. Set the Trigger Definition to be etime (elapsed time). This will force the element to be resampled each timestep.
For this example we'll use a Uniform distribution, between a range of 1 and 2 million m3.
Add a time history result so we can see the Pond_volume.
To link to Muk3D, we need to add an External element. The DLL path needs to point to the Muk3DInterface.dll file, which is in the GoldSimDLL directory. Open the file GoldSim_model_definition.pdf and this will tell you what some of the fields on this form should be. Set the Function name to be Function0, and make sure the option Run in separate process check box is checked.
Select the interface tab and add a new input called Pond_volume, linking to the output of the Stochastic element Pond_volume.
Add 2 new outputs for Pond_elevation and Surface_area.
Finally, add a new Time History element to show the Pond_elevation and Surface_area.
This is what the final model should look like.
The final step is to change the duration of the simulation. Open the simulation settings and set the Duration to 10 days.
Testing the script
|If you don't have GoldSim and want to use the GoldSim player file, open the model.gsp file now.|
Now that the GoldSim model has been created, we can test the link. Just so we can see what's going on, we'll print the inputs (which is a Python list), and add some dummy outputs.
Start the GoldSim server in Muk3D by running Simulation/Start GoldSim server. You'll see a blue bar in the lower right indicating that the server is running.
In GoldSim, start the simulation.
As the GoldSim model is running, you will see the input value printed to the Output window in Muk3D.
Opening the Pond_results history element will show the return values for the pond elevation and surface area.
|If the simulation doesn't appear to run, make sure that the GoldSim server has been started in Muk3D. If it hasn't, GoldSim will show an error message saying that it either cant contact the server or an initialization error.|
Coding the execute method
Now its time to make the script do something useful by populating the execute method with some code. The easiest way to create code for a GoldSim script is to record a macro, going through the steps needed, and then copy-paste into the GoldSim script.
- Load the file ../../grid+dam.mgrid
- Run the command Create pond surface for volume. Set the pond volume to be 1,000,000 m3 and max pond elevation of 399m.
- Select the pond layer and run View/Unload current layer.
- Stop recording the macro using Scripts/End macro recording.
Open the recorded macro in the text editor. First step is to copy the import at the top of the file. The function set_active_layer is used to set the active layer in the Scene manager so that the selected layer can be removed later on.
In the setup method, copy the code that opens the base grid.
In the execute method, copy the code that creates the pond surface based on the volume. Set the pond_volume keyword argument to the Pond_volume variable. In the call to Unload current layer, set the dont_ask argument to be True. This will stop the script bugging the user each time the pond surface is removed.
Finally, we need to set the correct values for Pond elevation and Surface area. These are contained in the variable result, returned from the Create pond surface for volume function call. Printing the result variable shows that this value is a Python dictionary with the entries for surface_area and elevation.
Remove the lines where the Outputs list is populated with dummy data. Then after the call to Create pond surface for volume append the pond elevation (accessed as result['elevation']) and surface area (accessed as result['surface_area']) to the Outputs list.
Save the script and run the simulation in GoldSim.
Letting the user select the base grid
In the setup method, the grid used in the model is hardwired. We can create a simple user interface to allow a user to select the base grid to use for the modelling. The interface can be created in the get_input_data method. In this case, we can uncomment the line that adds a file field to the form.
Also make sure to set the return value to True so that the form is shown.
Next, in the setup method, we substitute our grid in the load function. This is accessed from the user_parameters dictionary and accessed using the key 'Base grid' (the file field's name). We're also going to rename the layer_name to 'grid'. This makes it easier to select the grid in other functions if it always has a consistent name. The last thing to change is the overwrite argument to True, so that the grid is loaded and if it exists automatically overwrites the loaded grid.
The last thing to do is to change the name of the grid in the execute method.
Save the script and run the GoldSim model again. A file dialog box will appear asking for the base grid.