Newer
Older
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
---
title: "r2ogs6 User Guide"
author: "Anna Heinrich"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{r2ogs6 User Guide}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>"
)
```
```{r setup}
library(r2ogs6)
```
## Prerequisites
Apart from having the library itself loaded, you need to have OpenGeoSys 6 installed to be able to use `r2ogs6`.
## Creating your simulation object
...
To represent a simulation object, `r2ogs6` uses an R6 class called 'OGS6'. (...).
Don't let ... intimidate you, though. Working with your simulation object is easier than it sounds, so let's get to it.
Before we can work with an object, we need to create it. To create it, we need to call the class constructor and provide it with some parameters:
* `sim_name` The name of your simulation
* `sim_id` A simulation ID (defaults to 1, this is used for chaining simulations)
* `sim_path` All relevant files for your simulation will be in here
* `ogs_bin_path` This is the path to the `bin` folder of your OpenGeoSys 6 distribution
* `test_mode` (This defaults to `FALSE` and should be left alone. I'm setting it to `TRUE` for this vignette because it turns off path validation and we haven't supplied a valid `ogs_bin_path`)
Usually, you will only ever define `sim_name`, `sim_path` and `ogs_bin_path`.
```{r}
ogs6_obj <- OGS6$new(sim_name = "my_simulation",
sim_id = 1,
sim_path = "C:\\my_sim_folder\\",
ogs_bin_path ="C:\\Programs\\OpenGeoSys\\...\\bin\\",
test_mode = TRUE)
```
And that's it, we now have a simulation object.
## Loading an OpenGeoSys 6 simulation from a project file
The quickest and easiest way to load a simulation is by using an already existing benchmark. If you take a look at the [OpenGeoSys documentation](https://www.opengeosys.org/docs/benchmarks/elliptic/elliptic-dirichlet/), you'll find plenty of benchmarks to choose from along with a link to their project file on GitLab at the top of the respective page.
For demonstration purposes, I will use a project from the `HydroMechanics` benchmarks, which can be found [here](https://gitlab.opengeosys.org/ogs/ogs/-/tree/master/Tests/Data/HydroMechanics/IdealGas/flow_free_expansion).
NOTE: `r2ogs6` has not been tested with every existing benchmark. Due to the large number of input parameters, you might encounter cases where the import fails.
## Setting up your own OpenGeoSys 6 simulation
(...)
### Check the status of your OGS6 simulation object
Since there's plenty of required and optional input parameters, you might get lost while setting up your simulation. To get a brief overview of your simulation, you can use the `OGS6` function `get_status()`. This tells you which input parameters are missing before you can run a simulation.
```{r}
# Call on the OGS6 object (note the R6 style)
ogs6_obj$get_status()
```
Since we haven't defined anything so far, you'll see a lot of red there.
### Knowing what kind of data to add to your OGS6 simulation object
The results of `get_status()` already gave us a hint what we can add. We'll go from there and try to find out more about the possible input data. Say we want to find out more about `process` objects.
```r
# To take a look at the documentation, use ? followed by the name of a class
?r2ogs6_process
```
As a rule of thumb, classes are named with the prefix `r2ogs6_` followed by their XML tag name in the `.prj` file. The only exceptions to this rule are subclasses where this would lead to duplicate class names. The class `r2ogs6_time_loop` for example contains a subclass representing a `process` child element which is not to be confused with the `process` children of the first level `processes` node directly under the root node of the `.prj` file. Because of this, that subclass is named `r2ogs6_tl_process`.
(...)
Let's try adding something now.
### Adding input data via add_*
To add data to our simulation object, we use one of ... .
```{r}
ogs6_obj$add_parameter(r2ogs6_parameter(
name = "pressure0",
type = "Constant",
value = 1
))
```
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
As soon as we've added all necessary parameters, we can try starting our simulation by calling `run_simulation(ogs6_obj, write_logfile = TRUE)`. This will run a few additional checks and then start OpenGeoSys 6. If `write_logfile` is set to `FALSE`, the output from OpenGeoSys 6 will be shown on the console.
## Running multiple simulations
If we want to run not one but multiple simulations, we can use the simulation object we just created as a blueprint for an ensemble or chain run.
### Ensemble runs
To set up an ensemble run, we first need a base simulation object. Conveniently, we already have `ogs6_obj`, so we can go from there. We will pass this object to another one, namely an object of class `OGS6_Ensemble`. Additionally, we have to define which parameters should vary between the different simulations and provide their respective values. The syntax for this is as follows:
```{r}
ogs6_ens <- OGS6_Ensemble$new(
ogs6_obj = ogs6_obj,
parameters = list(list(ogs6_obj$parameters[[1]]$value, c(2, 3, 4)))
)
```
Internally, the `OGS6_Ensemble` object clones the `OGS6` object provided to it and for these clones, it overwrites the parameters we defined with the values we provided. The parameters we define must belong to the same `OGS6` object we passed to the ensemble object as a blueprint via the `ogs6_obj` argument.
Note that for our example, I'm altering the first object in `ogs6_obj$parameters` because so far, one `r2ogs6_parameter` is the only thing we have added to our simulation. Don't let the `parameters` argument of the `OGS6_Ensemble` constructor confuse you though - you can define all kinds of parameters here and aren't limited to variables of `r2ogs6_parameter`. If we had defined a `r2ogs6_process` already, we could have passed the variable `ogs6_obj$processes[[1]]$reference_temperature` along with the value vector `c(20, 30, 40)` to the `OGS6_Ensemble` constructor.
We can check if the initialization of our ensemble object worked like this:
```{r}
ogs6_ens$ensemble[[2]]$parameters[[1]]$value
```
`ensemble` returns the list of all `OGS6` objects we want to run the simulation on. Since we provided the vector `c(2, 3, 4)` when initializing the ensemble object, `ensemble` will have a length of four (since it contains the original `OGS6` object plus three almost-identical clones). So when we reference the second `OGS6` object in the list and inspect the `value` variable of its first `parameter` object, the return value is `2` because that's the value we defined for this parameter in our vector.
Note that the class variables of `OGS6_Ensemble` objects are read-only, so be sure to define all parameters during initialization.
To start an ensemble run, we call `ogs6_ens$run_simulation(parallel = FALSE)`. This calls `run_simulation()` on each of the simulation objects in `ogs6_ens$ensemble`. Depending on the size of our ensemble and the available system resources, it might make sense to set the `parallel` parameter to `TRUE`.
NOTE: Parallelization depends on the OS: A fork cluster is used on UNIX-like Systems while on Windows systems, a socket cluster is used. Parallelization hasn't been tested on Windows yet.
### Chain runs
Chaining simulations works in a similar manner to creating ensembles. The main difference is how we define the relevant parameters. Like with an ensemble, for chains we use a special class object to pass our base simulation object to, only this time, the class we use is called `OGS6_Chain`. And while we define parameters along with their values for `OGS6_Ensemble` objects, the `parameter` argument of `OGS6_Chain` only refers to the parameter definitions, not their values (which will be calculated along the chain).
...
To start a chain run, we call `ogs6_chain$run_simulation()`. This calls `run_simulation()` on the base object and then reads in the information required to start the next simulation from the output files produced by OpenGeoSys 6 (based on the parameters we defined). Since chain runs can't be parallelized, this might take a while.