Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
aef9256
Add support for second input file `EFDC2.INP`
vt-max Dec 9, 2022
ea6df43
Convert to Markdown
Dec 12, 2022
efadcb1
Move C101 card to EFDC2.INP for test
Dec 12, 2022
f326709
Merge pull request #237 from OpenDA-Association/add-inputfile-efd2
Dec 12, 2022
ed38e9d
Add WQDGSTOX: algae salinity / freshwater toxicity
vt-max Dec 8, 2022
62f0147
Add test case nakdong 2022
Dec 12, 2022
1438c8b
Disable SEEK('C21') call as in provided source
Dec 12, 2022
d0de3e4
Add writing of algae growth rates and limits
Dec 12, 2022
5d790e5
Rename test
Dec 12, 2022
977303f
Merge pull request #238 from OpenDA-Association/add-wqdgstox-support
Dec 12, 2022
f450e46
Support parsing `IBIN_TYPE` in card C2
vt-max Dec 9, 2022
4cd4e28
Fix reading card C2
Dec 13, 2022
d7004b6
Add IBIN_TYPE to EFDC.INP
Dec 13, 2022
29dd329
Fix error in configuration
Dec 13, 2022
6dece88
Enable SEEK('C21')
Dec 13, 2022
47cdc17
Fix regression
Jan 10, 2023
e042b7f
Merge pull request #236 from OpenDA-Association/add-ibin-type-flag
Jan 30, 2023
bdbca88
Merge pull request #235 from OpenDA-Association/230-update-documentat…
Jan 30, 2023
e7bc315
Add empty line to fix seek(C21)
Jan 30, 2023
34d8869
Merge pull request #270 from OpenDA-Association/269-fix-model_nakdong…
Jan 30, 2023
447f439
Add binaries
Jan 30, 2023
d8bc32d
Cleanup project
Jan 30, 2023
be74549
Merge pull request #272 from OpenDA-Association/271-model_efdc_dll-bi…
Jan 30, 2023
efbb8c4
Remove Debug dll (too large)
Jan 31, 2023
3e4dd4b
Update readme.md
Jan 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# OpenDA in memory coupling with EFDC


OpenDA is an open interface standard for (and free implementation of) a set of tools to quickly implement data-assimilation and calibration for arbitrary numerical models. OpenDA wants to stimulate the use of data-assimilation and calibration by lowering the implementation costs and enhancing the exchange of software among researchers and end-users. A model that conforms to the OpenDA standard can use all the tools that are available in OpenDA. General information on OpenDA can be found on the OpenDA website: http://www.openda.org. Technical documentation for OpenDA is avalaible at http://www.openda.org/docu/openda_2.0/doc/developers_corner.html.

Structure of the OpenDA wrapper for EFDC
----------------------------------------
## Structure of the OpenDA wrapper for EFDC

To make the EFDC model available for OpenDA a mixed Java/Fortran wrapper is written. The Fortran source together with the EFDC fortran source is compiled as a shared library (for Unix/Linux)or a dynamic linked library (for Windows). This library is called from Java using Java Native Access (JNA), for details see http://github.com/twall/jna.

```bash
/public/model_efdc_dll/java/src/org/openda/model_efdc_dll/EfdcDLL.java
/public/model_efdc_dll/java/src/org/openda/model_efdc_dll/EfdcExchangeItemType.java
/public/model_efdc_dll/java/src/org/openda/model_efdc_dll/EfdcGridExchangeItem.java
Expand All @@ -16,24 +18,26 @@ To make the EFDC model available for OpenDA a mixed Java/Fortran wrapper is writ
/public/model_efdc_dll/java/src/org/openda/model_efdc_dll/GfortranFunctionMapper.java
/public/model_efdc_dll/java/src/org/openda/model_efdc_dll/IEfdcFortranNativeDLL.java
/public/model_efdc_dll/java/src/org/openda/model_efdc_dll/IntelFortranFunctionMapper.java
```

OpenDA expects from a OpenDA compliant model that it provides Java classes which implement the methods from the IModelInstance and IModelFactory interfaces (see the OpenDA technical documentation). These classes are provided in EfdcModelInstance.java and EfdcModelFactory.java. At the Java side much of these methods are delegated to the shared library. This delegation is handled by EfdcDLL.java. IEfdcFortranNativeDLL.java provides interface declarations for the functions that are available in the shared library. Each Fortran compiler uses a different name-mangling convention for function names in the compiled library. The classes GfortranFunctionMapper.java and IntelFortranFunctionMapper.java translate the function names to the correct names for the shared libraries compiled by the gfortran and intel fortran compiler. For windows the function names in the DLL are set using preprocessor directives in the Fortran source code.

