Giter Club home page Giter Club logo

trnsystor's Introduction

PyPI version fury.io codecov PyPI pyversions

trnsystor

A python scripting language for TRNSYS.

Create .dck files from stratch in an object-oriented python structure. Add components, specify parameters, connect components together and more throught python code.

Installation

pip install trnsystor

Usage

Since TRNSYS 18, type proformas can be exported to XML schemas. trnsystor builds on this easy to read data structure to easily create TrnsysModels using the most popular scripting language in the data science community: Python.

From the xml file of a type proforma, simply create a TrnsysModel object by invoking the from_xml() constructor:

>>> from trnsystor import TrnsysModel
>>> xml = "tests/input_files/Type951.xml"
>>> pipe1 = TrnsysModel.from_xml(xml)

Calling pipe1 will display its Type number and Name:

>>> pipe1
Type951: Ecoflex 2-Pipe: Buried Piping System

Then, pipe1 can be used to get and set attributes such as inputs, outputs, parameters and external files. For example, to set the Number of Fluid Nodes, simply set the new value as you would change a dict value:

>>> pipe1.parameters['Number_of_Fluid_Nodes'] = 50
>>> pipe1.parameters['Number_of_Fluid_Nodes']
NNumber of Fluid Nodes; units=-; value=50
The number of nodes into which each pipe will be divided. Increasing the number of nodes will improve the accuracy but cost simulation run-time.

Since the Number of Fluid Nodes is a cycle parameter, the number of outputs is modified dynamically:

