def supplier_elements(self): """A |Elements| collection of all "supplying" basins. (All river basins are assumed to supply something to the downstream basin.) >>> from hydpy import RiverBasinNumbers2Selection >>> rbns2s = RiverBasinNumbers2Selection( ... (111, 113, 1129, 11269, 1125, 11261, ... 11262, 1123, 1124, 1122, 1121)) The following elements are properly connected to the required outlet nodes already: >>> for element in rbns2s.supplier_elements: ... print(repr(element)) Element("land_111", outlets="node_113") Element("land_1121", outlets="node_1123") Element("land_1122", outlets="node_1123") Element("land_1123", outlets="node_1125") Element("land_1124", outlets="node_1125") Element("land_1125", outlets="node_1129") Element("land_11261", outlets="node_11269") Element("land_11262", outlets="node_11269") Element("land_11269", outlets="node_1129") Element("land_1129", outlets="node_113") Element("land_113", outlets="node_outlet") It is both possible to change the prefix names of the elements and nodes, as long as it results in a valid variable name (e.g. does not start with a number): >>> rbns2s.supplier_prefix = 'a_' >>> rbns2s.node_prefix = 'b_' >>> rbns2s.supplier_elements Elements("a_111", "a_1121", "a_1122", "a_1123", "a_1124", "a_1125", "a_11261", "a_11262", "a_11269", "a_1129", "a_113") """ elements = devicetools.Elements() for supplier in self._supplier_numbers: element = self._get_suppliername(supplier) try: outlet = self._get_nodename(self._up2down[supplier]) except TypeError: outlet = self.last_node elements += devicetools.Element(element, outlets=outlet) return elements
def supplier_elements(self) -> devicetools.Elements: """An |Elements| object containing all "supplying basins". (All river basins are assumed to supply something to the downstream basin.) >>> from hydpy import RiverBasinNumbers2Selection >>> rbns2s = RiverBasinNumbers2Selection( ... (111, 113, 1129, 11269, 1125, 11261, ... 11262, 1123, 1124, 1122, 1121)) The following elements are correctly connected to the required outlet nodes already: >>> for element in rbns2s.supplier_elements: ... print(repr(element)) Element("land_111", outlets="node_113") Element("land_1121", outlets="node_1123") Element("land_1122", outlets="node_1123") Element("land_1123", outlets="node_1125") Element("land_1124", outlets="node_1125") Element("land_1125", outlets="node_1129") Element("land_11261", outlets="node_11269") Element("land_11262", outlets="node_11269") Element("land_11269", outlets="node_1129") Element("land_1129", outlets="node_113") Element("land_113", outlets="node_outlet") It is both possible to change the prefix names of the elements and nodes: >>> rbns2s.supplier_prefix = "a_" >>> rbns2s.node_prefix = "b_" >>> rbns2s.supplier_elements Elements("a_111", "a_1121", "a_1122", "a_1123", "a_1124", "a_1125", "a_11261", "a_11262", "a_11269", "a_1129", "a_113") """ elements = devicetools.Elements() for supplier in self._supplier_numbers: element = self._get_suppliername(supplier) try: outlet = self._get_nodename(self._up2down[supplier]) except TypeError: outlet = self.last_node elements += devicetools.Element(element, outlets=outlet) return elements
def router_elements(self) -> devicetools.Elements: """An |Elements| object containing all "routing basins". (Only river basins with an upstream basin are assumed to route something to the downstream basin.) >>> from hydpy import RiverBasinNumbers2Selection >>> rbns2s = RiverBasinNumbers2Selection( ... (111, 113, 1129, 11269, 1125, 11261, ... 11262, 1123, 1124, 1122, 1121)) The following elements are correctly connected to the required inlet and outlet nodes already: >>> for element in rbns2s.router_elements: ... print(repr(element)) Element("stream_1123", inlets="node_1123", outlets="node_1125") Element("stream_1125", inlets="node_1125", outlets="node_1129") Element("stream_11269", inlets="node_11269", outlets="node_1129") Element("stream_1129", inlets="node_1129", outlets="node_113") Element("stream_113", inlets="node_113", outlets="node_outlet") It is both possible to change the prefix names of the elements and nodes: >>> rbns2s.router_prefix = "c_" >>> rbns2s.node_prefix = "d_" >>> rbns2s.router_elements Elements("c_1123", "c_1125", "c_11269", "c_1129", "c_113") """ elements = devicetools.Elements() for router in self._router_numbers: element = self._get_routername(router) inlet = self._get_nodename(router) try: outlet = self._get_nodename(self._up2down[router]) except TypeError: outlet = self.last_node elements += devicetools.Element(element, inlets=inlet, outlets=outlet) return elements
def prepare_io_example_1() -> Tuple[devicetools.Nodes, devicetools.Elements]: """Prepare an IO example configuration for testing purposes. Function |prepare_io_example_1| is thought for testing the functioning of *HydPy* and thus should be of interest for framework developers only. It uses the application models |lland_v1| and |lland_v2|. Here, we apply |prepare_io_example_1| and shortly discuss different aspects of the data it generates. >>> from hydpy.examples import prepare_io_example_1 >>> nodes, elements = prepare_io_example_1() (1) It defines a short initialisation period of five days: >>> from hydpy import pub >>> pub.timegrids Timegrids("2000-01-01 00:00:00", "2000-01-05 00:00:00", "1d") (2) It creates a flat IO testing directory structure: >>> pub.sequencemanager.inputdirpath 'inputpath' >>> pub.sequencemanager.fluxdirpath 'outputpath' >>> pub.sequencemanager.statedirpath 'outputpath' >>> pub.sequencemanager.nodedirpath 'nodepath' >>> import os >>> from hydpy import TestIO >>> with TestIO(): ... print(sorted(filename for filename in os.listdir(".") ... if not filename.startswith("_"))) ['inputpath', 'nodepath', 'outputpath'] (3) It returns three |Element| objects handling either application model |lland_v1| or |lland_v2|, and two |Node| objects handling variables `Q` and `T`: >>> for element in elements: ... print(element.name, element.model) element1 lland_v1 element2 lland_v1 element3 lland_v2 >>> for node in nodes: ... print(node.name, node.variable) node1 Q node2 T (4) It generates artificial time series data of the input sequence |lland_inputs.Nied|, the flux sequence |lland_fluxes.NKor|, and the state sequence |lland_states.BoWa| of each model instance, and the |Sim| sequence of each node instance. For unambiguous test results, all generated values are unique: >>> nied1 = elements.element1.model.sequences.inputs.nied >>> nied1.series InfoArray([ 0., 1., 2., 3.]) >>> nkor1 = elements.element1.model.sequences.fluxes.nkor >>> nkor1.series InfoArray([[ 12.], [ 13.], [ 14.], [ 15.]]) >>> bowa3 = elements.element3.model.sequences.states.bowa >>> bowa3.series InfoArray([[ 48., 49., 50.], [ 51., 52., 53.], [ 54., 55., 56.], [ 57., 58., 59.]]) >>> sim2 = nodes.node2.sequences.sim >>> sim2.series InfoArray([ 64., 65., 66., 67.]) (5) All sequences carry |numpy.ndarray| objects with (deep) copies of the time series data for testing: >>> import numpy >>> (numpy.all(nied1.series == nied1.testarray) and ... numpy.all(nkor1.series == nkor1.testarray) and ... numpy.all(bowa3.series == bowa3.testarray) and ... numpy.all(sim2.series == sim2.testarray)) InfoArray(True, dtype=bool) >>> bowa3.series[1, 2] = -999.0 >>> numpy.all(bowa3.series == bowa3.testarray) InfoArray(False, dtype=bool) """ testtools.TestIO.clear() hydpy.pub.sequencemanager = filetools.SequenceManager() with testtools.TestIO(): hydpy.pub.sequencemanager.inputdirpath = "inputpath" hydpy.pub.sequencemanager.fluxdirpath = "outputpath" hydpy.pub.sequencemanager.statedirpath = "outputpath" hydpy.pub.sequencemanager.nodedirpath = "nodepath" hydpy.pub.timegrids = "2000-01-01", "2000-01-05", "1d" node1 = devicetools.Node("node1") node2 = devicetools.Node("node2", variable="T") nodes = devicetools.Nodes(node1, node2) element1 = devicetools.Element("element1", outlets=node1) element2 = devicetools.Element("element2", outlets=node1) element3 = devicetools.Element("element3", outlets=node1) elements = devicetools.Elements(element1, element2, element3) element1.model = importtools.prepare_model("lland_v1") element2.model = importtools.prepare_model("lland_v1") element3.model = importtools.prepare_model("lland_v2") for idx, element in enumerate(elements): parameters = element.model.parameters parameters.control.nhru(idx + 1) parameters.control.lnk(lland.ACKER) parameters.derived.absfhru(10.0) # pylint: disable=not-callable # pylint usually understands that all options are callable # but, for unknown reasons, not in the following line: with hydpy.pub.options.printprogress(False): nodes.prepare_simseries() elements.prepare_inputseries() elements.prepare_fluxseries() elements.prepare_stateseries() # pylint: enable=not-callable def init_values(seq, value1_): value2_ = value1_ + len(seq.series.flatten()) values_ = numpy.arange(value1_, value2_, dtype=float) seq.testarray = values_.reshape(seq.seriesshape) seq.series = seq.testarray.copy() return value2_ value1 = 0 for subname, seqname in zip(["inputs", "fluxes", "states"], ["nied", "nkor", "bowa"]): for element in elements: subseqs = getattr(element.model.sequences, subname) value1 = init_values(getattr(subseqs, seqname), value1) for node in nodes: value1 = init_values(node.sequences.sim, value1) return nodes, elements
def prepare_io_example_1() -> Tuple[devicetools.Nodes, devicetools.Elements]: """Prepare an IO example configuration for testing purposes. Function |prepare_io_example_1| is thought for testing the functioning of *HydPy* and thus should be of interest for framework developers only. It uses the application models |lland_v1|, |lland_v2|, and |hland_v1|. Here, we apply |prepare_io_example_1| and shortly discuss different aspects of its generated data. >>> from hydpy.examples import prepare_io_example_1 >>> nodes, elements = prepare_io_example_1() (1) It defines a short initialisation period of five days: >>> from hydpy import pub >>> pub.timegrids Timegrids("2000-01-01 00:00:00", "2000-01-05 00:00:00", "1d") (2) It prepares an empty directory for IO testing: >>> import os >>> from hydpy import repr_, TestIO >>> with TestIO(): # doctest: +ELLIPSIS ... repr_(pub.sequencemanager.currentpath) ... os.listdir("project/series/default") '...iotesting/project/series/default' [] (3) It returns four |Element| objects handling either application model |lland_v1| |lland_v2|, or |hland_v1|, and two |Node| objects handling variables `Q` and `T`: >>> for element in elements: ... print(element.name, element.model) element1 lland_v1 element2 lland_v1 element3 lland_v2 element4 hland_v1 >>> for node in nodes: ... print(node.name, node.variable) node1 Q node2 T (4) It generates artificial time series data for the input sequence |lland_inputs.Nied|, the flux sequence |lland_fluxes.NKor|, and the state sequence |lland_states.BoWa| of each |lland| model instance, the state sequence |hland_states.SP| of the |hland_v1| model instance, and the |Sim| sequence of each node instance. For precise test results, all generated values are unique: >>> nied1 = elements.element1.model.sequences.inputs.nied >>> nied1.series InfoArray([0., 1., 2., 3.]) >>> nkor1 = elements.element1.model.sequences.fluxes.nkor >>> nkor1.series InfoArray([[12.], [13.], [14.], [15.]]) >>> bowa3 = elements.element3.model.sequences.states.bowa >>> bowa3.series InfoArray([[48., 49., 50.], [51., 52., 53.], [54., 55., 56.], [57., 58., 59.]]) >>> sim2 = nodes.node2.sequences.sim >>> sim2.series InfoArray([64., 65., 66., 67.]) >>> sp4 = elements.element4.model.sequences.states.sp >>> sp4.series InfoArray([[[68., 69., 70.], [71., 72., 73.]], <BLANKLINE> [[74., 75., 76.], [77., 78., 79.]], <BLANKLINE> [[80., 81., 82.], [83., 84., 85.]], <BLANKLINE> [[86., 87., 88.], [89., 90., 91.]]]) (5) All sequences carry |numpy.ndarray| objects with (deep) copies of the time-series data for testing: >>> import numpy >>> (numpy.all(nied1.series == nied1.testarray) and ... numpy.all(nkor1.series == nkor1.testarray) and ... numpy.all(bowa3.series == bowa3.testarray) and ... numpy.all(sim2.series == sim2.testarray) and ... numpy.all(sp4.series == sp4.testarray)) InfoArray(True) >>> bowa3.series[1, 2] = -999.0 >>> numpy.all(bowa3.series == bowa3.testarray) InfoArray(False) """ testtools.TestIO.clear() hydpy.pub.projectname = "project" hydpy.pub.sequencemanager = filetools.SequenceManager() with testtools.TestIO(): os.makedirs("project/series/default") hydpy.pub.timegrids = "2000-01-01", "2000-01-05", "1d" node1 = devicetools.Node("node1") node2 = devicetools.Node("node2", variable="T") nodes = devicetools.Nodes(node1, node2) element1 = devicetools.Element("element1", outlets=node1) element2 = devicetools.Element("element2", outlets=node1) element3 = devicetools.Element("element3", outlets=node1) element4 = devicetools.Element("element4", outlets=node1) elements_lland = devicetools.Elements(element1, element2, element3) elements = elements_lland + element4 element1.model = importtools.prepare_model("lland_v1") element2.model = importtools.prepare_model("lland_v1") element3.model = importtools.prepare_model("lland_v2") element4.model = importtools.prepare_model("hland_v1") for idx, element in enumerate(elements_lland): parameters = element.model.parameters parameters.control.nhru(idx + 1) parameters.control.lnk(lland.ACKER) parameters.derived.absfhru(10.0) control = element4.model.parameters.control control.nmbzones(3) control.sclass(2) control.zonetype(hland.FIELD) control.zonearea.values = 10.0 # pylint: disable=not-callable # pylint usually understands that all options are callable # but, for unknown reasons, not in the following line: with hydpy.pub.options.printprogress(False): nodes.prepare_simseries(allocate_ram=False) # ToDo: add option "reset" nodes.prepare_simseries(allocate_ram=True) elements.prepare_inputseries(allocate_ram=False) elements.prepare_inputseries(allocate_ram=True) elements.prepare_factorseries(allocate_ram=False) elements.prepare_factorseries(allocate_ram=True) elements.prepare_fluxseries(allocate_ram=False) elements.prepare_fluxseries(allocate_ram=True) elements.prepare_stateseries(allocate_ram=False) elements.prepare_stateseries(allocate_ram=True) # pylint: enable=not-callable def init_values(seq: TestIOSequence, value1_: float) -> float: value2_ = value1_ + len(seq.series.flatten()) values_ = numpy.arange(value1_, value2_, dtype=float) seq.testarray = values_.reshape(seq.seriesshape) seq.series = seq.testarray.copy() return value2_ value1 = 0.0 for subname, seqname in zip(["inputs", "fluxes", "states"], ["nied", "nkor", "bowa"]): for element in elements_lland: subseqs = getattr(element.model.sequences, subname) value1 = init_values(getattr(subseqs, seqname), value1) for node in nodes: value1 = init_values(node.sequences.sim, value1) # type: ignore[arg-type] init_values(element4.model.sequences.states.sp, value1) # type: ignore[arg-type] return nodes, elements