To exchange data between OpenDA and EFDC we implement the methods from the IExchangeItem interface of OpenDA. For more details see the OpenDA documentation (http://www.openda.org/docu/openda_2.1/doc/getting_started.html). For information on exchange items in the EFDC dll see exchange_items.txt.

EFDC input files
----------------
## EFDC input files

All the normal input EFDC input files are required by the shared libary. The simulation time period is set in EFDC.INP and EVENT_TOX2.INP.

```
EFDC.INP
EVENT_TOX2.INP
CELL.INP
CELLT.INP
```

Supress output
--------------
## Supress output

```
C71 ISSPH NPSPH ISRSPH ISPHXY
0 24 0 0 !SAL
0 24 0 0 !TEM
Expand All @@ -49,14 +53,18 @@ C72 ISPPH NPPPH ISRPPH IPPHXY

C73 ISVPH NPVPH ISRVPH IVPHXY
0 24 0 0
```

Restart files
-------------
## Restart files

Input

```
RESTART.INP, RSTWD.INP, TEMP.RST, WQWCRST.INP
```

Output

```
RESTART.OUT, RSTWD.OUT, TEMP.RSTO, WQWCRST.OUT
```
176 changes: 176 additions & 0 deletions model_efdc_dll/exchange_items.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# Exchange Items

OpenDA exchanges data with the EFDC model through exhcange items. Exchang items are defined in `model_exchange_items.f90`. Exchange items exist for grid data and time series. For time series OpenDA communicates with the time series that are stored in the model instance memory (see `model_*ser_time_series.f90`). For grid data, exchange items access the model state for a given instancen (`model_state.f90`).

All comunication between OpenDA and the EFDC dll is handled by `openDA_wrapper.f90`. Of importance are the following subroutines and functions.

checking if exchange_item is active in the EFDC configuration:

```fortran
function supports_exchange_item(instance, exchange_item_id) result (ret_val)
```

setting/getting times for time series exchange items:

```fortran
function get_times_for_ei(instance, exchange_item_id, bc_index, values_count, times) result (ret_val)
function set_times_for_ei(instance, exchange_item_id, bc_index, values_count, times) result (ret_val)
```

obtaining dimensions of exchange item:

```fortran
function get_values_count(instance, exchange_item_id) result(ret_val)
function get_values_count_for_location(instance, exchange_item_id, bc_index) result(ret_val)
function get_time_series_count(instance, exchange_item_id) result(ret_val)
function get_values_count_for_time_span(instance, exchange_item_id, bc_index, start_time, end_time) result(ret_val)
```

setting/getting data:

```fortran
function get_values(instance, exchange_item_id, start_index, end_index, values) result(ret_val)
function set_values(instance, exchange_item_id, start_index, end_index, values) result(ret_val)
function get_values_for_time_span(instance, exchange_item_id, bc_index, start_time, end_time, values_count, values) result(ret_val)
function set_values_for_time_span(instance, exchange_item_id, bc_index, start_time, end_time, values_count, values) result(ret_val)
```

Furthermore, the following subroutines are also of importance when adding an exchange item:
getting/changing/initializing the data-structure for exchange items:

```fortran
function m_openda_wrapper_init_(parent_directory_c, template_directory_c) result (ret_val)
function m_openda_wrapper_model_instance_(instance_dir_c) result(ret_val)
subroutine add_instance_storage()
```


checking various properties of the exchange-item data-structure

```fortran
function check_bc_indices(instance, exchange_item_id, bc_index, start_time, end_time, start_index, end_index) result(success)
function check_grid_indices(instance, exchange_item_id, start_index, end_index) result(success) NOTE: only when adding a grid belonging to the exchange item.
```


obtaining dimensions of exchange item:

```fortran
function m_openda_wrapper_get_layer_count_(instance, exchange_item_id) result(retval)
function m_openda_wrapper_get_times_count_for_location_(instance, exchange_item_id, bc_index)
function m_openda_wrapper_get_time_series_count_(instance, exchange_item_id) result(ret_val)
function m_openda_wrapper_get_times_count_for_time_span_(instance, exchange_item_id, bc_index, start_time, end_time) result(ret_val)
```


setting/getting data:

```fortran
function m_openda_wrapper_get_values_for_time_span_(instance, exchange_item_id, bc_index, start_time, end_time, values_count, values) result(ret_val)
function m_openda_wrapper_set_values_for_time_span_(instance, exchange_item_id, bc_index, start_time, end_time, values_count, values) result(ret_val)
```

## Currently supported exchange items

In the current release the exchange items exist for the following quantaties:

Atmospheric forcings:

| Variable | Time series Exchange item ID |
|--|--|
|Precipitation | 101 |
|AirTemperature | 102 |
|CloudCover | 103 |
|GlobalRadiation | 104 |
|AtmosphericPressure | 105 |
|RelativeHumidity | 106 |
|PotentialEvaporation | 107 |

Wind forcings:

| Variable | Time series Exchange item ID |
|--|--|
| WindSpeed |151|
| WindDirection |152|

Hydrodynamics:

| Variable | Time series Exchange item ID | Grid data Exchange item ID|
|--|--|--|
| WaterLevel | 201 | 1201 |
| Discharge | 301 | 1301 |
| WaterTemperature | 401 | 1401 |

Water Quality:

| Variable | Time series Exchange item ID | Grid data Exchange item ID|
|--|--|--|
| AlgalCyanobacteria | 501 | 1501 |
| AlgalDiatom | 502 | 1502 |
| AlgalGreenAlgae | 503 | 1503 |
| RefractoryPOCarbon | 504 | 1504 |
| LabilePOCarbon | 505 | 1505 |
| DissolvedOCarbon | 506 | 1506 |
| RefractoryPOPhosphorus | 507 | 1507 |
| LabilePOPhosporus | 508 | 1508 |
| DissolvedOPhosphorus | 509 | 1509 |
| Phosphate | 510 | 1510 |
| RefractoryPONitrogen | 511 | 1511 |
| LabilePONitrogen | 512 | 1512 |
| DissolvedONitrogen | 513 | 1513 |
| Ammonia | 514 | 1514 |
| Nitrate | 515 | 1515 |
| DisolvedOxygen | 519 | 1519 |

Toxics:

| Variable | Time series Exchange item ID | Grid data Exchange item ID|
|--|--|--|
|Cadmium | 601 | 1601 |
|Copper | 602 | 1602 |
|Lead | 603 | 1603 |
|Zinc | 604 | 1604 |
|Benzopyrene | 605 | 1605 |
|Pcb | 606 | 1606 |
|Phenol | 607 | 1607 |
|cisChlordane | 608 | 1608 |
|transChlordane | 609 | 1609 |
|Chlorbenzen | 610 | 1610 |
|MethylParathion | 611 | 1611 |
|PcbArchor1242 | 612 | 1612 |

Controls:

| Variable | Time series Exchange item ID |
|--|--|
| ControlsGateWaterLevel | 701 |
| ControlsGateOpeningHeight | 702 |

X-species:

| Variable | Time series Exchange item ID | Grid data Exchange item ID|
|--|--|--|
|XSpeciesnn | 8nn | 18nn |

## Adding exchange items

Support for the exchange item should be added to the EFDC dll and at the OpenDA site in `/public/model_efdc_dll/java/src/org/openda/model_efdc_dll/EfdcExchangeItemType.java`. When a new exchange item needs to be added, first define an exchange item ID in `model_exchange_items.f90` and `EfdcExchangeItemType.java`.

The exchange item ID is passed when OpenDA calls one of the exchange item subroutines (see above). Support for the new exchange item has to be added to these subroutine using the case statement. When the exchange item can differ between model instances, it is important data is stored in model instance memory. Grid data is probably already stored in the state vector of each instance (see `model_state.f90`). For time series have one of the existing `model_*ser_time_series.f90` can be used as an example. Most time series in EFDC have parameter defined in the related file `*SER.INP`. If an exchange item is used to for setting the time series, a template `*SER.INP` file needs to exist in the work directory. This template file needs to consist of the required number of locations (as defined in `EFDC.INP`) and have the correct parameters. For example see the `PSER.INP` for `NPSER=2` locations:
In the `openDA_wrapper` do not forget to add use `model_*ser_time_series`


```
C ** pser.inp file, in free format across line, repeat NPSER times
C **
C ** MPSER(NS) TCPSER(NS) TAPSER(NS) RMULADJ(NS) ADDADJ(NS)
C **
C ** TPSER(M,NS) PSER(M,NS)
C **
2 86400 0 1 0 ! location one
0.000 0.0
730.000 0.0
2 86400 0 1 0 ! location two
0.000 0.0
730.000 0.0
```
132 changes: 0 additions & 132 deletions model_efdc_dll/exchange_items.txt

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ private static void writeRunPeriodInModelConfigFiles(File templateDir,
efdcEventTox2InpDataObject.initialize(templateDir,
new String[]{EVENT_TOX2_INP_FILE_NAME, String.valueOf(timeZoneOffsetInHours), TSTART, TSTOP});
for (String id : efdcEventTox2InpDataObject.getExchangeItemIDs()) {
IExchangeItem exchangeItem = efdcInpDataObject.getDataObjectExchangeItem(id);
IExchangeItem exchangeItem = efdcEventTox2InpDataObject.getDataObjectExchangeItem(id);
if (TSTART.equals(id)) {
exchangeItem.setValuesAsDoubles(new double[]{startTime});
} else if (TSTOP.equals(id)) {
Expand Down
Loading