|
| 1 | +using Test |
| 2 | +using OrderedCollections |
| 3 | + |
| 4 | +using CSV, YAML |
| 5 | +using Dates |
| 6 | +using DataFrames |
| 7 | +using Streamfall |
| 8 | + |
| 9 | + |
| 10 | +@testset "Running nodes with interactions" begin |
| 11 | + # Load a network from a file, providing a name for the network and the file path. |
| 12 | + # Creates a graph representation of the stream with associated metadata. |
| 13 | + sn = load_network("Example Network", "../test/data/campaspe/campaspe_network.yml") |
| 14 | + |
| 15 | + # Load climate data, in this case from a CSV file with data for all nodes. |
| 16 | + climate_data = CSV.read( |
| 17 | + "../test/data/campaspe/climate/climate_historic.csv", DataFrame, |
| 18 | + comment="#", |
| 19 | + dateformat="YYYY-mm-dd" |
| 20 | + ) |
| 21 | + |
| 22 | + # Indicate which columns are precipitation and evaporation data based on partial identifiers |
| 23 | + climate = Climate(climate_data, "_rain", "_evap") |
| 24 | + |
| 25 | + run_catchment!(sn, climate) |
| 26 | + node_id, node = sn["406219"] |
| 27 | + |
| 28 | + # Run up to a point in the stream for all time steps. |
| 29 | + # All nodes upstream will be run as well (but not those downstream) |
| 30 | + run_node!(sn, node_id, climate) |
| 31 | + |
| 32 | + baseline_outflow = node.outflow |
| 33 | + |
| 34 | + # Reset a node (clears stored states) |
| 35 | + reset!(node) |
| 36 | + |
| 37 | + # Run a specific node, and only a specific node, for all time steps |
| 38 | + inflow = 10.0 # inflows for each time step |
| 39 | + extractions = 0.0 # extractions from stream for each time step |
| 40 | + gw_flux = 0.0 # forced groundwater interactions for each time step |
| 41 | + run_node!(node, climate; inflow=inflow, extraction=extractions, exchange=gw_flux) |
| 42 | + perturbed1 = node.outflow |
| 43 | + |
| 44 | + reset!(node) |
| 45 | + inflow = 10.0 # inflows for each time step |
| 46 | + extractions = 5.0 # extractions from stream for each time step |
| 47 | + gw_flux = 0.0 # forced groundwater interactions for each time step |
| 48 | + run_node!(node, climate; inflow=inflow, extraction=extractions, exchange=gw_flux) |
| 49 | + perturbed2 = node.outflow |
| 50 | + |
| 51 | + reset!(sn) |
| 52 | + inflow = 10.0 # inflows for each time step |
| 53 | + extractions = 5.0 # extractions from stream for each time step |
| 54 | + gw_flux = 2.0 # forced groundwater interactions for each time step |
| 55 | + inlets, outlets = find_inlets_and_outlets(sn) |
| 56 | + |
| 57 | + # Manual interactions |
| 58 | + timesteps = sim_length(climate) |
| 59 | + prep_state!(sn, timesteps) |
| 60 | + for ts in (1:timesteps) |
| 61 | + for outlet in outlets |
| 62 | + run_node!(sn[outlet], climate, ts; inflow=inflow, extraction=extractions, exchange=gw_flux) |
| 63 | + end |
| 64 | + end |
| 65 | + |
| 66 | + node_id, node = sn["406219"] |
| 67 | + perturbed3 = node.outflow |
| 68 | + |
| 69 | + @info length(baseline_outflow) length(perturbed1) length(perturbed2) length(perturbed3) |
| 70 | + @info all((baseline_outflow .+ 10.0) .== perturbed1) |
| 71 | + @info sum((baseline_outflow .+ 10.0) .- perturbed1) |
| 72 | + |
| 73 | + @test all(baseline_outflow .!= perturbed1 .!= perturbed2 .!= perturbed3) || "Perturbations resulted in identical streamflows" |
| 74 | + |
| 75 | + # Check that additional interactions are accounted for. |
| 76 | + # Cannot check for equivalence due to computational error, so we test that the |
| 77 | + # difference is within acceptable bounds. |
| 78 | + @test all((baseline_outflow .+ 10.0 .- perturbed1) .< 0.0005) || "Additional inflow not accounted for" |
| 79 | + @test all((baseline_outflow .+ 5.0 .- perturbed2) .< 0.0005) || "Extractions not accounted for" |
| 80 | +end |
| 81 | + |
0 commit comments