diff --git a/model_hec_hms/README.md b/model_hec_hms/README.md
new file mode 100644
index 000000000..7b132d828
--- /dev/null
+++ b/model_hec_hms/README.md
@@ -0,0 +1 @@
+This model updates the initial states of the HEC HMS model using data assimilation.
diff --git a/model_hec_hms/bin_external/bin_external_to_bin.test b/model_hec_hms/bin_external/bin_external_to_bin.test
new file mode 100644
index 000000000..e69de29bb
diff --git a/model_hec_hms/build.xml b/model_hec_hms/build.xml
new file mode 100644
index 000000000..0d7b3b06d
--- /dev/null
+++ b/model_hec_hms/build.xml
@@ -0,0 +1,154 @@
+
+
+
+
+ ant help --> print this help
+ ant build --> compile, make jar and copy resources
+ ant build-test --> compile test classes
+ ant clean --> remove output
+ ant javadoc --> build javadoc
+
+
+
+
+
+
+
+
+ module=${module}
+ srcdir=${srcdir}
+ jarname=${jarname}
+ builddir=${builddir}
+ bindir=${bindir}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${module}${line.separator}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Subversion Revision: ${svn.revision}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/model_hec_hms/doc/.gitkeep b/model_hec_hms/doc/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/model_hec_hms/java/resources/resources_to_bin.test b/model_hec_hms/java/resources/resources_to_bin.test
new file mode 100644
index 000000000..e69de29bb
diff --git a/model_hec_hms/java/src/org/openda/model_hec_hms/GridBounds.java b/model_hec_hms/java/src/org/openda/model_hec_hms/GridBounds.java
new file mode 100644
index 000000000..a8cf78fd5
--- /dev/null
+++ b/model_hec_hms/java/src/org/openda/model_hec_hms/GridBounds.java
@@ -0,0 +1,42 @@
+package org.openda.model_hec_hms;
+
+public class GridBounds {
+ private int minimumX = Integer.MAX_VALUE;
+ private int minimumY = Integer.MAX_VALUE;
+ private int maximumX = Integer.MIN_VALUE;
+ private int maximumY = Integer.MIN_VALUE;
+
+ public void addCell(int x, int y) {
+ minimumX = Math.min(minimumX, x);
+ minimumY = Math.min(minimumY, y);
+ maximumX = Math.max(maximumX, x);
+ maximumY = Math.max(maximumY, y);
+ }
+
+ public int getX() {
+ return minimumX;
+ }
+
+ public int getY() {
+ return minimumY;
+ }
+
+ public int getWidth() {
+ return maximumX + 1 - minimumX;
+ }
+
+ public int getHeight() {
+ return maximumY + 1 - minimumY;
+ }
+
+ public int getSize() {
+ return getWidth() * getHeight();
+ }
+
+ public int getIndex(GridCell gridCell) {
+ int x = gridCell.getX() - minimumX;
+ int y = gridCell.getY() - minimumY;
+
+ return x * getHeight() + y;
+ }
+}
diff --git a/model_hec_hms/java/src/org/openda/model_hec_hms/GridCell.java b/model_hec_hms/java/src/org/openda/model_hec_hms/GridCell.java
new file mode 100644
index 000000000..327b62bce
--- /dev/null
+++ b/model_hec_hms/java/src/org/openda/model_hec_hms/GridCell.java
@@ -0,0 +1,37 @@
+package org.openda.model_hec_hms;
+
+import java.util.Objects;
+
+public class GridCell {
+ private final int x;
+ private final int y;
+
+ public GridCell(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public int getY() {
+ return y;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof GridCell)) {
+ return false;
+ }
+
+ GridCell otherGridCell = (GridCell) other;
+
+ return x == otherGridCell.x && y == otherGridCell.y;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(x, y);
+ }
+}
diff --git a/model_hec_hms/java/src/org/openda/model_hec_hms/GridIdToGridCell.java b/model_hec_hms/java/src/org/openda/model_hec_hms/GridIdToGridCell.java
new file mode 100644
index 000000000..b2188f76a
--- /dev/null
+++ b/model_hec_hms/java/src/org/openda/model_hec_hms/GridIdToGridCell.java
@@ -0,0 +1,19 @@
+package org.openda.model_hec_hms;
+
+public class GridIdToGridCell {
+ private final String gridId;
+ private final GridCell gridCell;
+
+ public GridIdToGridCell(String gridId, GridCell gridCell) {
+ this.gridId = gridId;
+ this.gridCell = gridCell;
+ }
+
+ public String getGridId() {
+ return gridId;
+ }
+
+ public GridCell getGridCell() {
+ return gridCell;
+ }
+}
diff --git a/model_hec_hms/java/src/org/openda/model_hec_hms/StateFile.java b/model_hec_hms/java/src/org/openda/model_hec_hms/StateFile.java
new file mode 100644
index 000000000..10bb7af35
--- /dev/null
+++ b/model_hec_hms/java/src/org/openda/model_hec_hms/StateFile.java
@@ -0,0 +1,240 @@
+/* MOD_V2.0
+ * Copyright (c) 2012 OpenDA Association
+ * All rights reserved.
+ *
+ * This file is part of OpenDA.
+ *
+ * OpenDA is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * OpenDA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with OpenDA. If not, see .
+ */
+package org.openda.model_hec_hms;
+
+import org.openda.interfaces.IDataObject;
+import org.openda.interfaces.IExchangeItem;
+
+import java.io.*;
+import java.util.*;
+
+public class StateFile implements IDataObject {
+ private static final String[] EMPTY_STRING_ARRAY = new String[0];
+ private File workingDirectory;
+ private String filename = null;
+
+ private final Map items = new HashMap<>();
+ private final Map gridToBounds = new HashMap<>();
+ private final Map gridToValues = new HashMap<>();
+ private final Map> gridToCellToValues = new HashMap<>();
+
+ private final Map lines = new LinkedHashMap<>();
+ private final Map valuesToUpdate = new HashMap<>();
+
+ @Override
+ public void initialize(File workingDirectory, String[] arguments) {
+ this.workingDirectory = workingDirectory;
+
+ File inputFile = getInputFile(arguments);
+ processInputFile(inputFile);
+ collateGridBounds();
+ collateValuesForUpdating();
+ populateStateFileExchangeItems();
+ }
+
+ private File getInputFile(String[] arguments) {
+ if (null == arguments || 1 != arguments.length) {
+ throw new RuntimeException("Expected filename as only argument.");
+ }
+
+ filename = arguments[0];
+
+ File inputFile = new File(workingDirectory, filename);
+
+ try {
+ if (!inputFile.exists()) {
+ throw new RuntimeException("File: " + inputFile.getCanonicalFile() + " does not exist.");
+ }
+
+ if (!inputFile.isFile()) {
+ throw new RuntimeException("File: " + inputFile.getCanonicalFile() + " is not a file.");
+ }
+ } catch (IOException ioException) {
+ throw new RuntimeException(ioException);
+ }
+ return inputFile;
+ }
+
+ private void processInputFile(File inputFile) {
+ try (FileInputStream fileInputStream = new FileInputStream(inputFile);
+ InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
+ BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
+ String line = bufferedReader.readLine();
+ int lineNumber = 0;
+
+ String subBasin = null;
+ int x = 0;
+ int y = 0;
+ String loss = null;
+ int layerNumber = 0;
+
+ while (null != line) {
+ lines.put(lineNumber, line);
+
+ if (line.contains(":")) {
+ String[] labelAndValue = line.split(":");
+ String label = labelAndValue[0].trim();
+
+ switch (label) {
+ case "Subbasin":
+ subBasin = labelAndValue[1].trim();
+ break;
+ case "End":
+ subBasin = null;
+ break;
+ case "GridCell":
+ String gridCellString = labelAndValue[1].trim();
+ String[] gridCellIndices = gridCellString.split(",");
+ x = Integer.parseInt(gridCellIndices[0]);
+ y = Integer.parseInt(gridCellIndices[1]);
+ break;
+ case "End Grid Cell":
+ break;
+ case "Loss":
+ loss = labelAndValue[1].trim();
+ break;
+ case "End Loss":
+ loss = null;
+ break;
+ case "Number Groundwater Layers":
+ layerNumber = 0;
+ break;
+ case "Groundwater Storage":
+ double value = Double.parseDouble(labelAndValue[1].trim());
+ String gridId = subBasin + "_" + loss + "_" + layerNumber;
+ layerNumber++;
+
+ GridBounds gridBounds = gridToBounds.computeIfAbsent(gridId, bounds -> new GridBounds());
+ gridBounds.addCell(x, y);
+
+ Map cellToValue = gridToCellToValues.computeIfAbsent(gridId, m -> new HashMap<>());
+ GridCell gridCell = new GridCell(x, y);
+ cellToValue.put(gridCell, value);
+
+ GridIdToGridCell gridIdToGridCell = valuesToUpdate.put(lineNumber, new GridIdToGridCell(gridId, gridCell));
+
+ if (null != gridIdToGridCell) {
+ throw new RuntimeException("Duplicate in grid: " + gridId + " cell id: " + gridCell);
+ }
+ break;
+ default:
+ // Do nothing with other labels
+ }
+ }
+
+ line = bufferedReader.readLine();
+ lineNumber++;
+ }
+ } catch (IOException ioException) {
+ throw new RuntimeException(ioException);
+ }
+ }
+
+ private void collateGridBounds() {
+ for (Map.Entry gridToBound : gridToBounds.entrySet()) {
+ int valueArraySize = gridToBound.getValue().getSize();
+ gridToValues.put(gridToBound.getKey(), new Double[valueArraySize]);
+ }
+ }
+
+ private void collateValuesForUpdating() {
+ for (Map.Entry> gridToCellToValue : gridToCellToValues.entrySet()) {
+ for (Map.Entry cellToValue : gridToCellToValue.getValue().entrySet()) {
+ Double[] values = gridToValues.get(gridToCellToValue.getKey());
+ GridBounds gridBounds = gridToBounds.get(gridToCellToValue.getKey());
+ int valueArrayIndex = gridBounds.getIndex(cellToValue.getKey());
+ values[valueArrayIndex] = cellToValue.getValue();
+ }
+ }
+ }
+
+ private void populateStateFileExchangeItems() {
+ for (Map.Entry gridToValue : gridToValues.entrySet()) {
+ String gridId = gridToValue.getKey();
+ GridBounds gridBounds = gridToBounds.get(gridId);
+ int x = gridBounds.getX();
+ int y = gridBounds.getY();
+ int width = gridBounds.getWidth();
+ int height = gridBounds.getHeight();
+ double[] values = toPrimitiveDoubleArray(gridToValue.getValue());
+ StateFileExchangeItem stateFileExchangeItem = new StateFileExchangeItem(gridId, x, y, width, height, values);
+ items.put(gridId, stateFileExchangeItem);
+ }
+ }
+
+ @Override
+ public void finish() {
+ File outputFile = new File(workingDirectory, filename);
+
+ try (FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
+ OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);
+ BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter)) {
+ int lineNumber = 0;
+ for (Map.Entry line : lines.entrySet()) {
+ if (valuesToUpdate.containsKey(lineNumber)) {
+ String label = line.getValue().split(":")[0];
+ bufferedWriter.write(label);
+ GridIdToGridCell gridIdToGridCell = valuesToUpdate.get(lineNumber);
+ StateFileExchangeItem exchangeItem = items.get(gridIdToGridCell.getGridId());
+ GridBounds gridBounds = gridToBounds.get(gridIdToGridCell.getGridId());
+ int cellIndex = gridBounds.getIndex(gridIdToGridCell.getGridCell());
+ double[] values = exchangeItem.getValuesAsDoubles();
+ bufferedWriter.write(": " + values[cellIndex]);
+ } else {
+ bufferedWriter.write(line.getValue());
+ }
+ bufferedWriter.newLine();
+
+ lineNumber++;
+ }
+ } catch (IOException ioException) {
+ throw new RuntimeException(ioException);
+ }
+ }
+
+ @Override
+ public String[] getExchangeItemIDs() {
+ return items.keySet().toArray(EMPTY_STRING_ARRAY);
+ }
+
+ @Override
+ public String[] getExchangeItemIDs(IExchangeItem.Role role) {
+ return items.keySet().toArray(EMPTY_STRING_ARRAY);
+ }
+
+ @Override
+ public IExchangeItem getDataObjectExchangeItem(String exchangeItemID) {
+ return items.get(exchangeItemID);
+ }
+
+ private double[] toPrimitiveDoubleArray(Double[] values) {
+ double[] primitiveArray = new double[values.length];
+
+ for (int valueIndex = 0; valueIndex < values.length; valueIndex++) {
+ if (null == values[valueIndex]) {
+ primitiveArray[valueIndex] = Double.NaN;
+ } else {
+ primitiveArray[valueIndex] = values[valueIndex];
+ }
+ }
+
+ return primitiveArray;
+ }
+}
diff --git a/model_hec_hms/java/src/org/openda/model_hec_hms/StateFileExchangeItem.java b/model_hec_hms/java/src/org/openda/model_hec_hms/StateFileExchangeItem.java
new file mode 100644
index 000000000..fb0302330
--- /dev/null
+++ b/model_hec_hms/java/src/org/openda/model_hec_hms/StateFileExchangeItem.java
@@ -0,0 +1,138 @@
+package org.openda.model_hec_hms;
+
+import org.openda.interfaces.IExchangeItem;
+import org.openda.interfaces.IGeometryInfo;
+import org.openda.interfaces.IQuantityInfo;
+import org.openda.interfaces.ITimeInfo;
+
+public class StateFileExchangeItem implements IExchangeItem {
+ private final String gridId;
+ private final int x;
+ private final int y;
+ private final int width;
+ private final int height;
+ private double[] values;
+
+ public StateFileExchangeItem(String gridId, int x, int y, int width, int height, double[] values) {
+ this.gridId = gridId;
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ this.values = values;
+ }
+
+ @Override
+ public Role getRole() {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ @Override
+ public String getId() {
+ return gridId;
+ }
+
+ @Override
+ public String getDescription() {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ @Override
+ public void copyValuesFromItem(IExchangeItem sourceItem) {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ @Override
+ public ITimeInfo getTimeInfo() {
+ return null;
+ }
+
+ @Override
+ public IQuantityInfo getQuantityInfo() {
+ return null;
+ }
+
+ @Override
+ public IGeometryInfo getGeometryInfo() {
+ return null;
+ }
+
+ @Override
+ public ValueType getValuesType() {
+ return IExchangeItem.ValueType.IVectorType;
+ }
+
+ @Override
+ public Object getValues() {
+ return getValuesAsDoubles();
+ }
+
+ @Override
+ public double[] getValuesAsDoubles() {
+ return values;
+ }
+
+ @Override
+ public void axpyOnValues(double alpha, double[] axpyValues) {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ @Override
+ public void multiplyValues(double[] multiplicationFactors) {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ @Override
+ public void setValues(Object values) {
+ if (!(values instanceof double[])) {
+ throw new IllegalArgumentException("Values must be of type double[]");
+ }
+
+ double[] valuesArray = (double[]) values;
+
+ int expectedLength = width * height;
+
+ if (expectedLength != valuesArray.length) {
+ throw new IllegalArgumentException("The number of values: " + valuesArray.length + " is not equal to the expected size of the current array: " + expectedLength);
+ }
+
+ this.values = valuesArray;
+ }
+
+ @Override
+ public void setValuesAsDoubles(double[] values) {
+ int expectedLength = width * height;
+
+ if (expectedLength != values.length) {
+ throw new IllegalArgumentException("The number of values: " + values.length + " is not equal to the expected size of the current array: " + expectedLength);
+ }
+
+ this.values = values;
+ }
+
+ @Override
+ public double[] getTimes() {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ @Override
+ public void setTimes(double[] times) {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public int getY() {
+ return y;
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+}
diff --git a/model_hec_hms/java/test/org/openda/model_hec_hms/StateFileTest.java b/model_hec_hms/java/test/org/openda/model_hec_hms/StateFileTest.java
new file mode 100644
index 000000000..227b20fa9
--- /dev/null
+++ b/model_hec_hms/java/test/org/openda/model_hec_hms/StateFileTest.java
@@ -0,0 +1,110 @@
+/* MOD_V2.0
+ * Copyright (c) 2012 OpenDA Association
+ * All rights reserved.
+ *
+ * This file is part of OpenDA.
+ *
+ * OpenDA is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * OpenDA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with OpenDA. If not, see .
+ */
+package org.openda.model_hec_hms;
+
+import junit.framework.TestCase;
+import org.openda.interfaces.IDataObject;
+import org.openda.interfaces.IExchangeItem;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+import java.util.List;
+
+public class StateFileTest extends TestCase {
+ private static final File TEST_RESOURCES_DIRECTORY = new File("java/testResources");
+
+ public void testStateFileWithNoExchangeItems() throws IOException {
+ // Given input file
+ File temporaryInputFile = File.createTempFile("temp-no-exchange-items", ".state");
+ File sourceInputFile = new File(TEST_RESOURCES_DIRECTORY, "no-exchange-items.state");
+ try {
+ Files.copy(sourceInputFile.toPath(), temporaryInputFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
+
+ // Given state file
+ IDataObject dataObject = new StateFile();
+ String[] args = {temporaryInputFile.getName()};
+
+ // When initialized
+ dataObject.initialize(new File(temporaryInputFile.getParent()), args);
+
+ // Then no exchange items are found
+ String[] exchangeItemIds = dataObject.getExchangeItemIDs();
+ assertEquals(0, exchangeItemIds.length);
+
+ // When finished
+ dataObject.finish();
+
+ // Then output file matches input file
+ List expectedLines = Files.readAllLines(new File(TEST_RESOURCES_DIRECTORY, "expected-no-exchange-items.state").toPath());
+ List actualLines = Files.readAllLines(temporaryInputFile.toPath());
+ assertEquals(expectedLines, actualLines);
+ } finally {
+ Files.deleteIfExists(temporaryInputFile.toPath());
+ }
+ }
+
+ public void testStateFile() throws IOException {
+ // Given input file
+ File temporaryInputFile = File.createTempFile("temp-exchange-items", ".state");
+ File sourceInputFile = new File(TEST_RESOURCES_DIRECTORY, "exchange-items.state");
+ try {
+ Files.copy(sourceInputFile.toPath(), temporaryInputFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
+
+ // Given state file
+ IDataObject dataObject = new StateFile();
+ String[] args = {temporaryInputFile.getName()};
+
+ // When initialized
+ dataObject.initialize(new File(temporaryInputFile.getParent()), args);
+
+ // Then exchange items are found
+ String[] exchangeItemIds = dataObject.getExchangeItemIDs();
+ assertEquals(2, exchangeItemIds.length);
+
+ // Then exchange items contains values for: Subbasin: Subbasin-16, Loss: Soil Moisture Account, Groundwater Storage: 1
+ IExchangeItem exchangeItem = dataObject.getDataObjectExchangeItem("Subbasin-16_Soil Moisture Account_1");
+ assertNotNull(exchangeItem);
+ assertTrue(exchangeItem instanceof StateFileExchangeItem);
+ StateFileExchangeItem stateFileExchangeItem = (StateFileExchangeItem) exchangeItem;
+
+ // Then the exchange item has an aray of values
+ double[] values = stateFileExchangeItem.getValuesAsDoubles();
+ assertEquals(12, values.length);
+ assertEquals(0.238, values[2], 0.001);
+
+ // When the values are updated
+ for (int i = 0; i < values.length; i++) {
+ values[i] = i / 2.0;
+ }
+
+ // And the file is output
+ dataObject.finish();
+
+ // Then the values are updated
+ List expectedLines = Files.readAllLines(new File(TEST_RESOURCES_DIRECTORY, "expected-exchange-items.state").toPath());
+ List actualLines = Files.readAllLines(temporaryInputFile.toPath());
+ assertEquals(expectedLines, actualLines);
+ } finally {
+ Files.deleteIfExists(temporaryInputFile.toPath());
+ }
+ }
+}
diff --git a/model_hec_hms/java/testResources/exchange-items.state b/model_hec_hms/java/testResources/exchange-items.state
new file mode 100644
index 000000000..ebf1040c8
--- /dev/null
+++ b/model_hec_hms/java/testResources/exchange-items.state
@@ -0,0 +1,196 @@
+Snapshot: EndState
+ Run ID: Gridded_DANA2024_BurnMDT
+ Snapshot Time:22 October 2024, 14:00
+ Execution Time: 16 September 2025, 13:21:01
+ Basin Model: Rambla Poyo Burn - Gridded
+ Version: 4.13
+End:
+
+Subbasin: Subbasin-16
+ Loss method: Gridded Soil Moisture Account
+ Transform method: Modified Clark
+ GridCell: 3489,21866
+ Loss: Soil Moisture Account
+ Soil Storage: 3.6723709106445312
+ Number Groundwater Layers: 2
+ Groundwater Storage: 0.43229889136872823
+ Groundwater Storage: 0.14531690262134514
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 0.002240212732261733
+ Lag Table Flow: 0.002240212732261733
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+ GridCell: 3490,21865
+ Loss: Soil Moisture Account
+ Soil Storage: 1.6355958186173745
+ Number Groundwater Layers: 2
+ Groundwater Storage: 0.03208461245284903
+ Groundwater Storage: 0.04834661463798384
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 0.01296803998623444
+ Lag Table Flow: 0.01284603101324866
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+ GridCell: 3490,21864
+ Loss: Soil Moisture Account
+ Soil Storage: 4.225638389587402
+ Number Groundwater Layers: 2
+ Groundwater Storage: 0.5342433215407607
+ Groundwater Storage: 0.14348083748066623
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 0.010820381639851927
+ Lag Table Flow: 0.010820381639851927
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+ GridCell: 3490,21866
+ Loss: Soil Moisture Account
+ Soil Storage: 1.6355958186173745
+ Number Groundwater Layers: 2
+ Groundwater Storage: 0.025055088630458626
+ Groundwater Storage: 0.04078704317766789
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 0.0025467914276175786
+ Lag Table Flow: 0.0025225504210034527
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+ GridCell: 3491,21866
+ Loss: Soil Moisture Account
+ Soil Storage: 3.740156888961792
+ Number Groundwater Layers: 2
+ Groundwater Storage: 0.1708343510261292
+ Groundwater Storage: 0.06832272241445166
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 2.684966328935324E-4
+ Lag Table Flow: 2.684966328935324E-4
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+ GridCell: 3490,21863
+ Loss: Soil Moisture Account
+ Soil Storage: 4.225638389587402
+ Number Groundwater Layers: 2
+ Groundwater Storage: 0.5416751881340691
+ Groundwater Storage: 0.1413567255361503
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 0.008813760335686847
+ Lag Table Flow: 0.008813760335686847
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+ GridCell: 3491,21865
+ Loss: Soil Moisture Account
+ Soil Storage: 1.6355958186173745
+ Number Groundwater Layers: 2
+ Groundwater Storage: 0.03986169816321006
+ Groundwater Storage: 0.05606346620176033
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 0.001229402537535392
+ Lag Table Flow: 0.0012175929741580981
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+ GridCell: 3491,21863
+ Loss: Soil Moisture Account
+ Soil Storage: 3.8967862129211426
+ Number Groundwater Layers: 2
+ Groundwater Storage: 1.9212463609771424
+ Groundwater Storage: 0.5595039464956546
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 1.6030003029359727E-4
+ Lag Table Flow: 1.6030003029359727E-4
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+ GridCell: 3491,21864
+ Loss: Soil Moisture Account
+ Soil Storage: 3.8967862129211426
+ Number Groundwater Layers: 2
+ Groundwater Storage: 1.9117279814288
+ Groundwater Storage: 0.5574813526628896
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 1.856005724496666E-4
+ Lag Table Flow: 1.856005724496666E-4
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+ GridCell: 3489,21865
+ Loss: Soil Moisture Account
+ Soil Storage: 3.6019248962402344
+ Number Groundwater Layers: 2
+ Groundwater Storage: 0.7460371505550496
+ Groundwater Storage: 0.2382428626952494
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 0.00760024320276418
+ Lag Table Flow: 0.00760024320276418
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+ Baseflow: None
+ End Baseflow
+End:
+
+Reach: Reach-3
+ Route: Lag
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 22.865836383074644
+ Lag Table Flow: 17.10341665595959
+ End Lag Table:
+ End Route:
+End:
diff --git a/model_hec_hms/java/testResources/expected-exchange-items.state b/model_hec_hms/java/testResources/expected-exchange-items.state
new file mode 100644
index 000000000..2da820121
--- /dev/null
+++ b/model_hec_hms/java/testResources/expected-exchange-items.state
@@ -0,0 +1,196 @@
+Snapshot: EndState
+ Run ID: Gridded_DANA2024_BurnMDT
+ Snapshot Time:22 October 2024, 14:00
+ Execution Time: 16 September 2025, 13:21:01
+ Basin Model: Rambla Poyo Burn - Gridded
+ Version: 4.13
+End:
+
+Subbasin: Subbasin-16
+ Loss method: Gridded Soil Moisture Account
+ Transform method: Modified Clark
+ GridCell: 3489,21866
+ Loss: Soil Moisture Account
+ Soil Storage: 3.6723709106445312
+ Number Groundwater Layers: 2
+ Groundwater Storage: 0.43229889136872823
+ Groundwater Storage: 1.5
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 0.002240212732261733
+ Lag Table Flow: 0.002240212732261733
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+ GridCell: 3490,21865
+ Loss: Soil Moisture Account
+ Soil Storage: 1.6355958186173745
+ Number Groundwater Layers: 2
+ Groundwater Storage: 0.03208461245284903
+ Groundwater Storage: 3.0
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 0.01296803998623444
+ Lag Table Flow: 0.01284603101324866
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+ GridCell: 3490,21864
+ Loss: Soil Moisture Account
+ Soil Storage: 4.225638389587402
+ Number Groundwater Layers: 2
+ Groundwater Storage: 0.5342433215407607
+ Groundwater Storage: 2.5
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 0.010820381639851927
+ Lag Table Flow: 0.010820381639851927
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+ GridCell: 3490,21866
+ Loss: Soil Moisture Account
+ Soil Storage: 1.6355958186173745
+ Number Groundwater Layers: 2
+ Groundwater Storage: 0.025055088630458626
+ Groundwater Storage: 3.5
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 0.0025467914276175786
+ Lag Table Flow: 0.0025225504210034527
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+ GridCell: 3491,21866
+ Loss: Soil Moisture Account
+ Soil Storage: 3.740156888961792
+ Number Groundwater Layers: 2
+ Groundwater Storage: 0.1708343510261292
+ Groundwater Storage: 5.5
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 2.684966328935324E-4
+ Lag Table Flow: 2.684966328935324E-4
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+ GridCell: 3490,21863
+ Loss: Soil Moisture Account
+ Soil Storage: 4.225638389587402
+ Number Groundwater Layers: 2
+ Groundwater Storage: 0.5416751881340691
+ Groundwater Storage: 2.0
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 0.008813760335686847
+ Lag Table Flow: 0.008813760335686847
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+ GridCell: 3491,21865
+ Loss: Soil Moisture Account
+ Soil Storage: 1.6355958186173745
+ Number Groundwater Layers: 2
+ Groundwater Storage: 0.03986169816321006
+ Groundwater Storage: 5.0
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 0.001229402537535392
+ Lag Table Flow: 0.0012175929741580981
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+ GridCell: 3491,21863
+ Loss: Soil Moisture Account
+ Soil Storage: 3.8967862129211426
+ Number Groundwater Layers: 2
+ Groundwater Storage: 1.9212463609771424
+ Groundwater Storage: 4.0
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 1.6030003029359727E-4
+ Lag Table Flow: 1.6030003029359727E-4
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+ GridCell: 3491,21864
+ Loss: Soil Moisture Account
+ Soil Storage: 3.8967862129211426
+ Number Groundwater Layers: 2
+ Groundwater Storage: 1.9117279814288
+ Groundwater Storage: 4.5
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 1.856005724496666E-4
+ Lag Table Flow: 1.856005724496666E-4
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+ GridCell: 3489,21865
+ Loss: Soil Moisture Account
+ Soil Storage: 3.6019248962402344
+ Number Groundwater Layers: 2
+ Groundwater Storage: 0.7460371505550496
+ Groundwater Storage: 1.0
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 0.00760024320276418
+ Lag Table Flow: 0.00760024320276418
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+ Baseflow: None
+ End Baseflow
+End:
+
+Reach: Reach-3
+ Route: Lag
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 22.865836383074644
+ Lag Table Flow: 17.10341665595959
+ End Lag Table:
+ End Route:
+End:
diff --git a/model_hec_hms/java/testResources/expected-no-exchange-items.state b/model_hec_hms/java/testResources/expected-no-exchange-items.state
new file mode 100644
index 000000000..41ea9fb23
--- /dev/null
+++ b/model_hec_hms/java/testResources/expected-no-exchange-items.state
@@ -0,0 +1,40 @@
+Snapshot: EndState
+ Run ID: Gridded_DANA2024_BurnMDT
+ Snapshot Time:22 October 2024, 14:00
+ Execution Time: 16 September 2025, 13:21:01
+ Basin Model: Rambla Poyo Burn - Gridded
+ Version: 4.13
+End:
+
+Subbasin: Subbasin-6
+ Loss method: Gridded Soil Moisture Account
+ Transform method: Modified Clark
+ GridCell: 3466,21834
+ Loss: Soil Moisture Account
+ Soil Storage: 1.6355958186173745
+ Number Groundwater Layers: 0
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 3
+ Lag Table First: 2
+ Lag Table Second: 0
+ Lag Table Last: 1
+ Lag Table Flow: 0.011798220206410559
+ Lag Table Flow: 0.012886484547997392
+ Lag Table Flow: 0.010244278335716013
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+End:
+
+Reach: Reach-3
+ Route: Lag
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 22.865836383074644
+ Lag Table Flow: 17.10341665595959
+ End Lag Table:
+ End Route:
+End:
diff --git a/model_hec_hms/java/testResources/no-exchange-items.state b/model_hec_hms/java/testResources/no-exchange-items.state
new file mode 100644
index 000000000..41ea9fb23
--- /dev/null
+++ b/model_hec_hms/java/testResources/no-exchange-items.state
@@ -0,0 +1,40 @@
+Snapshot: EndState
+ Run ID: Gridded_DANA2024_BurnMDT
+ Snapshot Time:22 October 2024, 14:00
+ Execution Time: 16 September 2025, 13:21:01
+ Basin Model: Rambla Poyo Burn - Gridded
+ Version: 4.13
+End:
+
+Subbasin: Subbasin-6
+ Loss method: Gridded Soil Moisture Account
+ Transform method: Modified Clark
+ GridCell: 3466,21834
+ Loss: Soil Moisture Account
+ Soil Storage: 1.6355958186173745
+ Number Groundwater Layers: 0
+ End Loss:
+ Transform: Modified Clark
+ Lag Table Number Flows: 3
+ Lag Table First: 2
+ Lag Table Second: 0
+ Lag Table Last: 1
+ Lag Table Flow: 0.011798220206410559
+ Lag Table Flow: 0.012886484547997392
+ Lag Table Flow: 0.010244278335716013
+ End Lag Table:
+ End Transform:
+ End Grid Cell:
+End:
+
+Reach: Reach-3
+ Route: Lag
+ Lag Table Number Flows: 2
+ Lag Table First: 1
+ Lag Table Second: 0
+ Lag Table Last: 0
+ Lag Table Flow: 22.865836383074644
+ Lag Table Flow: 17.10341665595959
+ End Lag Table:
+ End Route:
+End:
diff --git a/model_hec_hms/java/unit_test_info.txt b/model_hec_hms/java/unit_test_info.txt
new file mode 100644
index 000000000..6f2c136ef
--- /dev/null
+++ b/model_hec_hms/java/unit_test_info.txt
@@ -0,0 +1,6 @@
+#
+# Info for running unit tests when IDE has current directory as startup dir.
+#
+
+ModuleName=model_hec_hms
+UnitTestsRootDir=..
diff --git a/model_hec_hms/model_hec_hms.iml b/model_hec_hms/model_hec_hms.iml
new file mode 100644
index 000000000..e836ef153
--- /dev/null
+++ b/model_hec_hms/model_hec_hms.iml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/model_hec_hms/module.properties b/model_hec_hms/module.properties
new file mode 100644
index 000000000..2b7ff35b7
--- /dev/null
+++ b/model_hec_hms/module.properties
@@ -0,0 +1,32 @@
+#module settings
+module=model_hec_hms
+
+#preferences
+debug=yes
+
+#import stuff from other modules from here
+projectdir=..
+projectlib=bin
+
+#
+# ALL SET TO DEFAULTS - NO NEED TO CHANGE
+#
+srcdir=java/src
+testdir=java/test
+resourcesdir=java/resources
+testresourcesdir=java/testResources
+external=bin_external
+builddir=build
+buildtestdir=build-test
+javadocdir=javadoc
+jarname=${module}.jar
+modulebindir=bin
+modulelibdir=bin
+
+listfiles=no
+failonerror=no
+minmemory=200M
+maxmemory=200M
+
+projectname=OpenDA
+vendor=OpenDA association
diff --git a/model_hec_hms/native/.gitkeep b/model_hec_hms/native/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/model_hec_hms/tests/run_test.sh b/model_hec_hms/tests/run_test.sh
new file mode 100644
index 000000000..f75b5d199
--- /dev/null
+++ b/model_hec_hms/tests/run_test.sh
@@ -0,0 +1,3 @@
+#! /bin/sh
+
+java -cp ../bin/module_hec_hms.jar org.openda.mode_hec_hms.StateFile
diff --git a/model_hec_hms/unit_test_info.txt b/model_hec_hms/unit_test_info.txt
new file mode 100644
index 000000000..e352d416d
--- /dev/null
+++ b/model_hec_hms/unit_test_info.txt
@@ -0,0 +1,6 @@
+#
+# Info for running unit tests when IDE has current directory as startup dir.
+#
+
+ModuleName=model_hec_hms
+UnitTestsRootDir=.
diff --git a/model_hec_hms/xmlSchemas/.gitkeep b/model_hec_hms/xmlSchemas/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/openda.ipr b/openda.ipr
index 0ca6269e8..09af9d886 100644
--- a/openda.ipr
+++ b/openda.ipr
@@ -367,6 +367,7 @@
+