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 @@ +