///// <summary> ///// The linkable component that gets the update call should be the only linkable component in a composition that ///// has no output items. For that reason the composition will be able to automatically detect which model is the ///// startup model. If there are more models without output items in a composition the composition is invalid. ///// </summary> ///// <param name="requiredOutputItems">Output Items to do the update for</param> //public LinkableComponentStatus OnUpdate(IOutput[] requiredOutputItems) //{ // if (Status == LinkableComponentStatus.Updating) // { // // Update call that was invoked by bidirectional link // return Status; // } // Status = LinkableComponentStatus.Updating; // foreach (IInput inputItem in Inputs) // { // if (inputItem.Provider != null) // { // // TODO inputItem.TimeSet = TimeSet for input item; get from engine // while (!inputItem.Provider.IsAvailable) // { // inputItem.Provider.Component.Update(); // } // // get and store input // IList providedValues = inputItem.Provider.Values; // LogIncomingValues(inputItem, providedValues); // inputItem.Values = providedValues; // } // } // // compute output / store in output / increment time stored in output // foreach (OutputItem outputItem in outputItems) // { // // TODO get values from Engine // // TODO outputItem.TimeSet = TimeSet for output item; // } // // check if more time stamps need to be done // _currentTime = ((ITimeStamp)_engineApiAccess.GetCurrentTime()).ModifiedJulianDay; // if (_currentTime >= _engineApiAccess.GetTimeHorizon().End.ModifiedJulianDay) // { // return LinkableComponentStatus.Done; // } // return LinkableComponentStatus.Updated; //} protected void LogIncomingValues(EngineInputItem item, IList values) { string message = Caption + " " + item.Caption + " values:"; foreach (double value in values) { message += " " + value; } message += " <= " + item.Provider.Caption + " from " + item.Provider.Component.Caption + ")"; log.Info(message); }
public override void SetEngineValues(EngineInputItem inputItem, IValueSet values) { //--- set input values --- if (inputItem == _InputItem) { _Inpath = (string)values.GetValue(0, 0); } else { throw new ArgumentException("Unknown Input Item Id: \"" + inputItem.Id + "\"", "inputItem"); } }
public override void SetEngineValues(EngineInputItem inputItem, ITimeSpaceValueSet values) { int elementCount = ValueSet.GetElementCount(values); double[] avalues = new double[elementCount]; for (int i = 0; i < elementCount; i++) { avalues[i] = (double)values.GetValue(0, i); } ScalarSet scalarSet = new ScalarSet(avalues); _engineApiAccess.SetValues(inputItem.ValueDefinition.Caption, inputItem.SpatialDefinition.Caption, scalarSet); }
protected void LogIncomingValues(EngineInputItem inputItem, IList providedValues) { string message = Caption + " " + inputItem.Caption + " values:"; foreach (double value in providedValues) { message += " " + value; } message += " <= " + inputItem.Provider.Caption + " from " + inputItem.Provider.Component.Caption + ")"; Console.Out.WriteLine(message); Console.Out.Flush(); }
public override void SetEngineValues(EngineInputItem inputItem, ITimeSpaceValueSet values) { if (inputItem == _storageInput) { IList elementValues = values.GetElementValuesForTime(0); for (int i = 0; i < _storage.Length; i++) { _storage[i] = (double)elementValues[i]; } } else if (inputItem == _firstElementStorageInput) { _storage[0] = (double)values.GetValue(0, 0); } else { throw new ArgumentException("Unknown Input Item Id: \"" + inputItem.Id + "\"", "inputItem"); } }
public override void SetEngineValues(EngineInputItem inputItem, ITimeSpaceValueSet values) { IQuantity quantity = inputItem.ValueDefinition as IQuantity; if (quantity == null) { throw new ArgumentException("Can only accept quantity as valuedefinition", "inputItem"); } if (quantity.Caption == "InFlow" && inputItem.SpatialDefinition.Caption == "AllBranches") { for (int i = 0; i < _simpleRiverEngine.GetNumberOfNodes(); i++) { _simpleRiverEngine.AddInflow(i, (double)values.GetValue(0, i)); } } else { throw new ArgumentException("Unknown quantity/elementSet combination", "inputItem"); } }
private void StoreInputValuesInComputationalCore(EngineInputItem inputItem, ITimeSpaceValueSet values) { char[] separator = new[] { ':' }; string[] subStrings = inputItem.SpatialDefinition.Caption.Split(separator); if (inputItem.Id.Equals("WholeRiver.Flow")) { // values are numberOfNodes-1 long (input for each branch. // Put inflow at "upstream" node/storage for (int i = 0; i < _inflowStorage.Length - 1; i++) { _inflowStorage[i] += ((double)values.GetValue(0, i)) * _timeStepLengthInSeconds; } } else if (subStrings[0] == "Node") { int nodeIndex = Convert.ToInt32(subStrings[1]); _inflowStorage[nodeIndex] += ((double)values.GetValue(0, 0)) * _timeStepLengthInSeconds; } else { throw new ArgumentException("Unknown Input Item Id: \"" + inputItem.Id + "\"", "inputItem"); } }
public override void Initialize(IArgument[] arguments) { //set component to run in loop mode this.CascadingUpdateCallsDisabled = true; Status = LinkableComponentStatus.Initializing; //read arguments foreach (IArgument entry in arguments) { if (entry.Id == "ElevationSurface") { _Inpath = Path.GetFullPath(entry.Value.ToString()); } else if (entry.Id == "OutputFile") { _outpath = Path.GetFullPath(entry.Value.ToString()); } } // -- Time settings for input and output exchange items -- ITime timeHorizon = new Time(StartTime, EndTime); //Create input element set Element e = new Element("Elevation Surface"); e.Id = "Elevation Surface"; ElementSet eSet = new ElementSet("Elevation Surface", "Elevation Surface", ElementType.IdBased); eSet.AddElement(e); Quantity quantity = new Quantity(new Unit("Raster", 1.0, 0.0, "Raster"), "Elevation Surface", "Elevation Surface"); //add input item _InputItem = new EngineEInputItem("ElevationSurface", quantity, eSet, this); //_InputItem.StoreValuesInExchangeItem = true; _InputItem.SetTimeHorizon(timeHorizon); this.EngineInputItems.Add(_InputItem); _InputItem.SetSingleTime(StartTime); //add input exchange item to input item list _inputs.Add(_InputItem); //create output element set e = new Element("Filled Surface"); e.Id = "Filled Surface"; eSet = new ElementSet("Filled Surface", "Filled Surface", ElementType.IdBased); eSet.AddElement(e); quantity = new Quantity(new Unit("Raster", 1.0, 0.0, "Raster"), "Filled Surface", "Filled Surface"); //add output item _OutputItem = new EngineEOutputItem("Filled Surface", quantity, eSet, this); _OutputItem.SetSingleTime(StartTime); //_OutputItem.StoreValuesInExchangeItem = true; _OutputItem.SetTimeHorizon(timeHorizon); this.EngineOutputItems.Add(_OutputItem); //add output exchange item to output item list _outputs.Add(_OutputItem); //initialize geoprocessing objects GP = new Geoprocessor(); GP.OverwriteOutput = true; //checkout spatial analyst license esriLicenseStatus LicenseStatus = esriLicenseStatus.esriLicenseUnavailable; LicenseStatus = license.Initialize(esriLicenseProductCode.esriLicenseProductCodeArcInfo); LicenseStatus = license.CheckOutExtension(esriLicenseExtensionCode.esriLicenseExtensionCodeSpatialAnalyst); Status = LinkableComponentStatus.Initialized; }
public override void SetEngineValues(EngineInputItem inputItem, ITimeSpaceValueSet values) { StoreInputValuesInComputationalCore(inputItem, values); }
public override void Initialize() { Status = LinkableComponentStatus.Initializing; // Handle arguments IDictionary <string, IArgument> argDict = Arguments.Dictionary(); Id = argDict.GetValue <string>("ModelId"); this.Caption = "RiverModel Default Model"; _flowItemsAsSpan = argDict.GetValue <bool>("FlowItemsAsSpan"); _storeValuesInItem = argDict.GetValue <bool>("StoreValuesInExchangeitems"); _timeStepLengthInSeconds = argDict.GetValue <double>("TimestepLength"); _timeStepLengthInDays = _timeStepLengthInSeconds / (24.0 * 3600.0); double xyscale = argDict.GetValue <double>("xyscale"); double xOffset = argDict.GetValue <double>("xoffset"); double yOffset = argDict.GetValue <double>("yoffset"); for (int i = 0; i < _numberOfNodes; i++) { _xCoordinate[i] = xyscale * _xCoordinate[i] + xOffset; _yCoordinate[i] = xyscale * _yCoordinate[i] + yOffset; } // -- create a flow quantity -- Dimension flowDimension = new Dimension(); flowDimension.SetPower(DimensionBase.Length, 3); flowDimension.SetPower(DimensionBase.Time, -1); Unit literPrSecUnit = new Unit("LiterPrSecond", 0.001, 0, "Liters pr Second"); Quantity flowQuantity = new Quantity(literPrSecUnit, "Flow", "Flow"); Quantity leakageQuantity = new Quantity(literPrSecUnit, "Leakage", "Leakage"); // -- create a ground water level quantity -- Dimension levelDimension = new Dimension(); levelDimension.SetPower(DimensionBase.Length, 1); Unit levelUnit = new Unit("GroundWaterLevel", 1, 0, "Ground water level"); levelUnit.Dimension = levelDimension; Quantity levelQuantity = new Quantity(levelUnit, "Ground water level", "Ground Water level"); // -- Time settings for input and output exchange items -- ITime timeHorizon = new Time(StartTime, EndTime); // -- create and populate elementset to represent all branches, links betwen nodes in the river network -- LineString fullRiverLineString = new LineString { Coordinates = GeometryFactory.CreateCoordinateList(_xCoordinate, _yCoordinate), Caption = "WholeRiver", Description = "WholeRiver", IsClosed = false, IsNodeBased = false, }; IElementSet fullRiverElementSet = new LineStringWrapper(fullRiverLineString); // --- populate input exchange items for flow to individual nodes, id-based --- for (int i = 0; i < _numberOfNodes; i++) { string id = "Node:" + i; ElementSet elementSet = new ElementSet(id, id, ElementType.IdBased); elementSet.AddElement(new Element(id)); EngineInputItem inputExchangeItem = CreateInputInflowToOneNode(i, id, flowQuantity, elementSet); inputExchangeItem.StoreValuesInExchangeItem = true; // Item is adding up, therefor store in item inputExchangeItem.TimeSet.SetTimeHorizon(timeHorizon); EngineInputItems.Add(inputExchangeItem); } // --- Populate input exchange item for flow into the whole river --- EngineInputItem wholeRiverFlowInputItem = CreateInputInflowToRiver(flowQuantity, fullRiverElementSet); wholeRiverFlowInputItem.TimeSet.SetTimeHorizon(timeHorizon); EngineInputItems.Add(wholeRiverFlowInputItem); // --- Populate input exchange item for ground water level of the whole river --- EngineDInputItem gwLevelInputItem = CreateInputGwLevel(levelQuantity, fullRiverElementSet); gwLevelInputItem.TimeSet.SetTimeHorizon(timeHorizon); EngineInputItems.Add(gwLevelInputItem); // --- Populate output exchange items for flow in river branches, id based --- for (int i = 0; i < _numberOfNodes - 1; i++) { string id = "Branch:" + i; ElementSet elementSet = new ElementSet(id, id, ElementType.IdBased); elementSet.AddElement(new Element(id)); EngineOutputItem outputExchangeItem = CreateOutputFlowInBranch(i, id, flowQuantity, elementSet); EngineOutputItems.Add(outputExchangeItem); } // --- populate output exchange items for leakage for individual branches -- for (int i = 0; i < _numberOfNodes - 1; i++) { string id = "Branch:" + i; ElementSet elementSet = new ElementSet(id, id, ElementType.IdBased); elementSet.AddElement(new Element(id)); EngineOutputItem outputExchangeItem = CreateOutputLeakageInBranch(i, id, leakageQuantity, elementSet); EngineOutputItems.Add(outputExchangeItem); } // --- Populate output exchange item for leakage from the whole georeferenced river --- EngineOutputItem wholeRiverOutputExchangeItem = CreateOuputLeakageInRiver(leakageQuantity, fullRiverElementSet); EngineOutputItems.Add(wholeRiverOutputExchangeItem); // --- Populate output exchange item for flow from the whole georeferenced river --- EngineOutputItem wholeRiverFlowOutputExchangeItem = CreateOutputFlowInRiver(flowQuantity, fullRiverElementSet); EngineOutputItems.Add(wholeRiverFlowOutputExchangeItem); // --- populate with initial state variables --- for (int i = 0; i < _numberOfNodes - 1; i++) { _flow[i] = 7; } foreach (EngineInputItem engineInputItem in EngineInputItems) { // TODO: Overwrites existing timeset, which has already had the time horizon set? engineInputItem.TimeSet = new TimeSet() { HasDurations = _flowItemsAsSpan }; } foreach (EngineOutputItem engineOutputItem in EngineOutputItems) { // TODO: Overwrites existing timeset, which has already had the time horizon set? engineOutputItem.TimeSet = new TimeSet() { HasDurations = _flowItemsAsSpan }; } Status = LinkableComponentStatus.Initialized; }
public override void Initialize() { Status = LinkableComponentStatus.Initializing; ReadArguments(); // Initialize storage vector _storage = new double[NumberOfElements]; for (int i = 0; i < NumberOfElements; i++) { _storage[i] = 0; } // -- Populate Exchange Items --- // Element set for a grid based (polygons) item Spatial2DRegularGrid regularGrid = new Spatial2DRegularGrid() { Description = "RegularGrid", Caption = "RegularGrid", Dx = _dx, Dy = _dy, X0 = _x0, Y0 = _y0, XCount = _xCount, YCount = _yCount, Orientation = _orientation, IsNodeBased = false, }; Spatial2DGridWrapper regularElmtSet = new Spatial2DGridWrapper(regularGrid); // Element set for a Polygon based item, of the lower left cell in the grid Element element0 = new Element("element:0"); element0.AddVertex(new Coordinate(_x0, _y0, 0)); element0.AddVertex(new Coordinate(_x0 + _dx, _y0, 0)); element0.AddVertex(new Coordinate(_x0 + _dx, _y0 + _dy, 0)); element0.AddVertex(new Coordinate(_x0, _y0 + _dy, 0)); // Element set for an ID based item, of the lower left cell in the grid ElementSet idSet = new ElementSet("FirstElement", "FirstElement", ElementType.IdBased); idSet.AddElement(element0); // is an IdBased set required to have elements? // Dimensions Dimension dimVolume = new Dimension(); dimVolume.SetPower(DimensionBase.Length, 3); Dimension dimLength = new Dimension(); dimLength.SetPower(DimensionBase.Length, 1); Dimension dimDischarge = new Dimension(); dimDischarge.SetPower(DimensionBase.Length, 3); dimDischarge.SetPower(DimensionBase.Time, -1); // Units Unit unitLiterStorage = new Unit("Storage", 0.001, 0.0, "Storage"); unitLiterStorage.Dimension = dimVolume; Unit unitGwLevel = new Unit("gw level", 1.0, 0.0, "Ground water level"); unitGwLevel.Dimension = dimLength; Unit unitDischarge = new Unit("Discharge", 0.001, 0, "Discharge into ground water model, [L/s]"); unitDischarge.Dimension = dimDischarge; // Quantities Quantity quantityStorage = new Quantity(unitLiterStorage, "Storage", "Storage"); Quantity quantityGwLevel = new Quantity(unitGwLevel, "Ground water level", "Ground water level"); Quantity quantityInflow = new Quantity(unitDischarge, "Inflow into ground water model", "Inflow"); // Storage input on the grid _storageInput = new EngineEInputItem("Grid.Storage", quantityStorage, regularElmtSet, this); _firstElementStorageInput = new EngineEInputItem("FirstElement.Storage", quantityStorage, idSet, this); // Storage output on the grid _storageOutput = new EngineEOutputItem("Grid.Storage", quantityStorage, regularElmtSet, this); _storageOutput.TimeSet.SetSingleTime(StartTime); _storageOutput.TimeSet.SetTimeHorizon(new Time(StartTime, EndTime)); // Storage output in the first element of the grid _firstElementStorageOutput = new EngineEOutputItem("FirstElement.Storage", quantityStorage, idSet, this); _firstElementStorageOutput.TimeSet.SetSingleTime(StartTime); _firstElementStorageOutput.TimeSet.SetTimeHorizon(new Time(StartTime, EndTime)); // Ground water level output. Calculated as (_gwBaseLevel + 0.1*storage height), assuming that the // water can populate 10% of the ground volume. EngineDOutputItem gwLevelOutput = new EngineDOutputItem("Grid.gwLevel", quantityGwLevel, regularElmtSet, this); gwLevelOutput.StoreValuesInExchangeItem = false; gwLevelOutput.ValueGetter = delegate() { IList <double> res = new List <double>(NumberOfElements); for (int i = 0; i < NumberOfElements; i++) { // Convert storage from liters to m3 and find the height. double storageHeight = 0.001 * _storage[i] / (_dx * _dy); res.Add(_gwBaseLevel + 10 * storageHeight); } return(new ValueSet(new List <IList> { (IList)res })); }; // Ground water inflow in the grid EngineDInputItem gwInflow = new EngineDInputItem("Grid.Inflow", quantityInflow, regularElmtSet, this); gwInflow.ValueSetter = delegate(ITimeSpaceValueSet values) { IList elmtValues = values.GetElementValuesForTime(0); for (int i = 0; i < NumberOfElements; i++) { // Values arrive in [L/s], storage is in liters. _storage[i] += (double)elmtValues[i] * _timeStepLengthInSeconds; if (_storage[i] < 0) // inflow can be negative, but storage can not be zero. Mass error here :-( { _storage[i] = 0; } } }; EngineOutputItems.Add(_storageOutput); EngineOutputItems.Add(_firstElementStorageOutput); EngineOutputItems.Add(gwLevelOutput); EngineInputItems.Add(_storageInput); EngineInputItems.Add(_firstElementStorageInput); if (_useMultiInput) { EngineInputItems.Add(new EngineMultiInputItemWrapper(gwInflow, this)); } else { EngineInputItems.Add(gwInflow); } Status = LinkableComponentStatus.Initialized; }