calling [pipe1.outputs` should display 116 Outputs.

The new outputs are now accessible and can also be accessed with loops:

>>> for i in range(1,50):
...    print(pipe1.outputs["Average_Fluid_Temperature_Pipe_1_{}".format(i)])
Average Fluid Temperature - Pipe 1-1; units=C; value=0.0 celsius
The average temperature of the fluid in the specified node of the first buried pipe.
... *skipping redundant lines*
Average Fluid Temperature - Pipe 1-49; units=C; value=0.0 celsius
The average temperature of the fluid in the specified node of the first buried pipe.

Connecting outputs with inputs

Connecting model outputs to other model inputs is quite straightforward and uses a simple mapping technique. For example, to map the first two ouputs of pipe1to the first two inputs of pipe2, we create a mapping of the form mapping = {0:0, 1:1}. In other words, this means that the output 0 of pipe1 is connected to the input 1 of pipe2 and the output 1 of pipe1 is connected to the output 1 of pipe2. Keep in mind that since python traditionally uses 0-based indexing, it has been decided that the same logic in this package even though TRNSYS uses 1-based indexing. The package will internally assign the 1-based index automatically when saving to file.

For convenience, the mapping can also be done using the output/input names such as mapping = {'Outlet_Air_Temperature': 'Inlet_Air_Temperature', 'Outlet_Air_Humidity_Ratio': 'Inlet_Air_Humidity_Ratio'}:

# First let's create a second pipe, by copying the first one:
pipe2 = pipe1.copy()
# Then, connect pipe1 to pipe2:
pipe1.connect_to(pipe2, mapping={0:0, 1:1})

Equations

In the TRNSYS studio, equations are components holding a list of user-defined expressions. In trnsystor a similar approach has been taken: the Equation class handles the creation of equations and the [EquationCollection` class handles the block of equations. Here's an example:

First, create a series of Equation by invoking the [from_expression` constructor. This allows you to input the equation as a string.

>>> from trnsystor import Equation
>>> equa1 = Equation.from_expression("TdbAmb = [011,001]")
>>> equa2 = Equation.from_expression("rhAmb = [011,007]")
>>> equa3 = Equation.from_expression("Tsky = [011,004]")
>>> equa4 = Equation.from_expression("vWind = [011,008]")

One can create a equation block:

>>> equa_col_1 = EquationCollection([equa1, equa2, equa3, equa4], name='test')

Changing Initial Input Values

To change the initial value of an input, simply call it by name or with it's zero-based index and set a new value. This new value will be checked against the bounds set by the proforma as for a regular input or parameter.

>>> pipe1.parameters['Number_of_Fluid_Nodes'] = 50
>>> pipe_type.initial_input_values["Inlet_Fluid_Temperature_Pipe_1"] = 70
>>> pipe_type.initial_input_values["Inlet_Fluid_Temperature_Pipe_1"].default  # or, pipe_type.initial_input_values[0]
70.0 <Unit('degC')>

Creating a Deck file

A deck file (.dck) is created by instanciating a Deck object and calling the instance method .save(). The Deck object contains the Simulation Cards and the different models (components) for the project. The following code block shows one way of creating a Deck and saving it to file.

>>> from trnsystor import Deck, ControlCards
>>> 
>>> control_card = ControlCards.debug_template(). # Specifies a predefined set of control cards. See section bellow.
>>> cdeck = Deck(name="mydeck", control_cards=control_card, author="jovyan")
>>> 
>>> list_models = []  # a list of TrnsysModel objects created earlier
>>>  
>>> deck.update_models(list_models)
>>> 
>>> deck.save("my_project.dck")

Simulation Cards

The Simulation Cards is a chuck of code that informs TRNSYS of various simulation controls such as start time end time and time-step. trnsystor implements many of those Statements with a series of Statement objects.

For instance, to create simulation cards using default values, simply call the all() constructor:

>>> from trnsystor import ControlCards
>>> cc = ControlCards.all()
>>> print(cc)
*** Control Cards
SOLVER 0 1 1          ! Solver statement    Minimum relaxation factor   Maximum relaxation factor
MAP                   ! MAP statement
NOLIST                ! NOLIST statement
NOCHECK 0             ! CHECK Statement
DFQ 1                 ! TRNSYS numerical integration solver method
SIMULATION 0 8760 1   ! Start time  End time    Time step
TOLERANCES 0.01 0.01  ! Integration Convergence
LIMITS 25 10 25       ! Max iterations  Max warnings    Trace limit
EQSOLVER 0            ! EQUATION SOLVER statement

Selecting elements of components

Inputs, Outputs, Parameters, Derivatives, SpecialCards and ExternalFiles can be accessed via their attribute in any TrnsysModel component. They are accessed via their position as for in a list. It is also possible to slice the collection to retrieved more than one element. In this case a list is returned:

>>> from trnsystor.trnsysmodel import TrnsysModel
>>> pipe = TrnsysModel.from_xml("tests/input_files/Type951.xml")
>>> pipe.inputs[0:2]  # getting the first 2 inputs
[Inlet Fluid Temperature - Pipe 1; units=C; value=15.0 °C
The temperature of the fluid flowing into the first buried horizontal pipe., Inlet Fluid Flowrate - Pipe 1; units=(kg)/(hr); value=0.0 kg/hr
The flowrate of fluid into the first buried horizontal pipe.]

Parsing string snippets

Since version 1.4, it is possible to parse string snippets of TRNSYS components. Deck.load() and Deck.loads() (similarly to json.load and json.loads for users who are familiar with json deserializing in python).

For example, one can load the following string into a Deck object:

from trnsystor import Deck
s = r"""
UNIT 3 TYPE  11 Tee Piece
*$UNIT_NAME Tee Piece
*$MODEL district\xmltypes\Type11h.xml
*$POSITION 50.0 50.0
*$LAYER Main
PARAMETERS 1
1  ! 1 Tee piece mode
INPUTS 4
0,0  ! [unconnected] Tee Piece:Temperature at inlet 1
flowRateDoubled  ! double:flowRateDoubled -> Tee Piece:Flow rate at inlet 1
0,0  ! [unconnected] Tee Piece:Temperature at inlet 2
0,0  ! [unconnected] Tee Piece:Flow rate at inlet 2
*** INITIAL INPUT VALUES
20   ! Temperature at inlet 1
100  ! Flow rate at inlet 1
20   ! Temperature at inlet 2
100  ! Flow rate at inlet 2

* EQUATIONS "double"
*
EQUATIONS 1
flowRateDoubled  =  2*[1, 2]
*$UNIT_NAME double
*$LAYER Main
*$POSITION 50.0 50.0
*$UNIT_NUMBER 2
"""
dck = Deck.loads(s, proforma_root="tests/input_files")

If the same string was in a file, it could be as easily parsed using Deck.load():

>>> from trnsystor import Deck
>>> with open("file.txt", "r") as fp:
>>>     dck = Deck.load(fp, proforma_root="tests/input_files")

trnsystor's People

Contributors

dependabot[bot] avatar florent-h avatar samuelduchesne avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

trnsystor's Issues

Help wanted, the external file

Dear author,

Thanks a lot for your work.

I just try to set the external weather file(.tm2) to type 15-2 for processing the weather data.

I could not find any detailed example in this, could you please give me an instance?

Further, I just run the type 15 in trnsystor, the tm2 file will decrease from 1232kb to 563kb. I do not know if there is any problem to damage the weather file.

image

Here some of the files just became 563kb

I also tested the type9e, still facing the problem of the setting of external_files, would you please give an example for how to config the external files for a model

image

Implement connection to other `TrnsysModel` objects

This is the initial logic behind the connection between trnsys types. The idea is to use a user-defined mapping of the form: output_of_pipe1_i to input_of_pipe2_i.

pipe_1.connect_to(pipe_2, mapping={0:0, 1:4, 2:3})

Parsing cycle-parameter types

Some types, such as the Type14h, define parameters using a cycle. Since the number of cycles in not defenined in the parameters, but rather is implied in the number of parameter (34 in the example bellow), the current parsing logic canoot parse types such as type14h.

Type14h

This type is written in the deck file like this:

* Model "Load profile" (Type 14)
* 

UNIT 9 TYPE 14	 Load profile
*$UNIT_NAME Load profile
*$MODEL .\Utility\Forcing Functions\General\Type14h.tmf
*$POSITION 57 563
*$LAYER Main # # # 
PARAMETERS 34
0		! 1 Initial value of time
0		! 2 Initial value of function
7		! 3 Time at point-1
0		! 4 Value at point -1
7		! 5 Time at point-2
0.2		! 6 Value at point -2
9		! 7 Time at point-3
0.2		! 8 Value at point -3
9		! 9 Time at point-4
0		! 10 Value at point -4
11		! 11 Time at point-5
0		! 12 Value at point -5
11		! 13 Time at point-6
0.1		! 14 Value at point -6
13		! 15 Time at point-7
0.1		! 16 Value at point -7
13		! 17 Time at point-8
0		! 18 Value at point -8
18		! 19 Time at point-9
0		! 20 Value at point -9
18		! 21 Time at point-10
0.1		! 22 Value at point -10
22		! 23 Time at point-11
0.1		! 24 Value at point -11
22		! 25 Time at point-12
0		! 26 Value at point -12
24		! 27 Time at point-13
0		! 28 Value at point -13
7		! 29 Time at point-14
0		! 30 Value at point -14
7		! 31 Time at point-15
0		! 32 Value at point -15
7		! 33 Time at point-16
0		! 34 Value at point -16
*------------------------------------------------------------------------------

ImportError: cannot import name 'Equation' from 'trnsystor'

Dear author,

I go through the code but still a little bit confused about the usage of the equation.

How could we build some variables in the equation, the inputs, and outputs we could just define in trnsys?

The code example in the doc seems only the description of equations, not the definitions.

Cannot reference [Unit number, Output number] tuple from Equation blocks

In Trnsys deck files, when making a connection between an equation block and another type, the output from the equation block is referenced by the name of the parameter, not the [unit number, output number] tuple used for types.

The following portion of the deck file is correct:

* EQUATIONS "double"
*
EQUATIONS 1
flowRateDoubled  =  2*[1, 2]
*$UNIT_NAME double
*$LAYER Main
*$POSITION 50.0 50.0
*$UNIT_NUMBER 2

UNIT 3 TYPE  11 Tee Piece
*$UNIT_NAME Tee Piece
*$MODEL district\xmltypes\Type11h.xml
*$POSITION 50.0 50.0
*$LAYER Main
PARAMETERS 1
1  ! 1 Tee piece mode
INPUTS 4
0,0  ! [unconnected] Tee Piece:Temperature at inlet 1
flowRateDoubled  ! double:flowRateDoubled -> Tee Piece:Flow rate at inlet 1 <<<<---- CORRECT
0,0  ! [unconnected] Tee Piece:Temperature at inlet 2
0,0  ! [unconnected] Tee Piece:Flow rate at inlet 2
*** INITIAL INPUT VALUES
20   ! Temperature at inlet 1
100  ! Flow rate at inlet 1
20   ! Temperature at inlet 2
100  ! Flow rate at inlet 2

While this is wrong:

* EQUATIONS "double"
*
EQUATIONS 1
flowRateDoubled  =  2*[1, 2]
*$UNIT_NAME double
*$LAYER Main
*$POSITION 50.0 50.0
*$UNIT_NUMBER 2

UNIT 3 TYPE  11 Tee Piece
*$UNIT_NAME Tee Piece
*$MODEL district\xmltypes\Type11h.xml
*$POSITION 50.0 50.0
*$LAYER Main
PARAMETERS 1
1  ! 1 Tee piece mode
INPUTS 4
0,0  ! [unconnected] Tee Piece:Temperature at inlet 1
2,1  ! double:flowRateDoubled -> Tee Piece:Flow rate at inlet 1 <<<<---- WRONG
0,0  ! [unconnected] Tee Piece:Temperature at inlet 2
0,0  ! [unconnected] Tee Piece:Flow rate at inlet 2
*** INITIAL INPUT VALUES
20   ! Temperature at inlet 1
100  ! Flow rate at inlet 1
20   ! Temperature at inlet 2
100  ! Flow rate at inlet 2

For printers, must remove inputs and initial input values that are in excess of those connected

If the user sets the input 'How_many_variables_are_to_be_printed_by_this_component_' of a Type 25c printer to a number greater than the variables that are ultimately connected, an excess number of lines are printed in the deck file.

printer_path = "district/xmltypes/Type25c.xml"
printer = TrnsysModel.from_xml(printer_path)
printer.inputs['How_many_variables_are_to_be_printed_by_this_component_'] = 90
INPUTS 90
PLF_1               ! HeatPump_1:PLF_1 -> Printer - No units printed to output file:Input to be printed-1
workHP_1            ! HeatPump_1:workHP_1 -> Printer - No units printed to output file:Input to be printed-2
outletWaterTemp_1   ! HeatPump_1:outletWaterTemp_1 -> Printer - No units printed to output file:Input to be printed-3
[...]
14,11               ! pipe_1 - section_2 - unit_14:Thermal Losses - Pipe 1 -> Printer - No units printed to output file:Input to be printed-86
14,12               ! pipe_1 - section_2 - unit_14:Thermal Losses - Pipe 2 -> Printer - No units printed to output file:Input to be printed-87
0,0                 ! [unconnected] Printer - No units printed to output file:Input to be printed-88 (remove this line)
0,0                 ! [unconnected] Printer - No units printed to output file:Input to be printed-89 (remove this line)
0,0                 ! [unconnected] Printer - No units printed to output file:Input to be printed-90 (remove this line)
*** INITIAL INPUT VALUES
label  ! Input to be printed-1
label  ! Input to be printed-2
label  ! Input to be printed-3
[...]
label  ! Input to be printed-86
label  ! Input to be printed-87
label  ! Input to be printed-88 (remove this line)
label  ! Input to be printed-89 (remove this line)
label  ! Input to be printed-90 (remove this line)

The three lines at the end of INPUTS and at the end of INITIAL VALUES must be removed when creating the deck file.

Unit numbers are negative in connections with EquationCollections

When using the connect_to method between an EquationCollection and a TrnsysModel object, the unit number referring to the EquationCollection object is negative in the INPUTS block in the .dck file.

I believe this bug may stem from the missing *$UNIT_NAME, *$MODEL, *$POSITION, *$LAYER block for EquationCollections—see Issue #40.

from trnsystor.controlcards import ControlCards
from trnsystor.deck import Deck
from trnsystor.trnsysmodel import TrnsysModel
from trnsystor.statement import Equation
from trnsystor.collections.equation import EquationCollection

# create Deck with all() ControlCard
control_card = ControlCards.all()
deck = Deck(name="deck", control_cards=control_card)

# create "pipe" TrnsysModel from xml
pipe = TrnsysModel.from_xml("district/xmltypes/Type31.xml")

# create EquationCollection with single Equation that doubles flow rate from pipe
flow_rate_db = f"flowRateDoubled"
inlet = pipe.outputs["Outlet_flow_rate"]
exp_flow_rate = "f*2"

eq_flow_rate = Equation.from_symbolic_expression(flow_rate_db, exp_flow_rate, inlet)
equation_double = EquationCollection(eq_flow_rate, name="double")

# create "mixer" TrnsysModel from xml
mixer = TrnsysModel.from_xml("district/xmltypes/Type11h.xml")

# connect doubled flow rate of "equation_double" EquationCollection to "mixer" TrnsysModel
equation_double.connect_to(
    mixer,
    mapping={
        flow_rate_db: "Flow_rate_at_inlet_1",
    },
)

# update and save Deck with pipe TrnsysModel and "double" EquationCollection
deck.update_models([pipe, equation_double, mixer])
deck.save("test_negative_num.dck")

test_negative_num.dck

VERSION 18.0
*** Control Cards
SIMULATION 0 8760 1   ! Start time	End time	Time step
TOLERANCES 0.01 0.01  ! Integration	Convergence
LIMITS 25 10 25       ! Max iterations	Max warnings	Trace limit
NAN_CHECK 1           ! The NAN_CHECK Statement
OVERWRITE_CHECK 1     ! The OVERWRITE_CHECK Statement
TIME_REPORT 1         ! The TIME_REPORT Statement
DFQ 1                 ! TRNSYS numerical integration solver method
NOCHECK 0             ! CHECK Statement
EQSOLVER 0            ! EQUATION SOLVER statement
SOLVER 0 1 1          ! Solver statement	Minimum relaxation factor	Maximum relaxation factor
NOLIST                ! NOLIST statement
                      ! The LIST Statement
MAP                   ! MAP statement
UNIT 1 TYPE  31 Pipe
*$UNIT_NAME Pipe
*$MODEL district\xmltypes\Type31.xml
*$POSITION 50.0 50.0
*$LAYER Main
PARAMETERS 6
0.2   ! 1 Inside diameter
1     ! 2 Pipe length
3     ! 3 Loss coefficient
1000  ! 4 Fluid density
4.19  ! 5 Fluid specific heat
10    ! 6 Initial fluid temperature
INPUTS 3
0,0  ! [unconnected] Pipe:Inlet temperature
0,0  ! [unconnected] Pipe:Inlet flow rate
0,0  ! [unconnected] Pipe:Environment temperature
*** INITIAL INPUT VALUES
10   ! Inlet temperature
100  ! Inlet flow rate
10   ! Environment temperature


* EQUATIONS "double"

EQUATIONS 1
flowRateDoubled  =  2*[1, 2]

UNIT 3 TYPE  11 Tee Piece
*$UNIT_NAME Tee Piece
*$MODEL district\xmltypes\Type11h.xml
*$POSITION 50.0 50.0
*$LAYER Main
PARAMETERS 1
1  ! 1 Tee piece mode
INPUTS 4
0,0   ! [unconnected] Tee Piece:Temperature at inlet 1
-2,1  ! double:flowRateDoubled -> Tee Piece:Flow rate at inlet 1
0,0   ! [unconnected] Tee Piece:Temperature at inlet 2
0,0   ! [unconnected] Tee Piece:Flow rate at inlet 2
*** INITIAL INPUT VALUES
20   ! Temperature at inlet 1
100  ! Flow rate at inlet 1
20   ! Temperature at inlet 2
100  ! Flow rate at inlet 2

END
*!LINK_STYLE
*!LINK_STYLE_END

The unit number is -2 in the second INPUT of the Tee Piece unit block; it appears that EQUATIONS "double" should be unit number 2.

Incorrect logical unit used for external data files

When creating a deck file with the TRNSYS Type 15-3 (Weather Data Processor), the logical unit in the parameters is incorrectly assigned to the external data file path:

DECK FILE

UNIT 5 TYPE 15 Weather Data Processor; Combines data reading, radiation processing and sky temperature calculations
*$UNIT_NAME Weather Data Processor; Combines data reading, radiation processing and sky temperature calculations
*$MODEL C:\Users\flore\Documents\GitRepositories\district\district\xmltypes\Type15-3.xml
*$POSITION 300744.14196862775 5039529.141141754
*$LAYER Main
PARAMETERS 9
3    ! 1 File Type
30   ! 2 Logical unit (wrong logical unit)
5    ! 3 Tilted Surface Radiation Mode
0.2  ! 4 Ground reflectance - no snow
0.7  ! 5 Ground reflectance - snow cover
1    ! 6 Number of surfaces
1    ! 7 Tracking mode-1
0    ! 8 Slope of surface-1
0    ! 9 Azimuth of surface-1
*** External files
ASSIGN  "C:\Users\flore\Documents\GitRepositories\district\tests\input_data\weather_files\CAN_PQ_Montreal_CWEC.epw"  32 ! (logical unit that should be used)

LOG FILE

*** Fatal Error at time   :         0.000000
    Generated by Unit     :     5
    Generated by Type     :    15
    Message               : Unable to correctly read from the supplied data file - please check the file and re-run the simulation.

## Draft: connecting components without taking the same path

Draft: connecting components without taking the same path

import random

import matplotlib.pyplot as plt
import networkx as nx
import tqdm


def chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i + n]


if __name__ == '__main__':
    G = nx.grid_2d_graph(100, 100)
    H = G.copy()
    I = nx.Graph()
    paths = {}
    for i in tqdm.tnrange(10):
        node_list = [n for n in G.nodes()]
        chuncks = [c for c in chunks(node_list, int(len(node_list) / 4))]
        u = random.choice(chuncks[0])
        v = random.choice(chuncks[3])

        paths[i] = nx.shortest_path(G, u, v)
        edges = list(zip(paths[i], paths[i][1:] + paths[i][:1]))
        # G.remove_edges_from(edges)
        G.remove_nodes_from(paths[i])
        I.add_edges_from(edges[:-1])

    pos_h = {n: n for n in H.nodes}
    pso_i = {n: n for n in I.nodes}

    fig, ax = plt.subplots(1, 1, figsize=(20, 20))
    nx.draw_networkx_nodes(H, pos_h, arrows=False, with_labels=False,
                           node_size=1)
    nx.draw_networkx_edges(I, pso_i, edge_color='r')
    plt.show()

Imagine that at the end of those lines is a TRNSYS component. The point grid is there to show the available paths.:

test-shortestpath

Originally posted by @samuelduchesne in #11 (comment)

Incorrect number of TypeVariable instances created during cycle

In the method _resolve_cycles, when creating mutiple similar parameters, inputs, or outputs (i.e. TypeVariables) based on the value of a parameter (e.g. "Number_of_Outlet_Ports" for the Type647), not all TypeVariables are created.

Using the example of Type647 (Fluid Diverting Valve w/Up to 100 Outlets), there is only one instance of the output "Outlet_Flowrate" even though the cycling parameter "Number_of_Outlet_Ports" is set to 3. On the other hand, 3 instances of "Outlet_Temperature" are created, as expected.

pyTrnsysType - Issue

Requesting that EquationCollection.update accepts lists of Equations as arguments

The class method update of the EquationCollection class currently only accepts dictionaries and singular Equations as arguments. It would be beneficial that the method also accepts lists of Equations.

For example:

from pyTrnsysType import EquationCollection, Equation

eq_col = EquationCollection()

exp_1 = "m / v"
eq_1 = Equation.from_symbolic_expression("density", exp_1, *("mass", "volume"))

exp_2 = "r * g * h"
eq_2 = Equation.from_symbolic_expression("force", exp_2, *(eq_1.name, "g", "height"))

eq_col.update([eq_1, eq_2])

Missing "$" character in UNIT_NUMBER for equation blocks

The $ character is missing in front of UNIT_NUMBER for equation blocks.

The equation blocks are printed like this right now:

* EQUATIONS "double"
*
EQUATIONS 1
flowRateDoubled  =  2*[1, 2]
*$UNIT_NAME double
*$LAYER Main
*$POSITION 50.0 50.0
*UNIT_NUMBER 2

While they should be printed like this:

* EQUATIONS "double"
*
EQUATIONS 1
flowRateDoubled  =  2*[1, 2]
*$UNIT_NAME double
*$LAYER Main
*$POSITION 50.0 50.0
*$UNIT_NUMBER 2

Requesting that Deck.update_with_model accepts lists of TrnsysModels as arguments

Similar to Issue #18 , it would be advantageous to have the class method Deck.update_with_model accept lists of TrnsysModels (and EquationCollections) as arguments, since only singular TrnsysModel or EquationCollection objects currently work as arguments. Perhaps creating a new class method entitled update_with_model_list is called for.

For example:

from pyTrnsysType import ControlCards, Deck, TrnsysModel

control_card = ControlCards.basic_template()
deck = Deck(name="deck", control_card=control_card)

chiller = TrnsysModel.from_xml("Type666.xml")
cooling_tower = TrnsysModel.from_xml("Type510.xml")

deck.update_with_model_list([chiller, cooling_tower])

Problem with parsing inputs of Type 25 - Printer

An additional input is added at the end of the inputs of Type 25 (Printer), which is incorrect. The problem is also apparent in the initial values.

INPUTS 101
89,1   ! pipe_16 - section_2 - unit_89:Outlet Fluid Temperature - Pipe 1 -> Printer - No units printed to output file:Input to be printed-1
89,2   ! pipe_16 - section_2 - unit_89:Outlet Fluid Flowrate - Pipe 1 -> Printer - No units printed to output file:Input to be printed-2
89,3   ! pipe_16 - section_2 - unit_89:Outlet Fluid Temperature - Pipe 2 -> Printer - No units printed to output file:Input to be printed-3
[...]
0,0    ! [unconnected] Printer - No units printed to output file:Input to be printed-99
0,0    ! [unconnected] Printer - No units printed to output file:Input to be printed-100
0,0    ! [unconnected] Printer - No units printed to output file:How many variables are to be printed by this component?
*** INITIAL INPUT VALUES
label  ! Input to be printed-1
label  ! Input to be printed-2
label  ! Input to be printed-3
[...]
label  ! Input to be printed-99
label  ! Input to be printed-100
1      ! How many variables are to be printed by this component?

*$UNIT_NAME, *$MODEL, *$POSITION, and *$LAYER not printing for EquationCollections

The *$UNIT_NAME, *$MODEL, *$POSITION, and *$LAYER block is not printing to .dck files for EquationCollection objects. It is my understanding that this block is necessary for EQUATIONS in trnsys.

In the code below, the block is correctly printed for the "pipe" TrnsysModel but not the "double" EquationCollection:

from trnsystor.controlcards import ControlCards
from trnsystor.deck import Deck
from trnsystor.trnsysmodel import TrnsysModel
from trnsystor.statement import Equation
from trnsystor.collections.equation import EquationCollection

# create Deck with all() ControlCard
control_card = ControlCards.all()
deck = Deck(name="deck", control_cards=control_card)

# create pipe TrnsysModel from xml
pipe = TrnsysModel.from_xml("district/xmltypes/Type31.xml")

# create EquationCollection with single Equation that doubles flow rate from pipe
flow_rate_db = f"flowRateDoubled"
inlet = pipe.outputs["Outlet_flow_rate"]
exp_flow_rate = "f*2"

eq_flow_rate = Equation.from_symbolic_expression(flow_rate_db, exp_flow_rate, inlet)
equation_double = EquationCollection(eq_flow_rate, name="double")

# update and save Deck with "pipe" TrnsysModel and "double" EquationCollection
deck.update_models([pipe, equation_double])
deck.save("test_equation.dck")

test_equation.dck

VERSION 18.0
*** Control Cards
SIMULATION 0 8760 1   ! Start time	End time	Time step
TOLERANCES 0.01 0.01  ! Integration	Convergence
LIMITS 25 10 25       ! Max iterations	Max warnings	Trace limit
NAN_CHECK 1           ! The NAN_CHECK Statement
OVERWRITE_CHECK 1     ! The OVERWRITE_CHECK Statement
TIME_REPORT 1         ! The TIME_REPORT Statement
DFQ 1                 ! TRNSYS numerical integration solver method
NOCHECK 0             ! CHECK Statement
EQSOLVER 0            ! EQUATION SOLVER statement
SOLVER 0 1 1          ! Solver statement	Minimum relaxation factor	Maximum relaxation factor
NOLIST                ! NOLIST statement
                      ! The LIST Statement
MAP                   ! MAP statement
UNIT 1 TYPE  31 Pipe
*$UNIT_NAME Pipe
*$MODEL district\xmltypes\Type31.xml
*$POSITION 50.0 50.0
*$LAYER Main
PARAMETERS 6
0.2   ! 1 Inside diameter
1     ! 2 Pipe length
3     ! 3 Loss coefficient
1000  ! 4 Fluid density
4.19  ! 5 Fluid specific heat
10    ! 6 Initial fluid temperature
INPUTS 3
0,0  ! [unconnected] Pipe:Inlet temperature
0,0  ! [unconnected] Pipe:Inlet flow rate
0,0  ! [unconnected] Pipe:Environment temperature
*** INITIAL INPUT VALUES
10   ! Inlet temperature
100  ! Inlet flow rate
10   ! Environment temperature


* EQUATIONS "double"

EQUATIONS 1
flowRateDoubled  =  2*[1, 2]
END
*!LINK_STYLE
*!LINK_STYLE_END

[Unit number, Output number] tuple referenced between equation blocks; from_symbolic_expression parameters reversed

Similar to Issue #55, the [Unit number, Output number] tuple is being referenced in EquationCollections when referencing other EquationCollections, while it should be the parameter name that is referenced. Furthermore, when using Equation.from_symbolic_expression for these references, the parameters are reversed. See the test code below:

# create Deck with all() ControlCard
control_card = ControlCards.all()
deck = Deck(name="deck", control_cards=control_card)

# create "pipe" TrnsysModel from xml
pipe = TrnsysModel.from_xml("district/xmltypes/Type31.xml")

# create EquationCollection "constant" with single Equation that defines the additional flow rate for the pipe
delta_flow = "deltaFlowRate"
exp_delta_flow = "10"

eq_delta_flow = Equation.from_symbolic_expression(delta_flow, exp_delta_flow)
constants = EquationCollection(eq_delta_flow, name="constant")

# create EquationCollection "double" with single Equation that doubles flow rate from pipe
flow_rate_db = "flowRateDoubled"
inlet = pipe.outputs["Outlet_flow_rate"]
d_flow = constants.outputs["deltaFlowRate"]
exp_flow_rate = "i*2 + d"

eq_flow_rate = Equation.from_symbolic_expression(flow_rate_db, exp_flow_rate, *(inlet, d_flow))
equation_double = EquationCollection(eq_flow_rate, name="double")

# create "mixer" TrnsysModel from xml
mixer = TrnsysModel.from_xml("district/xmltypes/Type11h.xml")

# connect doubled flow rate of "equation_double" EquationCollection to "mixer" TrnsysModel
equation_double.connect_to(
    mixer,
    mapping={
        flow_rate_db: "Flow_rate_at_inlet_1",
    },
)

# update and save Deck with pipe and mixer TrnsysModels as well as "constant and "double" EquationCollections
deck.update_models([pipe, constants, equation_double, mixer])
deck.save("test_eq_connect.dck")

Output >>>

VERSION 18.0
*** Control Cards
SIMULATION 0 8760 1   ! Start time	End time	Time step
TOLERANCES 0.01 0.01  ! Integration	Convergence
LIMITS 25 10 25       ! Max iterations	Max warnings	Trace limit
NAN_CHECK 1           ! The NAN_CHECK Statement
OVERWRITE_CHECK 1     ! The OVERWRITE_CHECK Statement
TIME_REPORT 1         ! The TIME_REPORT Statement
DFQ 1                 ! TRNSYS numerical integration solver method
NOCHECK 0             ! CHECK Statement
EQSOLVER 0            ! EQUATION SOLVER statement
SOLVER 0 1 1          ! Solver statement	Minimum relaxation factor	Maximum relaxation factor
NOLIST                ! NOLIST statement
                      ! The LIST Statement
MAP                   ! MAP statement
UNIT 1 TYPE  31 Pipe
*$UNIT_NAME Pipe
*$MODEL district\xmltypes\Type31.xml
*$POSITION 50.0 50.0
*$LAYER Main
PARAMETERS 6
0.2   ! 1 Inside diameter
1     ! 2 Pipe length
3     ! 3 Loss coefficient
1000  ! 4 Fluid density
4.19  ! 5 Fluid specific heat
10    ! 6 Initial fluid temperature
INPUTS 3
0,0  ! [unconnected] Pipe:Inlet temperature
0,0  ! [unconnected] Pipe:Inlet flow rate
0,0  ! [unconnected] Pipe:Environment temperature
*** INITIAL INPUT VALUES
10   ! Inlet temperature
100  ! Inlet flow rate
10   ! Environment temperature


* EQUATIONS "constant"
*
EQUATIONS 1
deltaFlowRate  =  10
*$UNIT_NAME constant
*$LAYER Main
*$POSITION 50.0 50.0
*$UNIT_NUMBER 2


* EQUATIONS "double"
*
EQUATIONS 1
flowRateDoubled  =  [1, 2] + 2*[2, 1] <<<---- WRONG, should be: flowRateDoubled = deltaFlowRate + 2*[1,2]
*$UNIT_NAME double
*$LAYER Main
*$POSITION 50.0 50.0
*$UNIT_NUMBER 3


UNIT 4 TYPE  11 Tee Piece
*$UNIT_NAME Tee Piece
*$MODEL district\xmltypes\Type11h.xml
*$POSITION 50.0 50.0
*$LAYER Main
PARAMETERS 1
1  ! 1 Tee piece mode
INPUTS 4
0,0              ! [unconnected] Tee Piece:Temperature at inlet 1
flowRateDoubled  ! double:flowRateDoubled -> Tee Piece:Flow rate at inlet 1
0,0              ! [unconnected] Tee Piece:Temperature at inlet 2
0,0              ! [unconnected] Tee Piece:Flow rate at inlet 2
*** INITIAL INPUT VALUES
20   ! Temperature at inlet 1
100  ! Flow rate at inlet 1
20   ! Temperature at inlet 2
100  ! Flow rate at inlet 2

END
*!LINK_STYLE
*!LINK_STYLE_END

The setting of simulation card

Dear author,

Thanks a lot for your code and work. I may have a very naive problem since I am just starting the learning of trnsys.

Could we just modify the simulation card so that when we recall the py file for one time, the simulation will process only one step further?

Create SimulationCard Class

The Simulation Card can't be parsed from an XML. We need to create a new class to handle the Simulation Card Statements

Create Equation Class

Equations can't be parsed from an XML. We need to create a new class to handle Equation Statements

Unit parsing has weird behavior

In the xml proforma contains units defined as such: kJ/hr.m.K. They should, by convention, produce kJ/K/hr/m or rather kJ/(hr.m.K), but actually pytrsnsytypes parses them as K·kJ·m/hr'.

I believe there is an issue in the way pint handles the units.

What can be done?

Equation.from_symbolic_expression possibly considers the predicates LT, GT, etc. to be symbolic variables

Consider the following implementation of the method from_symbolic_expression from the Equation class:

# names of variables in equation
build_loop = "QBuildingLoop"
cap = "capacity"
load = "load"

exp_build_loop = "LT(l, c)*l + GE(l, c)*c"
eq_build_loop = Equation.from_symbolic_expression(build_loop, exp_build_loop, *(load, capacity))

The repr output for eq_build_loop becomes

QBuildingLoop = capacity**2 + load*GE(capacity, load).

I have tried to figure out exactly why this is outputted, but my best guess is that from_symbolic_expression is interpreting "LT" to be a symbolic variable. Further investigation is needed.

Deck output prints cycle in initial input values

UNIT 342 TYPE 25 Printer - No units printed to output file
*$UNIT_NAME Printer - No units printed to output file
*$MODEL district/xmltypes/Type25c.xml
*$POSITION 300078.5230023236 5039397.430813662
*$LAYER Main
PARAMETERS 10
1     ! 1 Printing interval
1     ! 2 Start time
8760  ! 3 Stop time
30    ! 4 Logical unit
0     ! 5 Units printing mode
0     ! 6 Relative or absolute start time
-1    ! 7 Overwrite or Append
-1    ! 8 Print header
0     ! 9 Delimiter
1     ! 10 Print labels
INPUTS 101
89,1   ! pipe_16 - section_2 - unit_89:Outlet Fluid Temperature - Pipe 1 -> Printer - No units printed to output file:Input to be printed-1
...
0,0    ! [unconnected] Printer - No units printed to output file:Input to be printed-100
0,0    ! [unconnected] Printer - No units printed to output file:How many variables are to be printed by this component?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.