scrollbar |
---|
Exercise outline
The goal of this exercise is to create a simple hydrological volume model. In the end, it should be possible to run the volume model and inspect some (very simple) spatio-temporal output results.
...
Code Block |
---|
using System;
using System.Linq;
using DelftTools.Functions;
using DelftTools.Functions.Generic;
using DelftTools.Shell.Core.Workflow;
using DelftTools.Shell.Core.Workflow.DataItems;
using GeoAPI.Extensions.Feature;
using GeoAPI.Geometries;
using NetTopologySuite.Extensions.Coverages;
namespace DeltaShell.Plugins.VolumeModel.Models
{
public class VolumeModel : ModelBase
{
private readonly DrainageBasin basin;
private readonly TimeSeries precipitation;
private readonly FeatureCoverage volume;
/// <summary>
/// Creates a volume model
/// </summary>
public VolumeModel()
{
// Create the input items of the volume model
basin = new DrainageBasin();
precipitation = new TimeSeries { Components = { new Variable<double>("Precipitation") } };
// Create the output item of the volume model
volume = new FeatureCoverage("Output data")
{
IsTimeDependent = true,
Arguments = { new Variable<IFeature>("Catchment") { FixedSize = 0 } },
Components = { new Variable<double>("Volume") },
};
// Wrap fields as input/output data items
DataItems.Add(new DataItem(precipitation, "Precipitation", typeof(TimeSeries), DataItemRole.Input, "PrecipitationTag"));
DataItems.Add(new DataItem(basin, "Basin", typeof(DrainageBasin), DataItemRole.Input, "BasinTag"));
DataItems.Add(new DataItem(volume, "Volume", typeof(FeatureCoverage), DataItemRole.Output, "VolumeTag"));
}
/// <summary>
/// The precipitation time series: P = P(t) [L/T]. Input of the model.
/// </summary>
public TimeSeries Precipitation
{
get { return precipitation; }
}
/// <summary>
/// The drainage basin (set of catchments). Input of the model.
/// </summary>
public DrainageBasin Basin
{
get { return basin; }
}
/// <summary>
/// Time-dependent feature coverage containing the volume of water per catchment: V = V(t, c) [L3/T]. Output of the model.
/// </summary>
public FeatureCoverage Volume
{
get { return volume; }
}
/// <summary>
/// The initialization of model runs
/// </summary>
protected override void OnInitialize()
{
// Clear any previous output
volume.Clear();
// Ensure the coordinate system of the volume output is the same as the catchments input (basin)
volume.CoordinateSystem = (GeoAPI.Extensions.CoordinateSystems.ICoordinateSystem) basin.CoordinateSystem;
// Ensure at least one catchment and one precipitation value is present
ValidateInputData();
// Initialize the output feature coverage
volume.Features.AddRange(basin.Catchments);
volume.FeatureVariable.FixedSize = basin.Catchments.Count();
volume.FeatureVariable.AddValues(basin.Catchments);
}
/// <summary>
/// The actual calculation during model run
/// </summary>
protected override void OnExecute()
{
// Loop all times
foreach (var time in precipitation.Time.Values)
{
// Obtain the precipitation value for the current time
var p = (double)precipitation[time];
// Calculate a volume value for every catchment based on catchment area and precipitation value
var volumes = basin.Catchments.Select(f => f.Geometry).Select(pol => pol.Area * p);
// Add the calculated volume values to the output feature coverage
volume[time] = volumes;
}
Status = ActivityStatus.Done;
}
private void ValidateInputData()
{
var hasCatchments = basin.Catchments.Any();
var hasPrecipitationData = precipitation.Time.Values.Any();
if (!hasCatchments && !hasPrecipitationData)
{
throw new InvalidOperationException("At least one catchment and one precipitation value should be present");
}
if (!hasCatchments)
{
throw new InvalidOperationException("At least one catchment should be present");
}
if (! basin.Catchments.All(c => c.Geometry is IPolygon || c.Geometry is IMultiPolygon))
{
throw new InvalidOperationException("All catchment features should be polygons");
}
if (!hasPrecipitationData)
{
throw new InvalidOperationException("At least one precipitation value should be present");
}
}
}
} |
...
Info |
---|
In order to inspect time dependent (output) data, open the Time Navigator window and move the slider or click one of the play buttons: |
scrollbar |
---|