08 ProgrammersGuide
08 ProgrammersGuide
Volume 8
Programmer's Guide
Revision history
2004-09
2005-02
Email: trnsys@engr.wisc.edu
Phone: +1 (608) 263 1586
Fax:
+1 (608) 262 8464
Notice
This report was prepared as an account of work partially sponsored by the United States
Government. Neither the United States or the United States Department of Energy, nor any of
their employees, nor any of their contractors, subcontractors, or employees, including but not
limited to the University of Wisconsin Solar Energy Laboratory, makes any warranty, expressed
or implied, or assumes any liability or responsibility for the accuracy, completeness or usefulness
of any information, apparatus, product or process disclosed, or represents that its use would not
infringe privately owned rights.
2004 by the Solar Energy Laboratory, University of Wisconsin-Madison
The software described in this document is furnished under a license agreement. This manual
and the software may be used or copied only under the terms of the license agreement. Except
as permitted by any such license, no part of this manual may be copied or reproduced in any form
or by any means without prior written consent from the Solar Energy Laboratory, University of
Wisconsin-Madison.
82
TRNSYS Contributors
S.A. Klein
W.A. Beckman
J.W. Mitchell
J.A. Duffie
N.A. Duffie
T.L. Freeman
J.C. Mitchell
J.E. Braun
B.L. Evans
J.P. Kummer
R.E. Urban
A. Fiksel
J.W. Thornton
N.J. Blair
P.M. Williams
D.E. Bradley
T.P. McDowell
M. Kummert
Additional contributors who developed components that have been included in the Standard
Library are listed in Volume 5.
Contributors to the building model (Type 56) and its interface (TRNBuild) are listed in Volume 6.
83
84
Table of contents
8. PROGRAMMER'S GUIDE
89
8.1. Introduction
89
89
810
810
810
811
812
812
812
814
815
8.2.2.5. Access to Kernel variables: Access Functions and the "TrnsysFunctions" module
816
817
817
818
819
819
820
821
822
822
823
824
825
825
826
827
827
827
828
829
831
832
832
85
832
833
834
834
834
835
837
8.4. Reference
8.4.1. Global constants
839
839
840
86
839
841
841
841
841
842
842
842
843
843
843
843
844
844
844
844
845
845
845
845
845
846
846
846
846
846
847
847
847
847
848
848
848
849
8.4.3.1. INFO(1:5)
849
8.4.3.2. INFO(6)
849
8.4.3.3. INFO(7)
850
8.4.3.4. INFO(8)
850
851
8.4.3.6. INFO(10)
852
8.4.3.7. INFO(11)
852
8.4.3.8. INFO(12)
852
8.4.3.9. INFO(13)
852
852
855
855
856
859
861
864
866
8.4.4.7. LINKCK
869
871
8.4.4.9. MESSAGES
872
8.4.4.10. ParRead
874
875
8.4.4.12. RCHECK
878
8.4.4.13. REWIND
884
8.4.4.14. SOLCEL
885
887
889
892
894
8.4.4.19. TYPECK
896
87
897
8103
8104
8105
8107
8107
8107
8108
8108
8109
8109
8109
8111
8111
8112
8112
8114
8114
8114
8114
8115
8116
8116
8117
8117
8117
8118
8119
8120
8120
8.5. References
88
8109
8121
8. PROGRAMMER'S GUIDE
8.1. Introduction
There are 3 main sections in this guide:
Section 8.2 explains how to update TRNSYS 15 components in order to use them in
TRNSYS 16. All TRNSYS 15 Types can be used in legacy mode after a few steps that do
not require any programming knowledge.
Section 8.3 describes the process of creating a new component from scratch
Section 8.4 Provides detailed reference on the TRNSYS kernel:
Calling sequence of Types and structure of the INFO array (8.4.3)
Available global constants (8.4.1). Some constants are especially interesting for
programmers since they set standard string lengths in TRNSYS (Fortran 90 does not
handle variable-length strings), see section 8.4.1.2.
Access functions that allow Types to access kernel variables (8.4.2)
Utility subroutines (0)
Instructions to recompile the TRNSYS DLL and add new DLL's to UserLib using different
compilers (Sections 8.4.9, 8.4.10 and above)
89
8.2.1.
The following 2 steps are required in order to use TRNSYS 15 Types in TRNSYS 16. If you want
to use your Type in a "TRNSYS 15 legacy mode", this is all you need to do. If you want to fully
convert your Types to the TRNSYS 16 standard, you will find additional instructions in section
8.2.1.3. Note that the steps listed in this section are also required to fully convert existing
TRNSYS 15 Types.
8.2.1.1.
In order for your component to be found by the TRNSYS Kernel, it needs to broadcast its name.
This is done by adding the following syntax to the component just underneath the subroutine line
at the top of the file.
!DEC$ATTRIBUTES DLLEXPORT :: TYPEnnn
Where nnn is the Type number. Thus Type205 would have the following line added:
!DEC$ATTRIBUTES DLLEXPORT :: TYPE205
It is important that the syntax begin in the leftmost column. In other words, do not put any
tabs or spaces to the left of the first exclamation point. As far as the Fortran compiler itself is
concerned, the line that has just been added is a comment. However, the pre-processor
recognizes the syntax and includes the Type in a file called an export library. Essentially this
means that the subroutine will be accessible by other subroutines not contained within the same
DLL.
Note: The line here above is required due to the new calling mechanism in TRNSYS 16, even
though TRNSYS 15 Types have to be linked to the main DLL. The "DLLEXPORT" directive is
required but it does not mean your Type will be usable in an external DLL.
8.2.1.2.
A number of structural changes have been made to TRNSYS components. Types in TRNSYS 16
are called in a different manner and with new INFO array codes, allowing them much more
flexibility in when and how they perform their calculations. Many of these changes are not
compatible with Types written for TRNSYS 15 or earlier so to avoid forcing users to completely
rewrite all their components, TRNSYS 16 contains two parallel calling structures, one for new
TRNSYS 16 components, and one for legacy components. In order for TRNSYS to determine the
manner in which it should call a component, each component must be "signed" with a version
number for which it was written. To sign your component, you need to add the following syntax to
it, at the top of the executable section (just below the variable declarations)
! Set the version information for TRNSYS
if (INFO(7) == -2) then
INFO(12) = 15
return 1
endif
By adding the above, you have signaled to TRNSYS that your component was written using the
TRNSYS 15 calling structure. TRNSYS will treat it accordingly. There should be no further
changes that you need to make to your Type in order for it to run under version 16.
810
8.2.1.3.
Additional considerations
If your Type refers to "param.inc", the include file that declares global TRNSYS 15 constants, you
need
to
update
the
path
to
that
file.
Param.inc
is
now
located
in
%TRNSYS16%\SourceCode\Include (%TRNSYS16% is your installation directory). Note that
Param.inc is obsolete and that TRNSYS 16 Types should use the global constants declared in
the TrnsysConstants module (see section 8.2.2.4 for details).
811
8.2.2.
The steps required in order to convert an existing Type to the TRNSYS 16 standard are given in
the following sections. The first two steps are the same as the steps required to run TRNSYS 15
Types in "legacy mode" (except that the Type is signed as a "Version 16" Type). Please note that
if you have a Type that was written for a TRNSYS version prior to TRNSYS 15, steps for
converting those Types are listed in the Reference section of this manual.
8.2.2.1.
See section 8.2.1.1 here above for details. You need to add the following syntax to the
component just underneath the subroutine line at the top of the file.
!DEC$ATTRIBUTES DLLEXPORT :: TYPEnnn
Where nnn is the Type number. Thus Type205 would have the following line added:
!DEC$ATTRIBUTES DLLEXPORT :: TYPE205
It is important that the syntax begin in the leftmost column. In other words, do not put any
tabs or spaces to the left of the first exclamation point.
8.2.2.2.
Note that detailed explanations of the INFO array and a full example of a typical calling sequence
for an iterative call are provided in section 8.4.3. The following sections just outline the changes
to existing TRNSYS 15 Types.
By adding the above, you have signaled to TRNSYS that your component was written using the
TRNSYS 16 standard.
812
If your component does use storage, then you should add lines that set up your local storage
array, then send the values to global storage using a call to the setStorageVars subroutine as
explained in section 8.2.2.6.
813
come of it. However, it is a good idea to specifically handle INFO(8). You can add the following
lines if your component does not have to do anything:
!
You may want your components to actually do something at the end of the simulation. They
could, for instances print a message to the list file or close logical units that were used during the
simulation. Standard component Type 22 (Iterative Feedback controller) performs end of the
simulation manipulations that you might use as an example.
The INFO(8)=-1 call also occurs if the simulation terminates with a fatal error. In that case, the
component that generates the error returns control to TRNSYS, which calls all components one
last time in order to perform their "end of simulation" operations. You can check if the very last
call occurs because of an error or as part of the normal simulation process by calling
getNumberOfErrors(). Some end of simulation operations are unnecessary or might crash
TRNSYS if the simulation ends with a fatal error. E.g. Type 22 handles INFO(8)=1 as follows:
if (info(8) == -1) then
! Exit immediately if this call is the result of a fatal error
if (getNumberOfErrors() > 0) then
return 1
! Otherwise, print the nb of "stuck" timesteps
else
...
printing manipulations
...
endif
return 1
! Exit
endif
Notes:
If the simulation ends without errors, the INFO(8) = -1 call happens after the user has
allowed the simulation to terminate by clicking on the "yes" or "continue" button at the end
of the simulation
The lines of code here above should be placed before the normal instructions so the
return occurs before those instructions are executed.
8.2.2.3.
One of the other focuses of version 16 development was to move away from single precision
variables toward double precision variables. Four of the arguments sent to each Type are now
double precision (TIME, PAR, T, and DTDT). Previously only XIN and OUT were double
precision. You will need to go through and declare TIME, PAR, T and DTDT as double precision
instead of real. It is also recommended that you do this for all your variables. If you prefer to keep
your variables single precision, it is important that you help Fortran make the conversion
correctly. The following incorrect code will not be caught by the Fortran compiler and may result
in incorrect answers:
RealVariable = DoublePrecisionVariable
814
8.2.2.4.
TRNSYS 16 Types should access global constants through the "TrnsysConstants" data module.
The available constants are described in section 8.4.1. Many new constants have been added in
order to promote consistency in TRNSYS (e.g. by making sure strings are sized in a consistent
way), and the existing constants previously found in the "param.inc" file have been transferred
into the new data module. Note that "param.inc" is still included in the TRNSYS distribution for
backwards compatibility, but it should not be used by TRNSYS 16 Types. To use the
"TrnsysConstants" module in a Type, add the following line at the top of the declaration section
(i.e. just below the !DEC$ATTRIBUTES instruction):
use TrnsysConstants
This will declare all the constants in the module in your Type. Alternatively, if you only want to use
the constant defining the maximum length of a Label string (maxLabelLength), you can use the
following syntax:
use TrnsysConstants, only: maxLabelLength
This will only declare the constant(s) listed after the "only" keyword. You can list several
constants in one "only:" instruction by using a comma-separated list.
A NOTE ON STRINGS
Fortran 77/90/95 do not provide variable-length strings, so each individual string variable must be
sized according to its expected maximum length. This can cause problems when different parts of
the code expect different maximum lengths for the same string. If your Type manipulates strings,
we strongly recommend that you check section 8.4.1 to see if a suitable constant is already
available for the size of your string, rather than using a new constant or a hard-coded value.
It is also recommended to use the generic "a" format when printing strings, rather than "ann"
where nn is the length of the string. Where an old print instructions for a variable descriptor
(column title in a printer) might say:
1000
character*10 myString
myString = 'Hello world'
write(*,1000) myString
format(a20)
Note that the generic "a" format does not work for character arrays (which are not exactly the
same as strings). In that case it is necessary to adjust the format instruction with a variable, e.g.:
use TrnsysConstants
! defines integer, parameter ::maxDescripLength
character (len=100) :: myFormatString
character :: myString(maxDescripLength)
! myString is a character array,
not a string
write(myFormatString,'(i)') maxDescripLength
myFormatString = '(' // trim(adjustl(myFormatString)) // 'a1)'
myString = 'Hello world'
write(*,myFormatString) trim(myString)
We recommend that you use string variables rather than character arrays when possible.
815
8.2.2.5.
That line should be inserted with the other "Use" instructions at the top of the declaration section.
Here again, it is possible to add "only:" instructions if only some of the functions are needed and if
name conflicts may occur (it is strongly discouraged to re-use TRNSYS function names in
Types)
Then, when a Kernel variable is needed, it can be accessed with the corresponding function. For
example, the simulation time step (DELT variable in the Kernel) is accessed through the
"getSimulationTimeStep()" function. Let's say a Type is integrating a value x over time, the result
being put in "integral".
TRNSYS 15
subroutine Type205(TIME,XIN,OUT,T,DTDT,PAR,INFO,ICNTRL,*)
common/SIM/TIME0,TFINAL,DELT,IWARN
real TIME0,TFINAL,DELT
integer IWARN
real x,s
s = s+x*DELT
subroutine Type205(TIME,XIN,OUT,T,DTDT,PAR,INFO,ICNTRL,*)
use TrnsysFunctions
TRNSYS 16
delt = getSimulationTimeStep()
s = s+x*delt
816
The TRNSYS 15 Common Blocks are still present in TRNSYS 16 in order to allow existing Types
to run in "legacy mode". However, they are not exported from the main DLL (TRNDll.dll). If you
do not replace Common Blocks with the use of Access Functions, you will not be able to use your
Type in an external DLL.
8.2.2.6.
STORAGE IN TRNSYS 15
One of the most unintuitive utilities in TRNSYS 15 was storage using the S array. The underlying
idea of storage is that sometimes you want your calculations not to be based upon the value of a
variable at the last iteration but the value of that variable at the end of the last time step. To use
the S array, one would bring it in as part of a COMMON block and declare how many places were
needed by setting INFO(10) to that number. Then every time a stored variable was needed, the
user would get a pointer into the S array by setting INFO(10) to a local integer variable (such as
ISTORE), then would start pulling out the stored values by referencing them as S(ISTORE),
S(ISTORE+1) etc. At the end of a time step, the user would do the reverse, again getting a
pointer into the S array, then setting its values to the correct local variables.
The problem was that Types did not know when it was the end of a time step, only that a new
time step had begun. Consequently, users had to notice that a new time step had started, then
update their S array with the most recent values (from the end of the last time step).In addition,
there was no check that a given Unit was not writing values in parts of the S array that had been
allocated to a different Unit.
STORAGE IN TRNSYS 16
In TRNSYS 16, the S array still exists in the COMMON block /STORE/ for legacy components.
However, three new utility subroutines were created, allowing for a hopefully more intuitive
approach to variable storage. The functions are described in details in section 8.4.2.1.
At the initialization call (INFO(7) = -1), the Type should call SetStorageSize to allocate
storage for the current Unit.
When the user wants to set storage at the end of a time step, a call is made to the
setStorageVars subroutine when INFO(13) = 1
When the user wants to obtain a previously stored value, a call is made to the
getStorageVars subroutine. This usually occurs during the first call of a new time step,
identified by INFO(7) = 0.
8.2.2.7.
817
errorCode is a standard TRNSYS error number (if available), message is the string that has to be
printed, severity indicates the severity of the message (e.g. warning or error) and UnitNo and
TypeNo indicate the calling unit and Type numbers.
Please refer to section 8.4.4.9 for more information on the Messages subroutine.
8.2.2.8.
One of the focuses of version 16 development was to move away from single precision variables
toward double precision variables. As a consequence, it is important to correctly handle the
arguments to utility subroutines (such as PSYCH) that your components may be calling. In
TRNSYS 15, the call to PSYCH was:
call PSYCH(TIME,INFO,IUNITS,MODE,WBMODE,PSYDAT,0,STATUS,N)
The arguments TIME and PSYDAT were both declared as real (single precision). In TRNSYS 16,
both TIME and PSYDAT should be declared in components as double precision and the call
should be made to the double precision version of PSYCH, which is called Psychrometrics. Thus
the syntax would be:
call Psychrometrics(TIME,INFO,IUNITS,MODE,WBMODE,PSYDAT,0,STATUS,N)
The single precision PSYCH subroutine still exists in TRNSYS 16 but it is merely a shell that
correctly converts single precision arguments to double precision, calls Psychrometrics, and
reconverts the results from double precision back to single precision. Table 8.2.2.8-1 shows the
TRNSYS 15 utility subroutine names in column 1, the corresponding TRNSYS 16 utility
subroutine name in column 2 and the arguments that must be converted from single to double
precision in column 3.
Table 8.2.2.8-1: TRNSYS 15 (single precision) and TRNSYS 16 (double precision) utility routines
Single precision
routine
Double precision
routine
PSYCH
Psychrometrics
TIME, PSYDAT
DATA
DynamicData
X, Y
TALF
TauAlpha
DIFFEQ
Differential_Eqn
ENCL
Enclosure
SPAR, WPAR, FV
VIEW
ViewFactor
A, B, C, D, E, F, G, H, X3, Y3, Z3
TABLE
Table_Coefs
B, C, D
INVERT
Matrix_Invert
DINVRT
Matrix_Invert
FLUIDS
Fluid_Props
PROP
STEAM
Steam_Props
PROP
818
8.3.1.
Fundamentals
At the most fundamental level, a component (referred to as a Type) in TRNSYS is merely a black
box. The TRNSYS kernel feeds inputs to the black box and in turn, the black box produces
outputs. To delve a little deeper, however, TRNSYS makes a distinction between inputs that
change with time and inputs that do not change with time. Examples of inputs that might change
with time are temperature, flow rate, or voltage. Example of inputs that do not change with time
are area or a rated capacity. In the early days of TRNSYS, this distinction was critical because
computing time was very costly and inputs that do not change with time can be set once at the
beginning of a simulation thereby saving a good bit of calculation time. With modern computing
power, this distinction is less critical but TRNSYS retains the designation of time dependent
inputs and time independent inputs. Time dependent inputs are referred to as INPUTS while time
independent inputs are referred to as PARAMETERS.
819
At each iteration and at each time step, a component turns the current values of the INPUTS and
PARAMETERS into OUTPUTS. No distinction is made among OUTPUTS; all OUTPUTS are
assumed to be time dependent and are recomputed by a component whenever appropriate.
TRNSYS has one more input / output distinction; that is DERIVATIVES. Components that solve
differential equations numerically will often have DERIVATIVES as well as INPUTS, OUTPUTS
and PARAMETERS. From the simulation users point of view, the DERIVATIVES for a given
Type specify initial values, such as the initial temperatures of various nodes in a thermal storage
tank or the initial zone temperatures in a multi zone building. At any given point in time, the
DERIVATIVES of a Type hold the results of the solved differential equation. If these
DERIVATIVES are set in a component as OUTPUTS, the simulation user can see, plot and
output these values.
8.3.1.1.
Much of the control as to what a component is supposed to do at a given point in the simulation
(particularly during initialization) is controlled by the contents of a data structure called the INFO
array. This array carries in its 15 spots, a great deal of information about what is going on
globally in the simulation at a given time. For example, the first INFO spot (INFO(1)) carries the
current UNIT number that the kernel is calling. The second INFO spot (INFO(2)) carries the
current TYPE number that the kernel is calling. The seventh INFO spot has a value of 1 if the
current call from the kernel intends for the called Type to initialize itself. The same spot has a
value of 0 at the very first call to a Type in a given time step. Thereafter it carries the total number
of iterations that have gone by in the current time step. The eighth INFO spot carries the total
number of calls to each Type that have gone by in the simulation at any given time. The thirteenth
INFO spot is normally 0 but is set to 1 after convergence has been reached in a given time step.
A complete reference to the contents of the INFO array is available in section 8.4.3 of this
manual. The INFO array will be used heavily in this section as a method for controlling the
functionality of a Type at various points in a simulation.
The remainder of this section of the Programmers Guide will use the example of a simple liquid
heating device to illustrate the process of writing a new component for TRNSYS.
Consider a simple heater that raises the variable inlet temperature of a flowing liquid to a user
defined temperature Tset. Writing an energy balance on the fluid of inlet temperature, Tin, at a
mass flow rate m:
Eq. 8.3.1-1
The first decision that must be made by the Type programmer is: what are going to be the
PARAMETERS, INPUTS and OUTPUTS of the model. Two possibilities become apparent. If the
goal of the component is for the end user to be able to specify an inlet temperature and a desired
outlet temperature, and in return, find out how much energy was required to bring the liquid from
820
For the purposes of this example, the INPUTS will be Tin, Tset, and m, the OUTPUTS of interest
& , the instantaneous heating rate and the outlet temperature, Tout. The PARAMETERS
will be Q
characterizing the heater will be Tset, Cpf, and Cap, allowing the heater to be capacity limited in
& will also be an OUTPUT
the amount of energy that it can deliver to the liquid stream. Note that m
so that this information is available to other components. We begin at the top of the new
component subroutine.
8.3.2.
Where n in TYPEn is a number between 1 and 999. To avoid problems with more than one
component being assigned the same number, the following conventions have been adopted:
Type1 150: reserved for library of Standard TRNSYS Components
Type151 200 : reserved for user written components
Type201 300: reserved for add on components commercially available from Transsolar
Type301 400: reserved for add on components commercially available from CSTB
Type401 500: reserved for add on components commercially available from Aiguasol
Type501 Type800: reserved for add on components commercially available from Thermal
Energy System Specialists
Type801 Type999: not reserved
For this example, Type number 151 will arbitrarily be chosen. Thus the first line of the subroutine
should be:
SUBROUTINE TYPE151(TIME,XIN,OUT,T,DTDT,PAR,INFO,ICNTRL,*)
In the subroutine parameter sequence shown above, the following variables are used:
TIME
XIN
OUT
the double precision array which the component fills with its
appropriate OUTPUTS
DTDT
PAR
INFO
ICNTRL
821
8.3.3.
DLL Export
With the release of TRNSYS v. 16.0, a great deal of effort was put into allowing Types to exist
either in the standard TRNDll.dll along with the other standard Types or to exist in an External
DLL. The TRNSYS 16 kernel examines the contents of a particular user library directory at the
beginning of each simulation where all external DLLs must be located if they are to be used. It
then loads all files with the extension *.dll, and examines them to find out if there are any
exported Type subroutines contained therein. If it finds exported Type routines it loads them into
memory for the duration of the simulation. The main advantage to end users is that they no longer
have to recompile the TRNDll.dll file when they receive a new component that they wish to use in
their simulation. Instead, they merely need to drop a DLL containing that Type into the
appropriate directory. As a Type programmer, there are certain steps that you must follow in
order to compile your Type and link it as an external DLL. For more information on linking your
component into a DLL, please refer to sections 8.3.16 and 8.4.10 of this manual. From a code
point of view, however, you need only add one line to your component, right at the top of the file
after the SUBROUTINE declaration and before any USE statements. The syntax of the line is:
!DEC$ATTRIBUTES DLLEXPORT :: TYPEn
Where n is the Type number. For our example (Type151) we would have the following line added:
...
!DEC$ATTRIBUTES DLLEXPORT :: TYPE151
...
It is important that the syntax begin in the leftmost column. In other words, do not put any
tabs or spaces to the left of the first exclamation point. The exclamation mark is recognized as a
comment by the Fortran code. It is, however, noticed by the Fortran compiler as an indication that
this subroutine should be exported for access by other DLLs.
8.3.4.
USE Statements
Whereas previous versions of TRNSYS relied heavily on Fortran COMMON blocks, TRNSYS 16
(and later version) Types should access global constants through various Data Modules that are
included with the source code. A Data Module is really nothing more than a file that contains a
series of variable declarations; they are a convenient way of declaring all in one place, the
variables that are accessible by various subroutines (Types, and kernel routines) within a
program. If a variable contained within a data module is needed by a given component, it is
accessed by adding a USE statement directly after the DLL Export instruction (see section 8.3.3
above). The syntax of a USE statement is as follows:
USE NameOfDataModule
The above has the effect of declaring ALL of the variables contained within the module in your
Type. Alternatively, if you only want to use a particular variable that is contained within the
module but do not want access to all of the variables therein, you can use the syntax:
USE NameOfDataModule, ONLY: nameOfVariable1,nameOfVariable2
This will only declare the variable(s) listed after the "ONLY" keyword. The advantage of listing
only those variables to which we want access is that we can reuse the names of global variables
locally as long as we do not request access to them through a USE statement. A complete list of
Data Modules accessible from a given Type or subroutine of a Type are listed in sections 8.4.1,
8.4.2. The most common Data Modules that you will need to access from your Type are:
TrnsysFunctions, TrnsysConstants, and TrnsysData. TrnsysFunctions contains a series of
functions that return commonly useful data such as the simulation start time or time step, or which
perform common functions such as reserving a new logical unit number in a global list for use by
822
an external file accessed by your Type. The TrnsysConstants module contains values that do not
change throughout a simulation but which are again, of common interest. The TrnsysData module
carries a series of data structure sizing constants such as the number of allowable UNITS in a
given simulation or the number of allowable EQUATIONS in a given simulation.
For the purposes of our example, the liquid heater will only need some of the TRNSYSs Access
Functions. Thus, in the USE statement section of the code, we need only add the following line:
...
! USE STATEMENTS
USE TrnsysFunctions
...
As previously mentioned, it is permissible to list the names of those functions that we wish to
access from the TrnsysFunctions module. However, since there is little chance that we will be
writing Functions of our own in this component, the chances that the name of a local function and
the name of a global function will conflict, is minimal.
8.3.5.
Variable Declarations
Having defined the subroutine arguments, exported the component, and given the component
access to global TRNSYS variables, we next need to declare all of the local variables that we
intend to use in the Type. Local variables can be split into two categories; local variables that are
required by every Type, and local variables that are only required by a given Type. Those local
variables that are required by every Type include the array that contains the Types parameters,
the array that contains the Types inputs, the array that contains the Types outputs, the simulation
time, etc. This block of variable declarations can simply be copied from an existing Type and can
be pasted into your new one. You only need make one modification to the following; that is to
change the values of NP, NI, NO, ND, and NS to match the number of parameters, inputs,
outputs, derivatives, and storage spots that will be required for your Type. The block of local
variables required by every Type is as follows.
...
IMPLICIT NONE !FORCE DECLARATION OF ALL VARIABLES
!
TRNSYS DECLARATIONS
DOUBLE PRECISION XIN,OUT,TIME,PAR,T,DTDT,TIME0, DELT,STORED
INTEGER*4 INFO(15),NP,NI,NOUT,ND,IUNIT,ITYPE,ICNTRL
CHARACTER*3 OCHECK,YCHECK
!
!
For the purposes of our liquid heater component, NP will be set to 4 (four parameters are
required), NI will be set to 5 (five inputs are required), NO will be set to 5 (five outputs will be
calculated), ND will be set to 0 (no derivatives are required), and NS will be set to 0 (no storage
spots are required).
With the local variables that apply to all components declared, we next declare the variables that
pertain only to our liquid heater. From a practical point of view, there is no way to anticipate and
simply enter all of the variables that will be needed during the course of developing a new
component. The following list is almost always created as the Type is being written and as local
variables are needed.
823
...
LOCAL VARIABLE DECLARATIONS
INTEGER IGAM
DOUBLE PRECISION TIN, & !temperature of fluid at heater inlet [C]
TOUT, &
!temperature of fluid at heater outlet [C]
TBAR, &
!average temperature of fluid in heater [C]
TAMB, &
!ambient temperature of heater surroundings [C]
TSET, &
!heater setpoint temperature [C]
TON, &
!set temporarily to TOUT before check on TOUT>TSET [C]
QMAX, &
!heater capacity [kJ/hr]
QAUX, &
!required heating rate [kJ/hr]
QLOSS, & !rate of thermal losses to surroundings [kJ/hr]
FLOW, &
!fluid flow rate through heater [kg/hr]
CP, &
!fluid specific heat [kJ/kg.K]
HTREFF, & !heater efficiency [-]
UA, &
!overall loss coeff. for heater during operation [kJ/hr.K]
QFLUID
!rate of energy delivered to fluid [kJ/hr]
...
8.3.6.
Data Statements
It is advantageous in some Types to set some constants that will be used throughout the Type
outside of the executable portion of the code using a DATA statement. The advantage of doing so
is that by defining a constant in a DATA statement, that definition is loaded at the simulation start
and never is there a time when simulation time has to be spent setting or resetting those values.
Often times Type programmers will set a variable called PI to the value 3.1415926 in a DATA
statement, or they will set a variable for the conversion factor between degrees and radians in a
DATA statement. Any variable whose value is set in a DATA statement must be declared among
the Local Variable declarations discussed in section 8.3.5 above.
One other common set of constants that are declared in DATA statements before the beginning
of the executable portion of a Type are the three letter codes that set the units of the Types
INPUT and OUTPUT variables. Refer to section 8.4.4.12 for additional information on these three
letter codes.
We have already declared and sized the two CHARACTER*3 arrays that will hold the input and
output unit codes for the liquid heater among the definition of local variables that are required by
all Types (see section 8.3.5). Our list of inputs, their units, and our list of outputs and their units is
as follows:
Table 8.3.1.1-1: Inputs, Outputs, and their Units
Input
Number
Input Description
Units
Output
Number
Output Description
Units
kg/hr
kg/hr
Control signal
0..1
kJ/hr
kJ/hr
Ambient temperature
kJ/hr
Referring to Table 8.3.1.1-1 and to Table 8.4.4.12-1 through Table 8.4.4.12-22, the following
DATA statements can be added to the Type, thus setting the units of the first input as a
temperature in degrees C, the units of the second input as mass flow rate in kilograms per hour,
the third input as a control signal having a value between 0 and 1, etc.
824
...
DATA STATEMENTS
DATA YCHECK/'TE1','MF1','CF1','TE1','TE1'/
DATA OCHECK/'TE1','MF1','PW1','PW1','PW1'/
...
8.3.7.
We have now arrived at the executable section of the Type; from here on, each line of the code
will be executed sequentially, starting at the top. It is therefore necessary to put those lines that
should be executed every single time step and every single iteration right at the beginning of the
executable section. In the case of almost all Types, the only thing that needs to be done this
regularly is to retrieve the values of some global variables that are used in controlling what the
Type does at what point in the simulation. Much of this information has already been passed to
the component. Variables such as TIME, and arrays such as INFO, PAR, and XIN are already
passed to us. Others, such as the time step, the simulation start time, and the simulation stop
time are not passed but must be retrieved on an as needed basis. This is the point in the Type
where AccessFunctions will be used most heavily. Almost all Types, this one included, need to
know the simulation start time and the simulation time step. These two variables are used later to
control Type functionality (see section 8.3.12 here below). Again, the local variable names for
these two variables have already been declared in the block of local variables that are required by
every Type. The local variable name for the simulation time step is DELT and the local variable
name for the simulation start time is TIME0 The code that should be added to Type151 is as
follows:
!----------------------------------------------------------------------------!
GET GLOBAL TRNSYS SIMULATION VARIABLES
TIME0
= getSimulationStartTime()
DELT
= getSimulationTimeStep()
8.3.8.
Version Signing
Version signing is one of a series of special calls that is made to a Type when the Type is not
intended to perform any manipulations of inputs or outputs. Once, at the very beginning of a
simulation, a Type needs to log itself as having been written for a given version of TRNSYS.
Throughout TRNSYSs history, new requirements have periodically been added to the
recommended practices in coding components. These requirements reflect new enhancements
that have been added or reflect changes is recommended coding practices that come from the
developers of Fortran compilers. Prior to the release of TRNSYS version 16, it was left to the
Type programmer to simply make the required modifications before being able to use an existing
Type with the new version of TRNSYS. With the release of TRNSYS 16.0, an effort was made to
allow for backwards compatibility in Types. That is that the TRNSYS 16 kernel was designed in
such a way that it was able to deal with Types that were written to conform with the TRNSYS 16
coding requirements, and to deal with Types that had been written for TRNSYS 15 (which have
different coding requirements). In order for the kernel to know how to treat a Type, however, each
Type must log itself as having been written with TRNSYS 16 conventions or as having been
written with TRNSYS 15 (and earlier) conventions. For additional information about the
differences in conventions, please refer to section 8.2 of this manual.
For the purposes of the liquid heater example, we are writing a TRNSYS 16 style component so
we must add lines of code that version sign our Type as complying with the TRNSYS 16 coding
requirements. The code lines that must be added are:
...
!------------------------------------------------------------------------------
825
...
At the very beginning of a TRNSYS simulation, the TRNSYS kernel calls each Type present in
the input file with the seventh spot of the INFO array set to a value of 2. Every Type should
therefore have a line in it that watches specifically for this situation. The only thing that the Type
should do when it realizes that INFO(7) = -2 is to set the twelfth input spot to a value of 16 if the
Type was written using TRNSYS 16 coding conventions or to a value of 15 if the Type was
written using previous coding conventions. If a Type does not handle the INFO(7) = -2 call
correctly (does not set INFO(12) to either 15 or 16) the TRNSYS kernel will not allow the
simulation to proceed and will generate an error, writing it to the simulation list and log files.
8.3.9.
The second special case call to Types occurs at the very END of each simulation. Whether the
simulation ends correctly or ends in error, each Type is recalled by the TRNSYS kernel before the
simulation shuts down. This call allows Types to perform any last call manipulations that may be
necessary. These may include closing external data files that were opened by the Type during
the course of a simulation, or calculating summary information that may have been collected
during a simulation. The Type that we are writing, does not require any such last call
manipulations, so it is advisable to simply return control directly to the TRNSYS kernel. The code
that is added to Type151 is as follows:
...
!-----------------------------------------------------------------------------!
PERFORM LAST CALL MANIPULATIONS
IF (INFO(8).EQ.-1) THEN
RETURN 1
ENDIF
...
You may want your component to actually do something at the end of the simulation. It could, for
instances print a message to the list file or close logical units that were used during the
simulation. Standard component Type 22 (Iterative Feedback controller) performs end of the
simulation manipulations that you might use as an example.
The INFO(8)=-1 call also occurs if the simulation terminates with a fatal error. In that case, the
component that generates the error returns control to TRNSYS, which calls all components one
last time in order to perform their "end of simulation" operations. You can check if the very last
call occurs because of an error or as part of the normal simulation process by calling
getNumberOfErrors(). Some end of simulation operations are unnecessary or might crash
TRNSYS if the simulation ends with a fatal error. E.g. Type 22 handles INFO(8)=1 as follows:
if (info(8) == -1) then
! Exit immediately if this call is the result of a fatal error
if (getNumberOfErrors() > 0) then
return 1
! Otherwise, print the nb of "stuck" timesteps
else
... printing manipulations
...
endif
return 1
! Exit
endif
826
Notes:
If the simulation ends without errors, the INFO(8) = -1 call happens after the user has
allowed the simulation to terminate by clicking on the "yes" or "continue" button at the end
of the simulation
The lines of code here above should be placed before the normal instructions so the
return occurs before those instructions are executed.
In more complex components than the one detailed by this example, the post convergence call
allows a number of different manipulations to be performed. They are resetting counters and
updating storage variables.
827
OldInitialValue = Stored(1)
NewFinalValue = Stored(2) !NewFinalValue was calculated by the
!component at each iteration in the time
!step and was stored in the Stored(2) spot.
Stored(1) = NewFinalValue
CALL setStorageVars(Stored,2,INFO)
RETURN 1
ENDIF
...
Set how the Type should be called using INFO(9). Most Types will set INFO(9) to a value of 1,
indicating that the Type should be called every iteration whether or not its input values have
changed. Types that are integrators or printers use different INFO(9) settings. Users
programming this kind of Type should refer to section 8.4.3.5 for more information.
Set the number of single precision storage spots required using INFO(10). It is highly
recommended that all components make use of DOUBLE, not SINGLE precision storage
structures. Therefore, in all likelihood, you should simply set INFO(10) to a value of 0.
Set the number of double precision storage spots required by calling the setStorageSize
subroutine. Information on calling setStorageSize can be found in section 8.4.4.16. It is again
important to bear in mind that we are not setting initial values of the storage variables at this time,
we are merely reserving space for later usage.
Call the TYPECK routine to make sure that the TRNSYS user has supplied the correct number of
parameters, inputs, and derivatives in the input file. Again, since we have already set the
expected number of parameters, inputs and derivatives using a Fortran parameter statement in
section 8.3.5, we need only paste in a line of the proper syntax at this point as shown below. The
1 in the fist argument of the call to TYPECK is an indicator of the action that TYPECK should take
in this particular case. For additional information on the arguments to TYPECK and their
meanings, please refer to section 8.4.4.19.
CALL TYPECK(1,INFO,NI,NP,ND)
Call the RCHECK routine to make sure that the units of the outputs that are connected to the
inputs of this Type are correct. In section 8.3.6, we listed three letter codes for the units of each of
the inputs and outputs of the Type151 that we are writing. By calling RCHECK, we are allowing
TRNSYS to check the users connections between other Types and this one to make sure that
they did not inadvertently connect an output with units of power (PW1 for example) to an input
with units of temperature (TE1 perhaps)
828
Return control to the TRNSYS kernel. Again, there are NO iterations performed during this time
step. Therefore there should be NO calculations performed.
The code required for the above steps in the context of Type151 is as follows. Please note that
the following code is quite generic and can be copied for any Type that does not have a variable
number of parameters, inputs, or derivatives allowed in the input file.
...
!-----------------------------------------------------------------------------!
PERFORM INITIALIZATION MANIPULATIONS
IF (INFO(7).EQ.-1) THEN
!retrieve unit and type number for this component from the INFO array
IUNIT=INFO(1)
ITYPE=INFO(2)
!reserve space in the global OUT array
INFO(6) = NO
! this TYPE should be called at each iteration whether or not its
! inputs change
INFO(9) = 1
! reserve space in the single precision storage structure
INFO(10) = 0
! call the Type check subroutine to compare what this Type requires to
! what has been supplied in the input file.
CALL TYPECK(1,INFO,NI,NP,ND)
! call the input-output check subroutine to set the correct input and
!output variable units.
CALL RCHECK(INFO,YCHECK,OCHECK)
! return to the calling program.
RETURN 1
ENDIF
...
829
Type151 has four parameters, one each for the maximum heating rate, the specific heat of the
working liquid, the overall loss coefficient of the heater, and the heater efficiency. Referring to the
code at the end of this section, each of these four parameters (PAR(1) through PAR(4) is set to a
local variable name: QMAX, CP, UA, and HTREFF respectively.
The second step performed during the time = time0 manipulations section is to check each of
the parameter values for validity. Parameters whose values cannot be negative, or whose values
must be between 0 and 1, can be flagged as an error using a call to the TYPECK subroutine.
Take, for example, the specific heat of the working liquid for the heater. It does not make any
physical sense to allow the user to enter a negative value of specific heat. We could use the
following code to detect and report the problem, assuming that the second parameter is the
specific heat and has been set to a local variable called SpecHeat.
...
SpecHeat = PAR(2)
IF (SpecHeat.LT.0.0) CALL TYPECK(-4,INFO,0,2,0)
...
The -4 argument in the call to TYPECK indicates to TYPECK that we are flagging an incorrect
parameter value and that we want TYPECK to report the error for us using its generic error
message. The 2 argument indicates to TYPECK that it is the second parameter that is a
problem.
Once TYPECK has reported the flagged parameter and printed its error message to the
simulation log and list files, it returns control to the calling Type but unfortunately does not return
an argument that tells the Type that an error message was written. It is good practice for a Type
that has called TYPECK with a bad parameter to immediately return control to the TRNSYS
kernel without completing its TIME = TIME0 manipulations in case the bad parameter could
cause other problems before the end of the call. It is therefore recommended that once all the
parameters have been checked, programmers use the ErrorFound( ) Access Function to
determine whether TYPECK wrote any error messages to the simulation list and log files. For
more information on the ErrorFound( ) Access Function, please refer to section 8.4.2.6. The code
for returning control in this manner is:
...
IF (ErrorFound()) RETURN 1
...
Next, it is necessary to set the initial values of any storage variables that are used by the Type.
This is accomplished simply by assigning local variable values to each of the spots in the array
that is used to transfer information to and from the double precision storage structure, then calling
the setStorageVars subroutine. The code used to set two initial storage values might look like the
following:
...
storageArray(1) = LocalVar1
storageArray(2) = LocalVar2
CALL setStorageVars(storageArray,2,INFO)
...
Since our Type151 does not require any storage variable spots, there is no need to include the
above step in this section of the Type151 code.
The final step performed during the TIME = TIME0 Manipulations section is to set the initial
values of the outputs. It is essential that you set initial values here, your Type should not perform
any of its calculations at this point in time. If it does, then it will likely get one time step ahead of
where it is supposed to be at this point in the simulation. Because of this restriction on performing
calculations, it is often difficult to know what value to choose for an output initial value. A good
default value is zero since that usually indicates to the user that the output has not yet been
calculated. In the case of devices that have fluid flow through them, the outlet temperature and
830
outlet flow rate of the fluid can often be set to the inlet temperature and inlet flow rate
respectively. In the case of Type151, the first two outputs can be set to the input initial values in
this manner. The other outputs cannot be calculated easily and so are simply set to zero.
Below is the entire code for the TIME = TIME0 Manipulations section of Type151.
...
!-----------------------------------------------------------------------------!
PERFORM INITIAL TIMESTEP MANIPULATIONS
IF(TIME.LT.(TIME0+DELT/2.)) THEN
!set the UNIT and TYPE numbers
IUNIT = INFO(1)
ITYPE = INFO(2)
!read parameter values
QMAX
= PAR(1)
CP
= PAR(2)
UA
= PAR(3)
HTREFF = PAR(4)
!check the parameters for problems and RETURN if any are found
IF(QMAX.LT.0.) CALL TYPECK(-4,INFO,0,1,0)
IF(CP.LT.0.)
CALL TYPECK(-4,INFO,0,2,0)
IF(UA.LT.0.)
CALL TYPECK(-4,INFO,0,3,0)
IF((HTREFF.GT.1.).OR.(HTREFF.LT.0.)) CALL TYPECK(-4,INFO,0,4,0)
IF (ErrorFound()) RETURN 1
!perform any required calculations, set the outputs to appropriate
! initial values.
OUT(1) = XIN(1) !outlet temperature = inlet temperature [C]
OUT(2) = XIN(2) !mass flowrate out = mass flowrate in [kg/hr]
OUT(3) = 0.
!required heating rate [kJ/hr]
OUT(4) = 0.
!rate of losses to environment [kJ/hr]
OUT(5) = 0.
!rate of energy delivered to stream [kJ/hr]
RETURN 1
!the first timestep is for initialization - exit.
ENDIF
...
What this does is take the first two spots of the INFO( ) array each and every time the Type is
called and save the current Type number and the current Unit number to local variables ITYPE
and IUNIT respectively. If there is only one instance of a given Type in a simulation, then the
value of IUNIT will always be equal to the value of INFO(1). Conversely, if there is more than one
instance of a given Type in a simulation, then whenever we begin simulating a new instance of
that Type, the value of IUNIT will not match the value of INFO(1). We make use of this very
feature at this stage of the manipulations. If the unit number has changed (IUNIT does not equal
INFO(1) then we know that we need to reread that parameter list so that we are sure that all local
variables are set to the current instance of the Types parameter lists. The code is as follows:
831
...
!-----------------------------------------------------------------------------!
RE-READ THE PARAMETERS IF ANOTHER UNIT OF THIS TYPE HAS BEEN CALLED SINCE
!
THE LAST TIME THEY WERE READ IN
IF(INFO(1).NE.IUNIT) THEN
!reset the unit number
IUNIT = INFO(1)
ITYPE = INFO(2)
!read the parameter values
QMAX
= PAR(1)
CP
= PAR(2)
UA
= PAR(3)
HTREFF = PAR(4)
ENDIF
...
There is no need to recheck the parameters for validity since this was done already during the
TIME = TIME0 manipulations section.
832
TSET = XIN(4)
TAMB = XIN(5)
CHECK THE INPUTS FOR VALIDITY AND RETURN IF PROBLEMS ARE FOUND
IF (FLOW.LT.0.)
CALL TYPECK(-3,INFO,2,0,0)
IF ((IGAM.GT.1.).OR.( IGAM.LT.0.))
CALL TYPECK(-3,INFO,3,0,0)
IF (ErrorFound() ) RETURN 1
...
Here the 3 in the TYPECK arguments indicates that we are flagging a bad input value
(previously we used 4 to indicate that we were flagging a bad parameter value.). The 2 and the
3 indicate the input number that is the problem in each case.
PERFORM CALCULATIONS
IF (FLOW .GT. 0.) GO TO 10 !if the inlet flow is greater than 0, skip to
!line 10
NO FLOW CONDITION
OUT(1) = TIN
OUT(2) = 0.
OUT(3) = 0.
OUT(4) = 0.
OUT(5) = 0.
RETURN 1
!
!
10
FLOW CONDITION
CHECK INLET TEMPERATURE AND CONTROL FUNCTION
IF ((TIN.LT.TSET).AND.(IGAM.EQ.1)) GO TO 20 !if the inlet temperature is
!below the set point temperature
!otherwise, the heater and the
!control signal is set to ON,
!skip to line 20. is OFF.
!
!
!
20
HEATER ON CONDITION
calculate the outlet temperature assuming that the heter is on and
running at capacity
TON =(QMAX*HTREFF+FLOW*CP*TIN+UA*TAMB-UA*TIN/2.d0)/(FLOW*CP+UA/2.d0)
!the outlet temperature is the lesser of TON and TSET the heater is
!able to modulate its energy output to reach the setpoint temperature.
TOUT = MIN(TSET,TON)
!calculate the average heater temperature losses are based on the
!average
TBAR = (TIN+TOUT)/2.d0
!calculate the auxiliary energy required, accounting for heater
!efficiency.
QAUX = (FLOW*CP*(TOUT-TIN)+UA*(TBAR-TAMB))/HTREFF
!calcualte the energy lost from the heater, including heater inefficiency
QLOSS = UA*(TBAR-TAMB) + (1.d0-HTREFF)*QAUX
!calculate the energy imparted to the liquid.
QFLUID = FLOW*CP*(TOUT-TIN)
833
SET OUTPUTS
OUT(1) = TOUT
OUT(2) = FLOW
OUT(3) = QAUX
OUT(4) = QLOSS
OUT(5) = QFLUID
...
834
TRNSYS DECLARATIONS
DOUBLE PRECISION XIN,OUT,TIME,PAR,T,DTDT,TIME0,TFINAL,DELT,STORED
INTEGER*4 INFO(15),NP,NI,NOUT,ND,IUNIT,ITYPE,ICNTRL
CHARACTER*3 OCHECK,YCHECK
!
!
DATA STATEMENTS
DATA YCHECK/'TE1','MF1','CF1','TE1','TE1'/
DATA OCHECK/'TE1','MF1','PW1','PW1','PW1'/
!----------------------------------------------------------------------------!
GET GLOBAL TRNSYS SIMULATION VARIABLES
TIME0
= getSimulationStartTime()
DELT
= getSimulationTimeStep()
!-----------------------------------------------------------------------------!
SET THE VERSION INFORMATION FOR TRNSYS
IF(INFO(7).EQ.-2) THEN
INFO(12)=16
RETURN 1
ENDIF
!------------------------------------------------------------------------------
835
!-----------------------------------------------------------------------------!
PERFORM POST CONVERGENCE MANIPULATIONS
IF(INFO(13).GT.0) THEN
RETURN 1
ENDIF
!-----------------------------------------------------------------------------!
PERFORM INITIALIZATION MANIPULATIONS
IF (INFO(7).EQ.-1) THEN
!retrieve unit and type number for this component from the INFO array
IUNIT=INFO(1)
ITYPE=INFO(2)
!reserve space in the global OUT array
INFO(6) = NO
! this TYPE should be called at each iteration whether or not its
! inputs change
INFO(9) = 1
! reserve space in the single precision storage structure
INFO(10) = 0
! call the Type check subroutine to compare what this Type requires to
! what has been supplied in the input file.
CALL TYPECK(1,INFO,NI,NP,ND)
! call the input-output check subroutine to set the correct input and
!output variable units.
CALL RCHECK(INFO,YCHECK,OCHECK)
! return to the calling program.
RETURN 1
ENDIF
!-----------------------------------------------------------------------------!
RE-READ THE PARAMETERS IF ANOTHER UNIT OF THIS TYPE HAS BEEN CALLED SINCE
!
THE LAST TIME THEY WERE READ IN
IF(INFO(1).NE.IUNIT) THEN
!reset the unit number
IUNIT = INFO(1)
ITYPE = INFO(2)
!read the parameter values
QMAX
= PAR(1)
CP
= PAR(2)
UA
= PAR(3)
HTREFF = PAR(4)
ENDIF
!-----------------------------------------------------------------------------!
RETRIEVE THE CURRENT INPUT VALUES FROM THE XIN ARRAY
TIN = XIN(1)
FLOW = XIN(2)
IGAM = JFIX(XIN(3)+0.1)
TSET = XIN(4)
TAMB = XIN(5)
!
CHECK THE INPUTS FOR VALIDITY AND RETURN IF PROBLEMS ARE FOUND
IF (FLOW.LT.0.)
CALL TYPECK(-3,INFO,2,0,0)
IF ((IGAM.GT.1.).OR.( IGAM.LT.0.))
CALL TYPECK(-3,INFO,3,0,0)
IF (ErrorFound() ) RETURN 1
!
836
PERFORM CALCULATIONS
IF (FLOW .GT. 0.) GO TO 10
NO FLOW CONDITION
OUT(1) = TIN
OUT(2) = 0.
OUT(3) = 0.
OUT(4) = 0.
OUT(5) = 0.
RETURN 1
!
!
10
FLOW CONDITION
CHECK INLET TEMPERATURE AND CONTROL FUNCTION
IF ((TIN.LT.TSET).AND.(IGAM.EQ.1)) GO TO 20
!
20
HEATER ON CONDITION
TON =(QMAX*HTREFF+FLOW*CP*TIN+UA*TAMB-UA*TIN/2.d0)/(FLOW*CP+UA/2.d0)
TOUT = MIN(TSET,TON)
TBAR = (TIN+TOUT)/2.d0
QAUX = (FLOW*CP*(TOUT-TIN)+UA*(TBAR-TAMB))/HTREFF
QLOSS = UA*(TBAR-TAMB) + (1.d0-HTREFF)*QAUX
QFLUID = FLOW*CP*(TOUT-TIN)
!
50
SET OUTPUTS
OUT(1) = TOUT
OUT(2) = FLOW
OUT(3) = QAUX
OUT(4) = QLOSS
OUT(5) = QFLUID
RETURN 1
END SUBROUTINE Type151
837
838
8.4. Reference
8.4.1.
Global constants
8.4.1.1.
Constant
Default
Comment
nMaxUnits
1000
nMaxEquations
500
nMaxDerivatives
100
nMaxOutputs
3000
nMaxParameters
2000
nMaxStorageSpots
10000
nMaxFiles
300
nMaxDescriptions
750
nMaxVariableUnits
750
nMaxLabels
100
nMaxFormats
100
nMaxChecks
20
nMaxCheckCodes
30
nMaxUnitConversions 250
nMaxUnitTypes
250
nMaxCardValues
250
minTimeStep
0. 1
3600
nMaxTimeSteps
109
nMaxPlottedTimeSteps 525601
nMaxErrorMessages
1000
839
8.4.1.2.
Constant
Default
Comment
maxPathLength
300
maxFileWidth
1000
maxDescripLength
25
maxVarUnitLength
20
maxEqnNameLength
20
maxLabelLength
300
maxMessageLength
800
840
8.4.2.
Access functions
This section lists all functions declared in the "TrnsysFunctions" module. Note that the
subroutines used to handle data storage are mentioned here for the record, but detailed
explanations on their use can be found in section 8.4.4.16.
Please note that the first group of access functions (getMaxDescripLength(), etc.) provide access
to global constants. Those constants are declared in the TrnsysConstants module, so Frotranwritten Types can access them more easily through an "use" statement: use TrnsysConstants.
Those access functions are provided for non-Fortran Types.
8.4.2.1.
function getMaxDescripLength( )
8.4.2.2.
function getmaxFileWidth( )
8.4.2.3.
function getMaxLabelLength( )
841
INTEGER LabLen
...
LabLen = getMaxLabelLength()
8.4.2.4.
function getMaxPathLength( )
8.4.2.5.
function getnMaxStorageSpots( )
8.4.2.6.
function CheckStability( )
This function is only used with Solver 1 (Powell's method). You can find more
information on TRNSYS Solvers in Volume 07, TRNEdit (check the section on
the Solver Statement).
An integer function that returns a 1 if the last time step converged and a 0 if the last time step did
not converge. The CheckStability function is used in SOLVER 1, which tries more than one
control strategy and then backs up a time step in order to try something else if it did not find a
stable solution. TRNSYS data reading components need to know that they should not continue
reading the data file but should back up as well.
Example Usage
if (CheckStability() < 1) then
backspace(LU_DATA)
endif
842
8.4.2.7.
function ErrorFound( )
Logical function that returns a value of TRUE if TRNSYS errors have been found. This function
is most useful in Types that call one or more of the TRNSYS Utility subroutines (such as
TYPECK, PSYCHROMETRICS, or STEAM) which may call find and flag errors. For example, say
a user written Type calls TYPECK to indicate that one of the INPUTS had an inappropriate value.
TYPECK would call the TRNSYS utility subroutine MESSAGES, which would print out the error,
would log that an error occurred and would return control to TYPECK. TYPECK would in turn
return control to the Type, which can then avoid the remainder of its calculations by accessing the
ErrorFound function. An example follows in which calculations cease if an illegal value of the
input variables FLOW_CHW, FLOW_CW, or FLOW_HW is found.
Example Usage
IF(FLOW_CHW.LT.0.) CALL TYPECK(-3,INFO,2,0,0)
IF(FLOW_CW.LT.0.) CALL TYPECK(-3,INFO,4,0,0)
IF(FLOW_HW.LT.0.) CALL TYPECK(-3,INFO,6,0,0)
IF( ErrorFound() ) RETURN 1
8.4.2.8.
function getConvergenceTolerance( )
Double precision function that returns the user specified value of a simulations convergence
tolerance (the second argument in the TOLERANCES keyword statement).
Example Usage
DOUBLE PRECISION ErrTol
...
ErrTol = getConvergenceTolerance()
8.4.2.9.
function getDeckFileName( )
A character function that returns the name (NOT including the path) of the input file being run.
This function is useful in printer and other output devices in which results that pertain to a
particular input file are to be stored. The length of the returned string is maxPathLength.
Example Usage
USE TrnsysConstants, ONLY: maxPathLength
CHARACTER (len=maxPathLength) DeckName
...
DeckName = getDeckFileName()
843
myFormat = getFormat(INFO(1),1)
...
! Print or read using myFormat
write(luPrint,myFormat) ... variables to be printed
844
close(LU,status='keep')
845
integer TRNSolver
...
if (TRNSolver == 0) then
... Do things required for successive substitution
else
... Do things required for Powell's solver
endif
846
Example Usage
USE TrnsysConstants, ONLY: maxPathLength
CHARACTER (len= maxPathLength) ExeLoc
...
ExeLoc = getTrnsysExeDir()
RootDir = getTrnsysRootDir()
847
...
do j = 1, nVariables
columnHeader = getVariableDescription(INFO(1),j)
... write column header to a file, etc...
enddo
848
8.4.3.
The INFO array is an integer array of 15 values. It conveys to the component subroutines (Types)
and to the TRNSYS kernel information about the current UNIT. The contents of the INFO array
for a given unit are given in Table 8.4.2.31-1 (see text for detailed explanations).
Table 8.4.2.31-1: INFO array contents
INFO(n)
Role
Unit number
Type number
Number of iterative calls to this Unit in the current time step. Special values: -1, -2
Indicate whether or not the Type depends on the passage of time and tells TRNSYS
where the Type should go in the calling sequence
10
11
12
TRNSYS version for which the Type was written (15 or 16)
13
Indicates when all Units have converged in the current time step
14
15
8.4.3.1.
INFO(1:5)
The fist 5 spots in INFO are set by TRNSYS from information in the input file (.dck). They are
used to distinguish the current Unit / Type from the other ones and to detect possible
configuration errors with the TYPECK routine. It is possible to check that the number of
parameters in the input file is acceptable, etc.
8.4.3.2.
INFO(6)
INFO(6) indicates the number of outputs used by the Type. A minimum of 20 outputs is reserved
for each unit in the simulation, but INFO(6) should always be set to provide an accurate Trace
and insure efficient error checking.
849
8.4.3.3.
INFO(7)
INFO(7) indicates how many times the Unit has been called in the current time step. This
information is very useful for building stability into user written controller routines and for
eliminating unneeded calculations at each time step. INFO(7) also carries out information through
special values (-1 and -2). Possible values of INFO(7) are listed in Table 8.4.3.3-1.
Table 8.4.3.3-1: INFO(7) values
INFO(7)
Role
-2
Special call at the very beginning of the simulation to allow for Type version signing.
Types should only set the value of INFO(13) during this call
-1
Initial call in simulation for this Unit. The Type should only perform initialization
operations here: array sizing, memory allocation, file opening, parameter checking,
etc. The Type should also set the value of INFO(6), INFO(9) and INFO(10) (if used)
First iterative call (second call) in the current time step for this Unit
Second iterative call (third call) in the current time step for this Unit
+n
8.4.3.4.
nth iterative call ((n+1)th call) in the current time step for this Unit
INFO(8)
INFO(8) indicates how many times the Unit has been called in the simulation. INFO(8) also
carries out information through special values (-1). Possible values of INFO(8) are listed in Table
8.4.3.4-1.
Table 8.4.3.4-1: INFO(8) values
INFO(8)
850
Role
Initial conditions at Time = Start time (no iteration for this time step)
First call of the first time step (Time = Start time + Time step)
Second call of the first time step (Time = Start time + Time step)
Third call of the first time step, or first call of next time step
Etc
-1
Very last call of the simulation. This call occurs after the "OK" or "Continue? Yes"
button has been pressed in TRNExe. Types should close files and perform other
post-simulation tasks during this call.
8.4.3.5.
INFO(9) indicates if the Type depends on the passage of time and tells TRNSYS where it should
go in the calling sequence. Different options are available: normal (iterative) component,
integrator, printer, etc. INFO(9) is initialized to 1 for all Types by the TRNSYS Kernel. Each Type
can change that value during the initialization call (when INFO(7) = -1).
Possible values of INFO(9) are listed in Table 8.4.3.5-1. Please note that the introduction of a
post-convergence call (flagged with INFO(13) = 1) makes some of the options offered by INFO(9)
redundant. They have been kept for backwards compatibility.
Table 8.4.3.5-1: INFO(9) values
INFO(9)
Role
The Type's outputs only depend upon its input values and not explicitly upon time.
Note that failure to properly identify such a component (keeping the default value of
INFO(9) = 1) will only results in some unnecessary calls to the component
1
(default)
The Type's outputs depend upon the passage of time and the Type must therefore
be called at least once every time step even if the values of inputs do not change
The Type should be called after all other components have converged and before
the integrators and printers. User-written statistic subroutines that send their output
to integrators is a situation where this may be appropriate.
Standard integrators
Standard printers
The Type should be called after all other components have converged and after the
integrators and printers. User-written output subroutines and non-iterative
controllers are situations for which this would be appropriate.
Note that the order in which components are called does not match the logical progression
in INFO(9) values for backwards compatibility reasons. The calling sequence is as follows:
Iterations during a time step: Units with INFO(9) = 1 (and Units with INFO(9) = 0 if their
inputs have changed) are called iteratively.
Convergence has been reached. All INFO(9) = 1 and 0 are called again with INFO(13) = 1
so they can perform post-convergence manipulations (e.g. store values)
INFO(9) = 3 components (user-written routines to be called after convergence but before
integrators) are called once
INFO(9) = 4 components (standard integrators) are called once
INFO(9) = 5 components (standard printers) are called once
INFO(9) = 2 components (user-written components to be called after integrators and
printers) are called once
This calling sequence only applies to normal time steps. All components are called once, in an
order according to their Unit numbers, during the following calls:
Version signing call (INFO(7) = -2)
Initialization call (INFO(7) = -1)
851
Initial time step (INFO(7) = 0, TIME = Start time). No iterations are performed, Types
should just output initial conditions. and the very
Very last call (INFO(8) = -1)
8.4.3.6.
INFO(10)
INFO(10) was used for storage management in TRNSYS 15. It was used to send the number of
required storage spots to TYPECK and then receive the index of the first reserved spot in the
global storage array. That way of handling storage is obsolete in TRNSYS 16 and should not be
used anymore. It is still present to allow TRNSYS 15 Types to run in legacy mode. Please note
that the storage array accessed by those Types is single-precision, unlike the storage array
manipulated through the new access functions (SetStorageSize, SetStorageVars,
GetStorageVars). The standard way of handling variable storage in TRNSYS 16 is described in
section 8.4.4.16.
8.4.3.7.
INFO(11)
INFO(11) sets the number of discrete control variables in the Type. It should only be set to a nonzero value if Solver 1 must be used with the Type. It is very important to make sure that the
Solver used in a simulation is handled properly by all Types. For more details about Solver 1,
please refer to the Solver Statement description in Volume 07, TRNEdit manual.
8.4.3.8.
INFO(12)
INFO(12) indicates the TRNSYS version for which the Type was written (15 or 16). It must be set
at the very first call during the simulation (INFO(7) = -2).
8.4.3.9.
INFO(13)
INFO(13) is a flag that indicates that all the Units have converged during the current time step. It
is 0 during iterative calls and 1 during the post-convergence call. Special units for which the Type
has set INFO(9) to any value greater than or equal to 2 will only be called once per time step, with
INFO(13) = 1.
852
It is assumed that the total number of iterative calls to the Type in the simulation (which is
reported in the "Iterative call breakdown" in the listing and log files) is nCalls.
The Type is assumed to follow TRNSYS 16 Standard (i.e. it is not signed as a "15" Type and
it does not use the old storage array)
Table 8.4.3.10-1: Typical INFO calling sequence for an iterative Type
Call description
Time
INFO element
6
10
11
12
13
Start
-2
-10
Initialization call
Start
-1
-10
16
Start
nO
16
st
st
Start+Step
nO
16
st
nd
st
Start+Step
nO
16
st
rd
nd
Start+Step
nO
16
Start+Step
nO
16
1 step, 1 call
1 step, 2 call (1 iter.)
1 step, 3 call (2 iter.)
st
1 step, post-convergence
nd
st
Start+2*Step
nO
16
nd
nd
st
Start+2*Step
nO
16
nd
rd
nd
Start+2*Step
nO
10
16
2 step, post-convergence
Start+2*Step
nO
11
16
etc.
16
2 step, 1 call
2 step, 2 call (1 iter.)
2 step, 3 call (2 iter.)
nd
st
Stop
nO
nCalls-3
16
nd
st
Stop
nO
nCalls-2
16
rd
nd
Stop
nO
nCalls-1
16
Stop
nO
nCalls
16
Stop
nO
-1
16
853
854
8.4.4.
Utility subroutines
8.4.4.1.
In order to allow calls to external programs, a utility subroutine named CALLPROGRAM has
been added to TRNSYS with the release of TRNSYS 15. CALLPROGRAM uses several Win32
Application Programming Interface (API) commands to start the external program. API
commands directly control the Windows operating system. Depending on the mode specified in
the call statement, CALLPROGRAM will either wait for the second program to finish its task
before proceeding or will merely start the second program and then proceed with other TRNSYS
calculations. The call statement for CALLPROGRAM is:
...
CALL CALLPROGRAM(CMDLINE,bwait,prochand, thrdhand)
...
Where:
CMDLINE
is the command line text string containing the path and name for
the executable program
BWAIT
PROCHAND
THRDHAND
When CALLPROGRAM is used to start another program and leave it running (BWAIT =
.FALSE.), then the program needs to be terminated at the end of the simulation before leaving
TRNSYS. This can be done by using the following commands:
...
res = TerminateProcess(PROCHAND,1)
IF (res.EQ.0) THEN
WRITE(CHCKWHY,*) GETLASTERROR()
ENDIF
...
See the source code of Type 66 (CALL EES MODELS) for an example of the use of
CALLPROGRAM.
855
8.4.4.2.
DFIT (FIT)
GENERAL DESCRIPTION
Subroutines FIT and DFIT use linear least-squares regression to determine coefficients of a user
defined correlation. FIT requires single precision arguments, while DFIT uses double precision
arguments. Since a majority of the kernel routine and standard components use double precision
variables throughout, it is recommended that user written routines employ the double precison
version DFIT. A call to DFIT is of the form:
INTEGER :: NROW,NCOL,NCOEF,NDATA,IFLAG
DOUBLE PRECISION :: X,Y,PHI
...
CALL FIT(NROW,NCOL,NCOEF,NDATA,X,Y,PHI,IFLAG,*N)
where,
NROW
NCOL
NCOEF
NDATA
PHI
IFLAG
J=
N data
(Y
j =1
Ymod el , j =
Ymod el , j )
Eq. 8.4.4-1
N coef
X
i =1
i, j
Eq. 8.4.4-2
where,
856
Yj
Ymodel,j
dependent variable of the user's model for the jth data point
Xi,j
Example
Consider the equation used in the Type53 Chiller component. The dimensionless
power consumption is correlated with performance data using the following bi-quadratic equation:
G = a0 + a1 E + a2 E 2 + a3 F + a4 F 2 + a5 EF
Eq. 8.4.4-3
3.0
0.2
10.0
5.0
0.4
12.5
7.0
0.6
13.1
NCOL =
NCOEF =
NDATA =
857
X=
1.0
1.0
1.0
E1
E2
E3
E1 2 E2 2 E3 2
F1
F2
F3
F1 2 F2 2 F3 2
Eq. 8.4.4-4
10.0
Y = 12.5
13.1
Eq. 8.4.4-5
The DFIT subroutine would be called with the above input data and return values for PHI and
IFLAG. PHI would be a vector containing the values for a0-a5.
858
8.4.4.3.
DIFFERENTIAL_EQN (DIFFEQ)
The double precision utility routine Differential_Eqn and its single precision companion DIFFEQ
provide analytical solutions to first-order linear differential equations that can be written as
dT
= aT + b
dt
Eq. 8.4.4-6
The designation double precision means that the arguments and results of the utility routine
Differential_Eqn must be declared in the calling Type as DOUBLE PRECISION variables as
opposed to REAL or INTEGER variables. In TRNSYS version 15.x and below, only a single
precision version of this utility was available. That single precision version (called DIFFEQ) was
maintained for completeness and backward compatibility but it is highly recommended that user
employ the double precision version (called Differential_Eqn) whenever possible.
Users intending to utilize the Powells method TRNSYS solver (SOLVER 1) should use the
Differential_Eqn subroutine discussed here instead of the optional DTDT array discussed in
section REVISIT. The form of the call to Differential_Eqn is:
CALL DIFFERENTIAL_EQN(TIME, AA, BB, TI, TF, TBAR)
where
TIME
AA
BB
TI
TF
TBAR
The Differential_Eqn routine does not require link checking since it is considered to be a kernel
routine; those routines which must be present to successfully run TRNSYS.
Differential_Eqn solves differential equations at each call based on parameters and the current
set of inputs. If the inputs have not converged, the iteration proceeds by direct substitution
provided that the Successive Substitution solver (SOLVER 0) is being used. Additional notes on
the analytical solution of differential equations are as follows:
1)
Differential_Eqn requires the arguments AA, BB, and TI, while returning TF and TBAR.
For calls to Differential_Eqn at the start time of the simulation (TIME= TIME0), the initial
condition TI is returned for both TF and TBAR.
2)
It is necessary to save the final values of dependent variables each time step as initial
conditions for the following interval. This can be done using calls to the getStorageVars
and setStorageVars routine discussed in sections 0 and 0.
859
3)
Inputs will often be a function of the dependent variable of the differential equation. For
instance, collector outlet temperature, which might be an input to a storage component,
might also be a function of the storage temperature. In order to get a good estimate of
the average inputs over each interval, TBAR should be set as an output if required as an
input of other components. To be consistent with this formulation and the rectangular
integration provided by Type24, etc., any outputs that are rates and are expressed as a
function of the dependent variable T should be evaluated at TBAR.
As an example of a model formulation, suppose that one wishes to study the temperature
response of a one-node house to ambient conditions. The instantaneous energy balance for this
situation is given as
dTR
= (UA) L (TR Ta )
dt
Eq. 8.4.4-7
a=
(UA) L
C
and
b=
(UA) L Ta
C
Eq. 8.4.4-8
The following code would establish initial conditions, solve the differential equation for the final
and average temperatures, and determine the average energy loss rate from the house for each
time interval.
DOUBLE PRECISION :: STORED(2),TI,AA,BB,UAL,TA,C,QLOSS,TF,TBAR
INTEGER :: NS,INFO(15)
...
!this section is executed at the end of each timestep. In this case it is
!used to update the storage structures for the following time step.
IF(INFO(7).EQ.13) THEN
CALL getStorageVars(NS,STORED,INFO)
STORED(1) = STORED(2)
CALL setStorageVars(NS,STORED,INFO)
ENDIF
...
CALL getStorageVars(NS,STORED,INFO)
TI = STORED(1)
AA = -UAL/C
BB = UAL*TA/C
CALL DIFFERENTIAL_EQN(TIME,AA,BB,TI,TF,TBAR)
STORED(2) = TF
QLOSS = UAL*(TBAR - TA)
CALL setStorageVars(NS,STORED,INFO)
...
For this particular example, the component would not be called by the kernel during any time step
after its inputs have converged within the algebraic error tolerance. There is no need for a
differential equation convergence check, since the solution will always be consistent with the
current set of inputs. A DERIVATIVES control statement should not be used for the component
in the simulation input file; the initial value of the dependent variable at the beginning of the
simulation should be supplied to the subroutines as a PARAMETER. In this respect the example
is similar to Types 12, 21 and 23.
860
8.4.4.4.
The DynamicData utility routine is available to read user supplied data from external text based
files that have been assigned a FORTRAN logical unit number in the TRNSYS input file. The
DynamicData routine is able to interpolate the data found in the file in up to four dimensions
during the course of the simulation. For each data set, up to five dependent (Y) functions may be
specified in terms of up to four independent (X) variables. At each call to the DynamicData
routine, the calling Type sends the values of each independent variable. DynamicData performs
the multi dimensional interpolation and returns the interpolated values of as many dependent
variables as have been provided in the data file and requested by the calling Type. DynamicData
is NOT able to extrapolate beyond the range of data given in the external file. If the calling Type
sends a value of an independent variable that falls above or below the range given in the data
file, DynamicData will return the values of the dependent variables that correspond to the
maximum or minimum of the range.
DynamicData is a double precision routine, meaning that the independent and dependent
variables found in the external file will be treated as FORTRAN double precision variables.
Similarly, the X and Y arrays in the calling Type must be declared as double precision. In
TRNSYS versions 15.x and below, DynamicData was known as either DATA or DYNDATA,
both of which were single precision routines. DATA and DYNDATA were retained for backwards
compatibility but every effort should be made to use the double precision DynamicData routine.
Examples of standard components that use DynamicData are the Type1 Solar Collector and the
Type44 Conditioning Equipment model. The form of a call to DynamicData is:
INTEGER :: LU,NIND,NX(:),NY(:),INFO(15)
DOUBLE PRECISION :: X(:),Y(:)
...
CALL DynamicData (LU, NIND, NX, NY, X, Y, INFO,*N)
where
LU
NIND
NX
NY
INFO
The data is read from logical unit LU at the start of the simulation. Thereafter, DynamicData
linearly interpolates for Y values given X values. If DynamicData is called with an X out of range
861
of the supplied data, then the closest specified value is used. DynamicData does not extrapolate
beyond the user supplied data.
The data supplied on the logical unit is read in free format. If NIND equals 4 and NX(4) is greater
than 1, then NX(4) values of the fourth independent variable X4 are read first. Similarly, if NIND
3 and NX(3) > 1, then a set of NX(3) values of the third independent variable, X3 are read. Next,
if NIND 2 and NX(2) > 1, then a set of NX(2) values of the second independent variable X2 are
read. Lastly, NX(1) values of the primary independent variable, X1, are read. The values of the
independent variables must be in ascending order, but need not be at regular intervals. The Y
values are read beginning with values corresponding to the smallest values of X1, X2, X3, and X4.
NX(1) sets of NY values of Y are read for each value of X2. NX(2) sets of NX(1) * NY values of Y
are read for each value of X3. In all, if 4 independent variables are employed, then NX(4) * NX(3)
* NX(2) * NX(1) * NY values of Y must be specified.
Example:
A user wishes to write a model for a water-to-water heat pump whose
performance depends upon the inlet flow stream temperatures to both the evaporator (Tevap)
and condenser (Tcond). DynamicData is to be used to evaluate both the capacity and COP. The
experimental data is shown in Table 8.4.4.4-1.
Table 8.4.4.4-1
Tcond = 20C
Tcond = 50C
Tevap (C)
Capacity (kJ/hr)
COP
Tevap (C)
Capacity (kJ/hr)
COP
10
35000
2.47
10
21000
1.73
20
41000
2.80
20
25000
1.96
30
49500
2.99
30
29000
2.09
The data is to be read from logical unit 10. Three values of Te and two values of Tc will be
supplied. The call to DynamicData within the calling Type routine might appear as
USE TrnsysFunctions
...
INGEGER :: NX(2),INFO(15),DUM
DOUBLE PRECIsion :: X(2),Y(2),CAP,COP,T_EVAP,T_COND
...
NX(1) = 3
!declares that there are 3 nx 1 values in the file.
NX(2) = 2
!declares that there are 2 nx 2 values in the file.
X(1)
= T_Evap
!sets x(1) to the local variable t_evap
X(2)
= T_Cond
!sets x(2) to the local variable t_cond
101
The syntax of the data file accessed through logical unit 10 would be as follows:
862
20.0 50.0
!Tcond values
!Tevap values
35000. 2.47
41000. 2.80
49500. 2.99
21000. 1.73
25000. 1.96
29000. 2.09
863
8.4.4.5.
ENCLOSURE (ENCL)
General Description
The utility routine ENCLOSURE (and its single precision companion ENCL) calculate view factors
between all surfaces of a rectangular parallelpiped. Up to 9 windows or doors may be located on
any of the 6 wall surfaces. ENCLOSURE is a double precision routine, meaning that its
arguments must be declared in the calling Type as double precision variables (as opposed to
REAL variables). The values returned by ENCLUSRE are also double precision. In TRNSYS
versions 15.x and below, ENCLOSURE was known simply as ENCL, which was a single
precision routine. ENCL was retained for backwards compatibility and every effort should be
made to use the double precision ENCLOSURE routine.
This routine is used by the TYPE 19 zone model. A call to ENCLOSURE is of the form
DOUBLE PRECISION :: SPAR(10),WPAR(10),FV
INTEGER :: INFO(15)
...
CALL ENCLOSURE (SPAR, WPAR, FV, INFO,*N)
where
SPAR
WPAR
FV
INFO
Subroutine ENCLOSURE outputs a table of the view factors between surfaces. The surface
numbers are as specified in the SPAR array.
Mathematical Description
Subroutine ENCL utilizes function subroutine VIEW to obtain view factors between continuous
rectangular surfaces. Reciprocity is also used to reduce the number of computations. In order to
determine view factors between surfaces that contain windows or doors, it is necessary to
perform some view factor algebra.
Consider the general case of m windows located on a surface i and n windows on a surface j as
shown in Figure 8.4.4.5-1.
864
jW
W i1
W i2
W i3
Wj2
j1
Wj3
W jn
W im
i
Figure 8.4.4.5-1
Fi j = Fi ( j + W ji + ... + W jn ) Fi (W jk )
n
Eq. 8.4.4-9
k =1
where
Fi ( j +W j1 + ... +W jn ) =
(A
+ AW j1 + ... + AW jn F( j +W j1 + ...+W jn ) i
Ai
Eq. 8.4.4-10
Eq. 8.4.4-11
k =1
Fi W jk =
AW jk F(W jk ) i
Eq. 8.4.4-12
Ai
Eq. 8.4.4-13
l =1
The variables Wi1 through Wim are the surface numbers associated with windows on wall i.
Likewise, Wj1 through Win refer to windows on wall j. Thus, (i+Wi1+...Win) and (j+Wj1+... Wjm),
each denote surfaces that are collections of individual surfaces. The variable A refers to the area
of a surface whose number is used as a subscription.
865
8.4.4.6.
FLUID_PROPS (FLUIDS)
The double precision utility routine called Fluid_Props and its single precision companion FLUIDS
are used to calculate the thermodynamic properties of various refrigerants based on correlations.
Arguments to the Fluid_Props routine should be declared in the calling Type as DOUBLE
PRECISION variables. Arguments to the FLUIDS routine should be declared in the calling Type
as REAL. With TRNSYS version 15.x and below, only the single precision version was available.
Since most kernel and standard Type variables were made DOUBLE PRECISION with the
release of TRNSYS version 16.0, every effort should be made to employ the double precision
version of this routine (Fluid_Props). Given two state properties, the Fluid_Props routine will
return the complete state of the refrigerant. A call to FLUIDS is of the form
INTEGER :: NREF,ITYPE,IFLAG
DOUBLE PRECISION :: PROP(9)
CHARACTER(len=2) :: UNITS
...
CALL FLUIDS (UNITS,PROP,NREF,ITYPE,IFLAGR,*N)
where
UNITS
PROP
PROP(1)
PROP(2)
PROP(3)
PROP(4)
PROP(5)
PROP(6)
PROP(7)
PROP(8)
PROP(9)
NREF
866
R-12
(12)
R-13
(13)
R-14
(14)
R-22
(22)
R-114
(114)
R-134A
(134)
R-500
(500)
R-502
(502)
AMMONIA
(717)
ITYPE
IFLAGR
An example illustrating the use of the FLUID_PROPS routine is shown below. In the example,
two inputs (temperature and quality) are read and are placed in the PROP array. The Fluid_Props
routine is called. If the Fluid_Props routine is not found for some reason, the error handling
routine called LINKCK is called (refer to section 8.4.4.7 for more information). If Fluid_Props
returns, the example checks to make sure that no errors were reported by Fluid_Props by calling
an Access Function called ErrorFound( ) (refer to section 8.4.2.6 for more information). If errors
were detected, execution of the Type that called Fluid_Props stops immediately by returning
control to the calling program. If errors were not found then the PROP array has been filled. The
Second and third array spots are set to local variables and Type execution continues normally.
100
USE TrnsysFunctions
...
CHARACTER(len=2) :: UNITS
DOUBLE PRECISION :: PROP(9),XIN(2),TEMP,QUALITY,PRESSURE,ENTHALPY
INTEGER :: NREF
...
UNITS = SI !SI units are desired.
NREF = 12
!Refrigerant R12
...
TEMP = XIN(1)
QUALITY = XIN(2)
...
PROP(1) = TEMP
PROP(5) = QUALITY
CALL FLUID_PROPS(UNITS,PROP,12,15,IFLAG,*100)
CALL LINKCK('TYPE58','FLUID_PROPS',1,58)
IF (ErrorFound()) RETURN 1
...
PRESSURE=PROP(2)
ENTHALPY=PROP(3)
MATHEMATICAL DESCRIPTION
The correlations required to solve for the refrigerant properties are from the Engineering Equation
Solver program (F-chart software, 1994), a numerical solver employing thermodynamic
correlations from many different sources. Interested users should contact the reference for more
details on the correlations.
Enthalpies for ammonia and R134a are based on the reference state: enthalpy equal to zero at 40C.
867
Enthalpies for all other refrigerants are based on the reference state: enthalpy equal to zero at
0C
This subroutine checks for many improper inputs, such as qualities less than 0. or greater than 1.,
and the input of two properties that cannot be correct for one state. For these and other improper
inputs, the subroutine either prints a warning, corrects one of the inputs, and continues; or prints
an error and halts the simulation.
Subcooled properties are not available for refrigerants. If a subcooled state is specified, the
saturated liquid results will instead be provided.
868
8.4.4.7.
LINKCK
The LINKCK subroutine is a utility subroutine used for the detection and subsequent error
message printing of unlinked subroutines. With earlier version of TRNSYS (up to version 15.0)
the LINKCK routine was of vital importance because as a memory saving step TRNSYS was
often compiled to include only those kernel routines that were critical to a given simulation. With
advances in computing power and speed, this step became less and less important. LINKCK
remains as a safeguard against inadvertently unlinked routines but almost always, unlinked
routines will be caught during the compiling and linking processes. A call to LINKCK is of the
form:
CHARACTER(len=12) :: ENAME1,ENAME2
INTEGER :: ILINK,LNKTYP
...
CALL LINKCK(ENAME1,ENAME2,ILINK,LNKTYP,*N)
where
ENAME1
ENAME2
ILINK
LNKTYP
The LINKCK subroutine is provided to the users as a means to standardize the TRNSYS error
and warning messages associated with unlinked subroutines. The user should only call LINKCK
when an unlinked subroutine is detected or an external function is required.
The following example should clarify the use of the LINKCK subroutine. Refer to section 3.3.5 for
more details.
SUBROUTINE TYPE75(TIME,XIN,OUT,T,DTDT,PAR,INFO,ICNTRL,*)
...
CHARACTER(len=12) ENAME1,ENAME2
DOUBLE PRECISION :: SPAR(10),WPAR(10),FV
INTEGER :: ILINK,LNKTYP,INFO(15)
...
!CALL THE ENCLOSURE SUBROUTINE AND INFORM LINKCK IF NOT PRESENT
CALL ENCLOSURE(SPAR,WPAR,FV,INFO,*101)
!STOP THE PROGRAM IF ENCL IS NOT PRESENT
ILINK = 1
IDUM = 75
ENAME1 = TYPE75
ENAME2 = ENCLOSURE
869
CALL LINKCK(ENAME1,ENAME2,ILINK,IDUM)
101
870
8.4.4.8.
where
NRC
(integer) is the column and row dimensions of the twodimensional A array as defined in the program that calls
Matrix_Invert.
IFLAG
The inverted matrix is returned in the A array. The method used to invert the matrix is the GaussJordan reduction with maximum pivoting.
871
8.4.4.9.
MESSAGES
The Messages utility routine provides the Type programmer with a convenient method of
reporting error messages to the end user. When a Type catches a particular condition, it can
send a text string and information as to the severity of the condition to the Messages utility
subroutine. Messages will take care of logging the event, reporting it to both the simulation list
and log files, and stopping the simulation if appropriate.
INTERFACE
subroutine Messages(errorCode,message,severity,unitNo,typeNo)
integer :: errorCode
character (len=*) :: message, severity
integer :: unitNo, typeNo
(Note: Although the length of message is not explicitly declared, it should never exceed the
maxMessageLength global constant).
USAGE
ERRORCODE
refer
to
the
If you wish to generate a custom error message (as will most often be the case for user-written
Types), simply set ErrorCode to a value of 1, indicating the messages that the second argument
(message) contains the information to be printed.
MESSAGE
If you are generating a custom error message, this string variable will be printed in a standard
format by the Messages subroutine. It should consist of one line of text, shorter than
maxMessageLength. The example here below illustrates the use of Write to add run-time
information to the message.
If you are using a standard error message, the string text will be printed in addition to the
standard error message under the heading Reported Information. It is a method for providing
additional information about the error.
SEVERITY
severity is a string that indicates the severity of the message. Messages understands 4 levels of
severity:
"Notice": A notice is simply information that you would like the user to know
"Warning": The messages subroutine keeps track of how many "Warning" messages have
been generated. If the maximum allowable number of warnings (set by the LIMITS statement
in the input file) are exceeded, then the messages subroutine automatically generates a
"Fatal" error.
"Fatal": Designates a fatal error, i.e. an error that should stop the simulation. A call to
Messages with such an error should be followed by a "return 1" statement in the calling
Type. Note that TRNSYS will stop after going up the chain of "return" statements and giving
872
the chance to all subroutines to perform end-of-simulation operations. Further errors might
be generated during that process.
"Stop": The error will abort TRNSYS immediately without going up the chain of "return"
statements, by generating an exception in the DLL and returning control to TRNExe.exe.
This error type should only be used as a last resort, e.g. when returning from that error
would result in memory access violations or other exceptions. Exiting from a DLL by
generating an exception is generally considered as bad programming and users should only
use this technique if the cost of modifying the Type to handle the error properly is too high.
Note: severity is a Fortran literal string and can be enclosed in single or double
quotes. Messages will understand some case variants of the codes here above.
e.g. notice, Notice and NOTICE are accepted (other variants are not)
EXAMPLE
The following example illustrates calls to Messages with different severity levels by a Type for
which par(1)>10 is not acceptable (values <10.1 are just rounded to 10 and the simulation goes
on).
subroutine type200(time,xin,out,t,dtdt,par,info,iCntrl,*)
use TrnsysConstants
Please note the use of RETURN 1 following the call to Messages with a severity of Fatal. When
the severity of the message is low (notice, message, or warning), the simulation should proceed;
thus no RETURN statement is required. In the case of a fatal message, however, the simulation
should be immediately stopped and the Type should return control to the TRNSYS kernel through
use of the RETURN 1 statement.
873
8.4.4.10. ParRead
This is an undocumented subroutine used internally by some standard Types. See the Source
code in ParRead.f90 for additional information.
874
where
TIME
INFO
IUNITS
MODE
2:
3:
4:
5:
6:
7:
and
humidity
ratio
875
value of enthalpy. 8:
input relative humidity
enthalpy (PSYDAT(6) and PSYDAT(4)).
and
WBMODE
PSYDAT(1)
PSYDAT(2)
PSYDAT(3)
PSYDAT(4)
PSYDAT(5)
PSYDAT(6)
PSYDAT(7)
PSYDAT(8)
PSYDAT(9)
(double precision) density of the air portion of the mixture (kg dry
air/m3)
EMODE
STATUS
MATHEMATICAL DESCRIPTION
In determining a number of moist air properties the water vapor saturation pressure (PWS) is
required. The correlations (ASHRAE, 2001) used for PWS are accurate over the temperature
range of 100C to 200C. A warning is printed if moist air states occur outside this temperature
range.
876
The correlations for the dew point temperature (Ashrae, 2001) are accurate over the temperature
range of -60C to 70C. A warning is printed if moist air states occur outside this dew point
range.
Enthalpies are based on the following reference states:
air enthalpy is zero at 0C
liquid water enthalpy is zero at 0C
This subroutine checks for many improper inputs, such as relative humidities less than 0. or
greater than 1., dew point temperatures greater than the dry bulb temperature, and the input of
two properties that cannot be correct for one state (such as a humidity ratio greater than
saturation humidity ratio for dry air at a given dry bulb temperature). For these and other improper
inputs, the subroutine prints a warning, corrects one of the inputs and continues, or prints an error
and halts the simulation.
877
8.4.4.12. RCHECK
The RCHECK subroutine was added to TRNSYS 14 to provide input-output mismatch checking
for all components, especially those that do not have the benefit of INPUT/OUTPUT unit
connection checking as part of an interface program such as IISiBat or the TRNSYS Simulation
Studio. A call to RCHECK is of the form:
INTEGER ::INFO(15)
CHARACTER(len=3) :: YCHECK(:),OCHECK(:)
...
CALL RCHECK(INFO,YCHECK,OCHECK)
where
INFO
YCHECK
OCHECK
The RCHECK array is passed the input and output types for each component in the simulation
and stores these variables in arrays with the same structure as the XIN and OUT arrays. When
the TRNSYS processor checks for input-output mismatches, the arrays are inspected to ensure
that the variable types for an input-output connection are consistent.
A user formulating a new component should utilize the input/output checking feature of TRNSYS
for two reasons: input/output checking ensures that TRNSYS connections are correctly defined,
and output information such as output type and output units are carried with the output and are
able to be processed by the TYPE 25 printer and the TYPE 57 unit conversion routine.
The first step in input/output checking is to characterize the inputs and outputs using Table
3.4.12.1. Users wishing to create additional input-output types or add a unit conversion to an
existing input-output type should modify the file UNITS.LAB, keeping the same format and style
as the original. Refer to the TYPE 57 unit conversion routine for more details on modifying this
file. The input-output types should be stored in the YCHECK and OCHECK arrays respectively.
The final step in using the input/output checking is to call the RCHECK array at the proper time,
with the proper arrays. The RCHECK routine should be called during the first iteration in most
cases (INFO(7)=-1 see Section 8.4.3) and after the call to the TYPECK subroutine (see Section
3.4.1).
878
The following example should help clarify the use of the RCHECK subroutine:
SUBROUTINE TYPE75(TIME,XIN,OUT,T,DTDT,PAR,INFO,ICNTRL,*)
!3 INPUTS AND 4 OUTPUTS FOR THIS TYPE
!INPUTS: TEMPERATURE IN (F)
!
MASS FLOWRATE IN (LBM/HR)
!
CONTROL SIGNAL (0 OR 1)
!OUTPUTS: TEMPERATURE OUT (C)
!
MASS FLOWRATE OUT (KG/HR)
!
HEAT TRANSFER RATE (KJ/HR)
!
HEAT TRANSFER RATE (W)
...
CHARACTER(len=3) :: YCHECK(3),OCHECK(4)
INTEGER :: INFO(15)
...
DATA YCHECK/TE2,MF3,CF1/
DATA OCHECK/TE1,MF1,PW1,PW2/
...
IF (INFO(7).EQ.-1) THEN
...
CALL RCHECK(INFO,YCHECK,OCHECK)
...
ENDIF
Table 8.4.4.12-1: TEMPERATURE
VAR. TYPE #
VAR. UNITS
VAR.TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
4
C
F
K
R
TE1
TE2
TE3
TE4
1.0
1.8
1.0
1.8
0
32
273.15
492
VAR. TYPE #
VAR. UNITS
VAR. TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
4
5
6
m
cm
km
in
ft
miles
LE1
LE2
LE3
LE4
LE5
LE6
1
100
1000
39.3701
3.28084
6.21371 E-04
0
0
0
0
0
0
VAR. TYPE #
VAR. UNITS
VAR. TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
4
5
6
m2
cm2
km2
in2
ft2
mi2
AR1
AR2
AR3
AR4
AR5
AR6
1
1 E+04
1 E-06
1550
10.7639
3.86102 E-07
0
0
0
0
0
0
VAR. TYPE #
VAR. UNITS
VAR. TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
4
5
6
m3
l
ml
in3
ft3
gal
VL1
VL2
VL3
VL4
VL5
VL6
1
1000
1 E+06
6.10237 E+04
35.3147
264.172
0
0
0
0
0
0
879
VAR. TYPE #
VAR. UNITS
VAR. TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
4
m3/kg
l/kg
ft3/lbm
in3/lbm
SV1
SV2
SV3
SV4
1
1000
16.0185
2.76799 E+04
0
0
0
0
VAR. TYPE #
VAR. UNITS
VAR. TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
4
5
m/s
km/hr
ft/s
ft/min
mph
VE1
VE2
VE3
VE4
VE5
1.0
3.6
3.28084
196.85
2.23694
0
0
0
0
0
VAR. TYPE #
VAR. UNITS
VAR. TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
4
5
kg
g
lbm
ounces
ton
MA1
MA2
MA3
MA4
MA5
1
1000
2.20462
35.274
1.10231 E-03
0
0
0
0
0
VAR. TYPE #
VAR. UNITS
VAR. TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
4
kg/m3
kg/l
lbm/ft3
lbm/gal
DN1
DN2
DN3
DN4
1.0
0.001
6.2428 E-02
8.3454 E-03
0
0
0
0
VAR. TYPE #
VAR. UNITS
VAR. TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
N
lbf
ounce
FR1
FR2
FR3
1.0
0.224809
3.59694
0
0
0
VAR. TYPE #
VAR. UNITS
VAR. TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
4
5
6
7
8
BAR
kPa
Pa
ATM
psi
lbf/ft2
in. H2O
in. Hg
PR1
PR2
PR3
PR4
PR5
PR6
PR7
PR8
1
100
1 E+05
0.986923
14.5038
2.08854 E+03
401.463
29.53
0
0
0
0
0
0
0
0
VAR. TYPE #
VAR. UNITS
VAR. TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
4
kJ
kWh
Cal
ft-lbf
EN1
EN2
EN3
EN4
1
2.77778 E-04
238.846
737.562
0
0
0
0
880
5
6
hp-hr
BTU
EN5
EN6
3.72506 E-04
0.947817
0
0
VAR. TYPE #
VAR. UNITS
VAR. TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
4
5
6
7
kJ/hr
W
kW
hp
BTU/hr
BTU/min
Tons
PW1
PW2
PW3
PW4
PW5
PW6
PW7
1
0.277778
2.77778 E-04
3.72505 E-04
0.947817
1.57969 E-02
7.89847 E-05
0
0
0
0
0
0
0
VAR. TYPE #
VAR. UNITS
VAR. TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
kJ/kg
BTU/lbm
ft-lbf/lbm
SE1
SE2
SE3
1
0.429923
334.553
0
0
0
VAR. TYPE #
VAR. UNITS
VAR. TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
kJ/kg-K
W-hr/kg-K
BTU/lbm-R
CP1
CP2
CP3
1
0.277778
0.238846
0
0
0
VAR. TYPE #
VAR. UNITS
VAR. TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
4
kg/hr
kg/s
lbm/hr
lbm/s
MF1
MF2
MF3
MF4
1
2.77778 E-04
2.20462
6.12395 E-04
0
0
0
0
VAR. TYPE #
VAR. UNITS
VAR. TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
4
5
6
7
m3/hr
m3/s
l/hr
l/s
ft3/s
ft3/hr
gpm
VF1
VF2
VF3
VF4
VF5
VF6
VF7
1
2.77778 E-04
1000
0.277778
9.80958 E-03
35.3144
4.40286
0
0
0
0
0
0
0
VAR. TYPE #
VAR. UNITS
VAR. TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
kJ/hr-m2
W/m2
BTU/hr-ft2
IR1
IR2
IR3
1
0.277778
8.8055 E-02
0
0
0
VAR. TYPE #
VAR. UNITS
VAR. TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
kJ/hr-m-K
W/m-K
BTU/hr-ft-R
KT1
KT2
KT3
1
0.277778
0.160497
0
0
0
881
VAR. TYPE #
VAR. UNITS
VAR. TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
kJ/hr-m2-K
W/m2-K
BTU/hr-ft2-R
HT1
HT2
HT3
1
0.277778
4.89194 E-02
0
0
0
VAR. TYPE #
VAR. UNITS
VAR. TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
4
5
6
N-s/m2
kg/m-s
poise
lbf-s/ft2
lbf-hr/ft2
lbm/ft-hr
VS1
VS2
VS3
VS4
VS5
VS6
1
1
10
2.08854 E-02
5.80151 E-06
2419.08
0
0
0
0
0
0
VAR. TYPE #
VAR. UNITS
VAR. TYPE
MULT. FACTOR
ADD. FACTOR
1
2
3
4
m2/s
m2/hr
ft2/s
ft2/hr
KV1
KV2
KV3
KV4
1
3600
10.7639
3.87501 E+04
0
0
0
0
VAR. TYPE
Dimensionless
DM1
Degrees
DG1
Percentage
PC1
Month
MN1
Day
DY1
Hour
TD1
Control function
CF1
In user-written routines that have output variable types dependent on input variable types, such
as a statistics or integrator routine, the call to RCHECK must come on the second iteration of the
first time step, after a call to the EQUATER subroutine. The EQUATER subroutine will determine
the output connected to the unknown input and provide the appropriate input type. A call to the
EQUATER subroutine has the following form:
CHARACTER(len=3) :: TRUTYP,INDES,ODES
DOUBLE PRECISION :: X1,A1,X2,A2
INTEGER :: IU,INNO, OUTU,OUTNO,ICK1,ICK2
CALL EQUATER(IU,INNO,INDES,TRUTYP,OUTU,OUTNO,ODES,X1,A1,X2,A2,ICK1,ICK2)
where
882
IU
INNO
INDES
the desired input variable type - not used in this capacity, set to
NAV for not available (3-character variable)
TRUTYP
OUTU
OUTNO
ODES
the desired output variable type for this unknown input - not used
in this capacity (3-character variable)
X1
the multiplication factor for the INDES variable - not used in this
capacity (double precision value)
A1
the addition factor for the INDES variable - not used in this
capacity (double precision value)
X2
A2
the addition factor for the OUTDES variable - not used in this
capacity (double precision value)
ICK1
ICK2
Users attempting to use the input/output checking algorithm in this capacity should refer to the
TYPE 55 Periodic Integrator subroutine and the EQUATER subroutine source code for more
details.
883
8.4.4.13. REWIND
The Rewind Utility is designed to rewind a data file whose end has been reached through multiple
read statements. It is able to then skip a specified number of steps from the beginning of the file
and leave a pointer ready to read the first non skipped line. A call to Rewind should have the
following form:
INTEGER :: LU,SKIP,IU,IT,IE
...
CALL REWIND(LU,SKIP,IU,IT,IE)
where
LU
SKIP
IU
(integer) the unit number of the Type calling the Rewind routine.
IT
(integer) the type number of the Type calling the Rewind routine.
IE
EXAMPLE
The following example shows the usage of the Rewind routine and a possible method for
checking whether errors occurred during the rewind process.
INTEGER :: LU,SKIP,IU,IT,IE,INFO(15)
...
LU = JFIX(PAR(1)+0.1)
SKIP = 10
IU = INFO(1)
IT = INFO(2)
CALL REWIND(LU,SKIP,IU,IT,IE)
IF (IE.GT.1) THEN
RETURN 1
ENDIF
...
884
8.4.4.14. SOLCEL
SOLCEL Models silicon cell I-V characteristics
Contributor:
The SOLCEL subroutine is called by Types 49 and 50 and uses a set of empirical values to
model the cells. Data for Spectrolab type cells, provided by Professor Evans, is "built-in" and is
used by default if no other data are supplied by the user. Users may supply their own data by
adding an extra parameter to the list of TYPE 49 or TYPE 50 in modes 5-8. This extra parameter
is interpreted as the logical unit number of the file containing the cell characteristics. The data
are read using 9F10.0 format and should be ordered as follows; (default values are listed after the
definition of the parameter):
First record:
ICELL
Cell type indicator, 0 for Spectrolab and Solarix Types, 1 for RCA types (peak
power tracking only for RCA); (0).
CELLPF
Ratio of cell area to absorber area; if ICELL = 1, the numerical value is ignored,
but a number must be present; (0.8).
Second record:
TL
TH
CL
CH
VOCLL
ISCLL
ISCLH
ISCHL
ISCHH
EG
AOMIN
DAODC
RSH
RSMIN
885
886
CONTR
DRSDC
NSER
where
UNITS
PROP
PROP(1)
PROP(2)
PROP(3)
PROP(4)
PROP(5)
PROP(6)
PROP(7)
ITYPE
IERR
An example illustrating the use of the STEAM_PROPS routine is shown with the following
considerations: SI units are desired, and Temperature (PROP(1)) and Quality (PROP(5)) are
known.
USE TrnsysFunctions
...
CHARACTER(len=2) :: UNITS
DOUBLE PRECISION :: PROP(7),XIN(2),TEMP,QUALITY,PRESSURE,ENTHALPY
...
887
100
MATHEMATICAL DESCRIPTION
The correlations required to solve for the steam properties are from the EES program (8), a
numerical solver employing thermodynamic correlations from many different sources. Interested
users should contact the reference for more details on the correlations.
Enthalpies for steam are based on the following reference state: enthalpy equal to zero at 0C
This subroutine checks for much improper input, such as qualities less than 0. or greater than 1.,
and the input of two properties that cannot be correct for one state. For these and other improper
inputs, the subroutine prints a warning, corrects one of the inputs, and continues; or prints an
error and halts the simulation.
Subcooled properties are not available for steam. If a subcooled state is specified, the saturated
liquid results will instead be provided.
888
INTERFACE
subroutine setStorageSize(n,INFO)
integer :: n, INFO(15)
DESCRIPTION
The setStorageSize subroutine should be called when INFO(7) = -1. This will tell the storage data
structure how many spots it needs to reserve for your component. The subroutine has two
arguments:
n: The integer number of storage spots required by this component.
INFO: The standard INFO array is sent so that the storage data structures know what unit
and type number are requesting storage.
GETSTORAGEVARS
INTERFACE
subroutine getStorageVars(storageArray,m,INFO)
integer :: m, INFO(15)
double precision :: storageArray(*)
DESCRIPTION
When the user wants to obtain a previously stored value (usually at the first call of a new time
step, i.e. when INFO(7) = 0), a call is made to the getStorageVars subroutine. The subroutine
takes the following arguments:
889
INTERFACE
subroutine setStorageVars(storageArray,m,INFO)
integer :: m, INFO(15)
double precision :: storageArray(*)
DESCRIPTION
When the user wants to set storage at the end of a time step, a call is made to the
setStorageVars subroutine when INFO(13) > 0. Much like the getStorageVars subroutine, the
setStorageVars subroutine takes the following arguments:
storageArray: a locally defined double precision array dimensioned to n (see setStorageSize
above) that will contain the stored variables that are being retrieved from storage.
m: the integer number of variables that are to be stored. This argument allows the user to
store only a subset of an array that is used in the Type.
INFO: the standard INFO array is sent so that the storage data structures know what unit
and type number are requesting storage.
STORAGE EXAMPLE
A tank model which uses global storage to store the initial tank temperature might contain the
following lines:
...
C PERFORM FIRST CALL MANIPULATIONS
IF (INFO(7).EQ.-1) THEN
...
!reserve space in the double precision storage structure
StorageSize = 1
CALL setStorageSize(StorageSize,INFO)
...
!return to the calling program
RETURN 1
ENDIF
C PERFORM INITIAL TIME STEP MANIPULATIONS
IF (TIME.LT.(TIME0+DELT/2.)) THEN
...
!set initial values of variables in the double precision storage structure
Stored(1) = T
CALL setStorageVars(Stored, StorageSize,INFO)
...
!return to the calling program
RETURN 1
890
ENDIF
...
CALL getStorageVars(Stored,StorageSize,INFO)
TZERO = Stored(1)
...
The above example is exceedingly simplistic. The result of it is that no matter what is done to the
local variable TZERO later in the Type, it will always be reset to the initial value of T each time the
Type is called anew. A much more common situation arises when not only do we wish to use an
initial value in calculations but at the end of the time step, we wish to set the final calculated value
as the initial value for the next time step. In TRNSYS version 15.x and before, there was no way
for a Type to know when it was being called for the last time in a given time step. With the release
of TRNSYS version 16, a post convergence call to all Types was added, simplifying this
process. In the following modification to the above example, TZERO is set to an initial value.
TFINAL is calculated based on TZERO. At the end of each time step, the converged value of
TFINAL is set as the value of TZERO for the next time step.
...
C PERFORM POST CONVERGENCE MANIPULATIONS
IF (INFO(13).GT. 1) THEN
CALL getStorageVars(Stored,StorageSize,INFO) !recall the storage values
Stored(1)=Stored(2)
!update the TZERO spot with the value stored
!in the TFINAL spot.
CALL setStorageVars(Stored,StorageSize,INFO) !set the new storage values
ENDIF
C PERFORM FIRST CALL MANIPULATIONS
IF (INFO(7).EQ.-1) THEN
...
!reserve space in the double precision storage structure
StorageSize = 2
CALL setStorageSize(StorageSize,INFO)
...
!return to the calling program
RETURN 1
ENDIF
C PERFORM INITIAL TIME STEP MANIPULATIONS
IF (TIME.LT.(TIME0+DELT/2.)) THEN
...
!set initial values of variables in the double precision storage structure
Stored(1) = T
Stored(2) = T
CALL setStorageVars(Stored, StorageSize,INFO)
...
!return to the calling program
RETURN 1
ENDIF
...
!retrieve the stored value of the initial temperature for this time step.
CALL getStorageVars(Stored,StorageSize,INFO)
TZERO = Stored(1)
...
!calculate TFINAL based on the initial temperature.
TFINAL = TZERO + ...
...
!update the second storage spot with the calculated value of TFINAL
Stored(2) = TFINAL
CALL setStorageVars(Stored,StorageSize,INFO)
...
891
where
ITYPE
NTABLE
NBS
NCS
NDS
Subroutine Table_Coefs reads the transfer function coefficient from the file ASHRAE.COF
accessed through FORTRAN logical unit 8. This logical unit can be changed by modifying a data
statement within the subroutine. After the coefficients have been read for a particular wall, the
coefficients are stored internally within the subroutine for use on subsequent calls to
Table_Coefs.
892
Note: Transfer function coefficients in the file ASHRAE.COF are different from
those actually found in the ASHRAE handbooks. Because the TYPE 19 singlezone model handles the inside radiative heat transfer separately, the inside
radiative resistance is not included in the ASHRAE.COF transfer coefficients.
Thus while the file ASHRAE.COF is well-suited for use with TYPE 19 and other
models which calculate radiative heat transfer separately, it must not be
assumed that this file matches the ASHRAE handbook values.
893
THETA
XKL
REFRIN
ALPHA
RHOD
If the value of RHOD is not known, then TALF can calculate it: When the sixth argument in the
function reference is less than zero, the reflectance of the N covers to diffuse radiation is
determined. The variable used as the sixth argument in the call to TALF is then set to this value
so that on subsequent calls to TALF the value of RHOD may be supplied.
Due to FORTRAN considerations, functions can not be checked for unlinked subroutines. Use
the LINKCK subroutine to warn the user that this function must be linked to the TRNSYS
executable.
MATHEMATICAL DESCRIPTION
The function subprogram Tau_Alpha calculates the transmittance-absorptance product () of a
solar collector for a given angle of incident radiation. The collector is described by the number of
glazings, N, each with refractive index ng and extinction length kL, and the absorptance of the
collector plate . The model uses Fresnel's equation for the specular reflectance at a planar
interface (assuming unpolarized incident radiation) and accounts for multiple reflections. The
transmittance for diffuse radiation is approximated as the transmittance for specular radiation at
an incident angle of 60. Fresnel's equations for reflectance at a planar interface for
perpendicular and parallel polarized radiation are the following:
894
perpendicular
1 =
sin 2 (1 2 )
sin 2 (1 + 2 )
parallel
2 =
Eq. 8.4.4-14
tan 2 (1 2 )
tan 2 (1 + 2 )
Eq. 8.4.4-15
The angles 1 and 2 are related by Snell's Law with the index of refraction for air of unity.
sin 2 =
sin 1
ng
Eq. 8.4.4-16
The transmittance and reflectance of a single glazing for each component of polarization,
including absorption and multiple reflections within the glazings, can be derived to give the
following [1,2]:
Ti ,1 =
a (1 i ) 2
2
2
1 a i
a 2 (1 i ) 2
Ri ,1 = i 1 +
2
2
1 a i
Eq. 8.4.4-17
Eq. 8.4.4-18
The internal transmittance, a, is a function of the extinction length and the transmission angle.
kL
cos 2
a = exp
Eq. 8.4.4-19
The transmittance and reflectance of N parallel plates, of the same material and thickness, can
be determined by the following recursive formulae.
Ti ,1Ti , N 1
Ti , N =
Ri , N
1 Ri ,1Ri , N 1
Ri ,1Ti , N
= Ri , N 1 +
1 Ri ,1Ri , N 1
Eq. 8.4.4-20
Eq. 8.4.4-21
The transmittance-absorptance product of the collector plate and glazing assembly can then be
calculated as
( ) =
(T
1, N
+ T2, N )
2(1 (1 ) RD )
Eq. 8.4.4-22
RD is calculated as the
895
8.4.4.19. TYPECK
The purpose of TYPECK is to perform some simple checks on the TRNSYS input file to ensure
the proper number of INPUTS, PARAMETERS, and DERIVATIVES have been specified for the
given component, and to terminate the simulation after compilation of the component input file
with appropriate error messages if errors are found. The form of a TYPECK call is:
INTEGER :: IOPT,INFO(15),NI,NP,ND
...
CALL TYPECK(IOPT,INFO,NI,NP,ND)
where
IOPT-
896
>0
1 or -1
2 or -2
3 or -3
4 or -4
5 or -5
INFO-
NI-
NP-
ND-
The integer variable ITYPE defines the type of orientation between the two surfaces. There are
five possibilities. The arguments A, B, C, D, E, F, G, H, X3, Y3, and Z3 (all double precision) are
dimensions or coordinates that depend upon the orientation chosen. Not all of these variables
are used for each orientation. The possible orientations and required dimensions are shown in
Figures 8.6.7.16-1 to 8.6.7.16-5. The VIEW factor from surface 2 to 1 is determined by the
routine. The integer arguments NA1 and NA2 are the number of differential areas for each
surface, when numerical integration is used to determine VIEW factors. NA1 is only used for
ITYPE equal to 3, 4, or 5. NA2 is only for ITYPE equal to 5.
2
1
B
C
Figure 8.4.4.20-1:ITYPE=1; parallel identical rectangles.
A
1
B
2
C
Figure 8.4.4.20-2: ITYPE=2; perpendicular rectangles with a common edge.
G
1
2
A
C
Figure 8.4.4.20-3: ITYPE=3; nonidentical parallel rectangles.
897
A
2
B
F
1
C
Figure 8.4.4.20-4: ITYPE=4; perpendicular rectangles without a common edge.
Z
Y
2
(0, 0, 0)
B
X
Figure 8.4.4.20-5: ITYPE=5; two rectangular surfaces of any orientation (X1=C, Y1=D, Z1=E, X2=F,
Y2=G, Z2=H from subroutine call statement).
MATHEMATICAL DESCRIPTION:
ITYPE = 1
The view factor from surface two to one of Figure 8.4.4.20-1 is determined with the following
expression taken from Reference 1.
2 (1 + X 2 )(1 + Y 2 )
F21 =
ln
XY 1 + X 2 + Y 2
1/ 2
+ 1 + Y 2 tan 1
X
1+ Y 2
Eq. 8.4.4-23
+ Y 1 + X 2 tan 1
Y
1+ X2
X tan 1 X Y tan 1 Y
where,
X = A/C
and
Y = B/C
ITYPE = 2
898
From Reference 1, the view factor from surface two to one of Figure 8.4.4.20-2 is
F21 =
1
1
1
Y tan 1 + X tan 1
Y
X
Y
)(
1 1+ Y 2 1+ X 2
+ ln
4 1+ X 2 + Y 2
) Y (1 + X
(1 + Y )(X
X2 +Y2
) X (1 + X
) (1 + X )(X
Y2
+Y 2
2
+Y 2
X 2 + Y 2 tan 1
2
)
)
+Y 2
2
+Y 2
X2
Eq. 8.4.4-24
where,
X = B/A
and
Y = C/A
ITYPE = 3
The VIEW factor from surface two to one of Figure 8.6.7.16-3 is found by numerical integration
using the following expression:
d 1 2
F21 =
dA1
Eq. 8.4.4-25
A1
A2
where Fd1-2 is the view factor from an elemental area dA1 on surface 1 to surface 2 and A1 and
A2 are the areas of surfaces 1 and 2, respectively. The number of differential areas used in the
integration, NA1, is specified as an argument in the call to VIEW.
The view factor Fd1-2 is determined by breaking surface 2 into 4 sections such that the normal to
the center of the element passes through a common corner of each section of surface 2.
From Reference 1,
4
Fd 1 2 =
i =1
Xi
Yi
Yi
Xi
1
tan 1
tan 1
+
2
2
2
2 1 + X 2
1 + Xi
1 + Yi
1 + Yi
i
Eq. 8.4.4-26
where
Xi =
Ai
B
and Yi = i
C
C
and Ai and Bi are dimensions of each section on surface 2, measured in the same directions as A
and B.
899
ITYPE = 4
The view factor from surface 2 to 1 of Figure 8.4.4.20-4 is also determined using Equation
8.6.7.16-3 The view factor Fd1-2 is found by breaking surface 4 into 2 sections such that the
normal to a common corner of the sections splits the element in half. From Reference 1,
2
Fd 1 2 =
i =1
1 1 1
tan
Yi
2
Yi
2
X i + Yi
tan 1
2
2
X i + Yi
1
Eq. 8.4.4-27
where
Xi =
A
C'
and Yi =
Bi
Bi
Bi is the dimension of each section measured in the direction of B. C' is the distance from the
edge of surface 2 to the center of the element on surface one.
ITYPE = 5
For two rectangular surfaces of arbitrary orientation as shown in Figure 8.4.4.20-5, the view factor
from 2 to 1 is:
F21 =
1
A2
cos 1 cos 2
dA2 dA1
S 2
A1 A2
Eq. 8.4.4-28
where S is the distance between the centers of elemental areas on each surface, 1 and 2 are
angles between the normals to each element and the line connecting their centers, and A1 and
A2 are the areas of surfaces 1 and 2. Equation (8.6.7.16-6) is solved by numerical integration.
The number of elemental areas used in the integration procedure, NA1 and NA2, are specified in
the argument list in the call to VIEW.
The distance S is
S=
( X d 2 X d 1 )2 + (Yd 1 Yd 2 )2 + (Z d 2 Z d 1 )2
Eq. 8.4.4-29
where (Xd1,Yd1,Zd1) and (Xd2,Yd2,Zd2) are the coordinates of the elemental areas on surfaces
1 and 2, respectively. For Surface 2,
cos 2 =
For Surface 1,
8100
Z d1 Z d 2
S
Eq. 8.4.4-30
v v
SN
cos 1 =
N S
Eq. 8.4.4-31
v
S is the vector originating at the center of the elemental area on surface 1 and ending at
v
the center of the second element on surface 2 and N is a normal vector to the elemental area on
where
surface 1.
In general,
v v
v
v
v
v
S = sxi + s y j + sz k
v
v
v
v
N = nx i + n y j + nz k
Eq. 8.4.4-32
Eq. 8.4.4-33
where i , j , and k are unit vectors in the x, y, and z directions, respectively. Substitution of
Equations (8.6.7.16-10) and (8.6.7.16-11) into Equation (8.6.7.16-9) gives
cos =
S x nx + S y n y + S z nz
2
Sx + S y + Sz
nx + n y + nz
Eq. 8.4.4-34
where,
Sx = Xd2 - Xd1
Sy = Yd2 - Yd1
Sz = Zd2 - Zd1
Eq. 8.4.4-35
Eq. 8.4.4-36
Eq. 8.4.4-37
nx =
K n yY 1 Z1
X1
X2 X2
K 1
Z1 Z 2
+
X1 X1
ny =
X2
Y1
Y2
X1
Eq. 8.4.4-38
Eq. 8.4.4-39
where,
X3
Z1 Z 3 Y 2
X
1
K=
X
2
1
Y 3
X 1
X2 X2
X3
Y 1
Z1 Z 2 Y 3
Y 1
X1 X1
X1
X 3 X 3
X2
Y 1 1
Y 1
Y 2
X1
X 1
X1
Eq. 8.4.4-40
8101
The coordinates X1, X2, X3, Y1, Y2, Y3, Z1, Z2, Z3 are as defined in Figure 8.4.4.20-5.
8102
8.4.5.
TRNSYS versions 11.1 and higher provide two methods for solving differential equations which
may occur in component models: an approximate analytical solution using the subroutine
Differential_Eqn (see Section 8.4.4.3), and a numerical solution using one of three numerical
methods (see Manual 07-TRNEdit). The analytical method is recommended whenever practical it
is possible to write the differential equation in the following general form:
dT
= aT + b
dt
Eq. 8.4.5-1
The numerical method generally requires shorter time steps and more computation for
comparable accuracy and numerical stability. Users intending to utilize the Powells method
TRNSYS solver (SOLVER 1) should use the Differential_Eqn subroutine whenever possible.
Numerical solutions to differential equations, when required can be obtained through the DTDT
and T arrays in the subroutine calling sequence. To use a very simple example, if the equation
dT
Q& i = C 1
dt
Eq. 8.4.5-2
were part of the mathematical model and the DERIVATIVE of the temperature T1 with respect to
DTDT(1) is the differential dT1/dt, and T(1) is the result of integrating DTDT(1). In this example
T1 is also desired to be the second OUTPUT of the sequentially ordered OUTPUT list. Note that
the subscripts of OUT and T do not have to be the same, but that T(n) will always be the result of
integrating DTDT(n).
A DERIVATIVES control statement followed by an initial values line must be included among the
component control statements for any model which uses the DTDT array. The presence of a
DERIVATIVES command signals TRNSYS to integrate derivatives placed in the DTDT array and
to return results in the T array, repeating the procedure at each timestep until either the
appropriate error TOLERANCE or the iteration LIMIT is reached. The initial values of the
dependent variables (i.e., T(n)) are available to the component subroutine, if needed, through the
T array at the first call of the simulation (i.e., when INF0(7) = - 1; see Section 8.4.3).
8103
8.4.6.
TRNSYS checks to make sure that all routines required by the TRNSYS input file are included in
the TRNSYS executable file by utilizing the FORTRAN alternate return. In previous TRNSYS
versions run with compilers allowing unresolved externals, unlinked subroutines were not
checked and were often the source of strange errors. The TRNSYS routines and all user-written
routines that call other subroutines should include an alternate return. The following example
should help the user understand the workings of the alternate return.
C* CALLING PROGRAM **
CALL TYPE2(TIME,XIN,OUT,T,DTDT,PAR,INFO,ICNTRL,*101)
100
WRITE(*,*) ERROR - TYPE 2 IS NOT LINKED !
CALL MYSTOP(1001)
RETURN 1
101
CONTINUE
.
.
C* CALLED SUBROUTINE **
SUBROUTINE TYPE2(TIME,XIN,OUT,T,DTDT,PAR,INFO,ICNTRL,*)
.
RETURN 1
The calling program will call the TYPE 2 subroutine and return to line 101 when the subroutine
calculations are completed due to the RETURN 1 line in the TYPE 2 subroutine. If the RETURN
1 is missing from the TYPE 2 subroutine or the subroutine is not linked, the program will return to
line 100 of the calling program and the error message will be flagged.
All user written routines should contain an asterisk (*) at the end of the subroutine designation
and RETURN 1s every place a RETURN is desired. Failure to do so will cause the unlinked
subroutine error message to be displayed and the program to terminate.
All user-written routines that call other subprograms should also include the alternate return
feature to check for unlinked subprograms. To activate the alternate return:
1)
Call the subprogram with an asterisk-line number combination at the end of the
subprogram designation.
2)
Specify the line number given in the step above as a CONTINUE line.
3)
Between the subprogram call and the CONTINUE statement, place an error
message and a:
CALL MESSAGES(-1,Error Message Text,fatal,INFO(1),INFO(2))
command - a call may instead be placed to the LINKCK subroutine (see Section
8.4.4.7).
4)
8104
Make sure all RETURNs in the subprogram are replaced with a RETURN 1
statement. Refer to the example given or a FORTRAN manual for more details.
8.4.7.
The ICNTRL array, which was new to version 14, conveys to the component subroutines (TYPE1,
TYPE2, etc.) and to the TRNSYS equation processor, the states of the controller variables. With
the release of TRNSYS 14, a new control strategy was designed to eliminate the problems
caused by previous TRNSYS controllers sticking in order to solve the system of equations (see
Manual 07-TRNEdit). With TRNSYS 14, the TRNSYS executive program, rather than the
component models, directly controlled discrete variables. At the start of each time step, the
values of all discrete variables are known. TRNSYS 14 (and subsequent versions) force these
values to remain at their current state until a converged solution to the equations is obtained or an
iteration limit is encountered. During these calculations, the component models calculate the
desired value of the discrete variables but they do not actually change the settings. After a
converged solution is obtained, or the maximum number of iterations is exceeded, TRNSYS
compares the current discrete variable values with the desired values. If they do not differ and a
converged solution has been obtained, the calculations are completed for the time step.
Otherwise, TRNSYS changes the values of the discrete variables to the desired setting and
repeats this process, taking care to not repeat the calculations with the same set of discrete
variables used previously.
To incorporate the new control strategy into user-written component routines, the ICNTRL and
INFO arrays must be set up correctly. INFO(11) should specify the number of discrete control
variables in the component routine. ICNTRL(2*(i-1)+1) and ICNTRL(2i) will contain the control
state at the previous iteration for controller i in the component model. (controlled by the TRNSYS
processor) and the desired control state at this iteration respectively.
The ICNTRL array is an integer array and must therefore pass and receive only integer values.
The assumption in TRNSYS is that an ICNTRL value of 1 implies the control signal was enabled
while an ICNTRL value of 0 denotes a disabled control signal.
For example, a user wishes to describe an on/off controller with hysteresis effects (control signal
depends on previous control signal). The component formulation would be of the following format:
UDB=PAR(1)
! UPPER DEAD BAND TEMP. DIFFERENCE
LDB=PAR(1)
! LOWER DEAD BAND TEMP. DIFFERENCE
.
INFO(11)=1
! 1 CONTROL VARIABLE)
.
.
TH=XIN(1)
! UPPER INPUT TEMPERATURE
TL=XIN(2)
! LOWER INPUT TEMPERATURE
.
.
STATEOLD=ICNTRL(1) ! CONTROL STATE AT PREVIOUS SOLUTION
STATENEW=STATEOLD
IF(STATEOLD.EQ.1) THEN
IF((TH-TL).LT.LDB) STATENEW=0
ELSE
IF(TH-TL).GT.UDB)) STATENEW=1
ENDIF
ICNTRL(2)=STATENEW
.
At every iteration, the value of ICNTRL(1) holds the controller state at the previous solution while
ICNTRL(2) holds the desired controller state at this iteration. The TRNSYS processor will check
to see if ICNTRL(1) is equal to ICNTRL(2) at convergence. If the values are not equal at
8105
convergence, ICNTRL(1) will be set to the desired controller state at convergence (ICNTRL(2))
and the process will be repeated.
IMPORTANT!! If a new component makes use of the ICNTRL array, then SOLVER 1 must be
used in any TRNSYS input file that contains that component.
8106
8.4.8.
As programming standards have evolved, so too have the conventions required by TRNSYS
Types. The following sections provide the user with information on the steps required to convert
Types written for earlier versions of TRNSYS to later versions.
8.4.8.1.
TRNSYS routines written for version 13.1 or earlier have to be modified for use with TRNSYS
version 14.1 and higher. The steps are summarized below for convenience - refer to the sections
listed for full details.
1) Change the TYPE specification from:
CALL TYPEn(TIME,XIN,OUT,T,DTDT,PAR,INFO)
to:
CALL TYPEn(TIME,XIN,OUT,T,DTDT,PAR,INFO,ICNTRL,*)
8.4.8.2.
TRNSYS routines written for version 14.1 have to be modified for use with TRNSYS 14.2 for
Windows. The Windows operating system does not deal well with two common features of
TRNSYS version 14.1 subroutines. The steps are summarized below for convenience.
1)
STOP
8107
CALL MYSTOP(1001)
RETURN 1
need to be replaced with a statement that writes the text to the listing file.
WRITE(LUW,*) There is an error in this type
Note: In most cases, writing to the list file requires the inclusion of the common block that
contains the value for the logical unit. Include the following line:
COMMON /LUNITS/ LUR, LUW, IFORM, LUK
8.4.8.3.
There are no modifications necessary to a TRNSYS 14.2 Type in order for it to be used with
TRNSYS version 15.x.
8.4.8.4.
The steps involved with converting TRNSYS components written for TRNSYS version 15.x to the
TRNSYS 16.x coding standard are included in section 8.2.1.3 of this manual.
8108
8.4.9.
The following sections give detailed information on the compiler settings used to rebuild
TRNDll.dll. They are for reference only. To use the default workspace, launch CVF 6.6, go to
"File/Open workspace" and select %TRNSYS16%\Compilers\Cvf66\Cvf66.dsw. You do not have
to modify any setting to recompile and debug TRNSYS if you use the project included in the
distribution. The instructions hereunder are for reference only. They explain how this workspace
was created and give all modifications to default settings. You will also need to use the
instructions here below if you want to use the open-source version of Type 56 (see section
8.4.9.4).
Supported Compiler version: 6.6b (Note: there has been a 6.6c update but it appears to be
unstable and it introduces some "features" that are incompatible with many existing programs. It
was pulled back by HP-Compaq, then posted again. We advise against using it)
8.4.9.1.
Cvf66 Workspace
In CVF, a Project is a set of files and settings that are used to build an application (.exe or .dll). A
Workspace is a container for one or more projects. We will first create an empty Workspace:
Go to File/New, select the "Workspace" Tab
Select "Blank Workspace"
Place in %TRNSYS16%\Compilers
Workspace name: Cvf66
8.4.9.2.
TRNDll project
The TRNSYS kernel and the standard components are compiled and linked into one DLL,
TRNDll.dll. To create the project:
Go to File/New, select the "Project" Tab
Project type: select "Win32 Dynamic Link Library"
Select "Add to current workspace"
Project name: TRNDll
The folder name should read %TRNSYS16%\Compilers\Cvf66\TRNDll
Click OK
Select "Empty DLL"
Click Finish, then OK
8.4.9.3.
Project settings
Go to Projects/Settings
In the left-hand window, select the "TRNDll" project
In the "Settings for" drop-down list box showing "Win32 Debug", select "All configurations".
We will now choose the settings that are common to the Debug and Release configurations.
8109
There are numerous settings here controlled by a series of tabs at the top. Below are the
important settings for each of these tabs. Each tab can have several "Categories" controlled by a
drop-down list, so there are many settings involved. Only the settings that must be changed from
their default values are mentioned.
Table 8.4.9.3-1: TRNDll Settings CVF 6.6, All Configurations
Tab
Debug
Drop-down
Value
..\..\..\Exe\TRNExe.exe
Program arguments
General
General
Compatibility
Fortran
Parameter
External
Procedures
Floating
Point
Runtime
Generate Source
Browse Information
Predefined
Preprocessor Symbols
Powerstation 4.0
compatibility options
Arguments Passing
Convention
String Length Argument
Passing
Floating point exception
handling
Extend precision of
Single precision
constants
Generate traceback
information
Runtime Error checking
Checked
TRNSYS_MULTI_DLL, TRNSYS_WIN32
Check "Libraries" and "Other Run-time Behavior"
C, by Reference
After All Args
0
Checked
Checked
Check all boxes
In the "Settings for" drop-down list box, select "Win32 Debug". We will now choose the settings
that only apply to the Debug configuration. Here again, only the settings that must be changed
from their default values are mentioned.
Table 8.4.9.3-2: TRNDll Settings CVF 6.6, Win32 Debug
Tab
Drop-down
Parameter
Value
Link
Input
Ignore Libraries
libcd.lib, msvcrtd.lib
Post-build description
Post-build command(s)
Postbuild
step
In the "Settings for" drop-down list box, select "Win32 Release". We will now choose the settings
that only apply to the Release configuration. Here again, only the settings that must be changed
from their default values are mentioned.
Table 8.4.9.3-3: TRNDll Settings CVF 6.6, Win32 Release
Tab
Drop-down
Parameter
Value
Link
Input
Ignore Libraries
libcd.lib, msvcrtd.lib
Post-build description
Post-
8110
build
step
Post-build command(s)
Notes:
The ignored libraries must change depending on the libraries used in the precompiled files.
Currently Type56 is distributed in Release mode, i.e. linked against the release version of
the standard libraries. Consequently the "debug" version must be ignored (libcd.lib and
msvcrtd.lib). If a Debug version of Type56 was linked to the DLL, the "non-debug" version of
default libraries should be ignored (libc.lib and msvcrt.lib).
The post-build step makes sure the required files are copied to the Exe folder without adding
unnecessary compiler files to that folder and making sure a copy of those files stays in the
Debug or Release directory
8.4.9.4.
Project files
On the left-hand window, go to "TRNDll files". You can delete the "Resource Files" and "Header
Files" folders, which will not be used. Go to the "Source file" folder. Right-click on it and choose
"New folder". Create the "Kernel" folder. Right click on this folder and choose "Add files to folder".
Browse to %TRNSYS16%\SourceCode\Kernel and select all .for and .f90 files. Click OK to add
the files to the project.
Go back to the "Source file" folder. Right-click on it and choose "New folder". Create the "Types"
folder. Right click on this folder and choose "Add files to folder". Browse to
%TRNSYS16%\SourceCode\Types and select all .for and .f90 files (if any). Click OK to add the
files to the project.
8.4.9.5.
Make sure the right project (TRNDll) is active in Project/Set active project, in case you have
several projects.
8111
Note: You need to do a Rebuild all before compiling any file that uses TRNSYS data modules. If
you try to compile a routine using the data modules before performing a "Rebuild" you will get an
message saying "error in opening module file" and the compilation will fail. The "Rebuild"
operation compiles the modules and creates the module files (.mod) before compiling the files
that require them.
8.4.9.6.
Debugging TRNSYS
Debugging TRNSYS is easy using the Visual Studio: Just press F5 to start TRNSYS. If you left
"Project Settings/Debug/General/Program Arguments" empty, an "open file" dialog box will show
up and you can select the deck file from there.
Before starting the debugger, you can set/remove breakpoints anywhere in the code using the
F12 key. You can then step through the code one instruction at a time using the F10 key (F11 to
enter called subroutines or functions).
Hint: To force the compiler to stop when an error such as an "out of bounds"
array occurs, you have to set it to stop on exceptions. To do this, launch the
debugger (F5). While it is stopped in the File/open dialog box, come back to the
debugger and go to Debug/Exceptions. Select all exceptions in the lower text
field, select "Stop always" for the action and click on "change". CVF has a bug in
the display but if you then click OK and come back at the same place you will see
that your changes have been made. From now on, CVF will stop when such
exceptions are generated and it will indicate the line that caused the problem.
8.4.9.7.
8112
HOW TO "FIX" A PROJECT THAT CRASHES WHEN YOU TRY DEBUGGING TRNSYS
Occasionally, some project files get corrupt and CVF crashes as soon as you try to debug
TRNSYS. This is a known compiler issue. The following fix has been found to work in most
cases:
Delete ALL files in the %TRNSYS16%\Compilers\Cvf66 directory except for Cvf66.dsw and
the subdirectories (only delete FILES, e.g. Cvf66.opt)
Delete ALL files in the %TRNSYS16%\Compilers\Cvf66\TRNDll directory except for
TRNDll.dsp and the subdirectories (only delete FILES, e.g. TRNDll.plg)
Delete
EVERYTHING
in
%TRNSYS16%\Compilers\Cvf66\TRNDll\Debug
%TRNSYS16%\Compilers\Cvf66\TRNDll\Release
and
Then reopen Cvf66.dsw. Some settings like breakpoints will be lost but the important project
settings are still there. The choice of debugging EXE is lost and you must re-enter
..\..\..\Exe\TRNExe.exe in Project settings / Debug / General / Executable for debug session.
If you are still unable to debug TRNSYS, please reinstall a fresh copy of the project from your
original installation media or recreate the workspace after deleting all existing files, according to
the instructions here above, after deleting all existing files in %TRNSYS16%\Compilers\Cvf66.
8113
8114
Tab
Drop-down
General
Debug
Parameter
Value
Output files
..\..\..\Userlib
..\..\..\Exe\TRNExe.exe
Program arguments
General
General
Compatibility
External
Procedures
Fortran
Floating
Point
Runtime
Generate Source
Browse Information
Powerstation 4.0
compatibility options
Arguments Passing
Convention
String Length Argument
Passing
Floating point exception
handling
Extend precision of
Single precision
constants
Generate traceback
information
Runtime Error checking
Checked
Check "Libraries" and "Other Run-time Behavior"
C, by Reference
After All Args
0
Checked
Checked
Check all boxes
In the "Settings for" drop-down list box, select "Win32 Debug". We will now choose the settings
that only apply to the Debug configuration. Here again, only the settings that must be changed
from their default values are mentioned.
Table 8.4.10.3-2: New DLL Settings CVF 6.6, Win32 Debug
Tab
Drop-down
Parameter
Value
Fortran
Preprocessor
..\TrnDll\Debug
Link
Input
Ignore Libraries
In the "Settings for" drop-down list box, select "Win32 Release". We will now choose the settings
that only apply to the Release configuration. Here again, only the settings that must be changed
from their default values are mentioned.
Table 8.4.10.3-3: New DLL Settings CVF 6.6, Win32 Release
Tab
Drop-down
Parameter
Value
Fortran
Preprocessor
..\TrnDll\Release
Link
Input
Ignore Libraries
Notes:
The ignored libraries must be adapted to the precompiled object files or libraries that you link
to the DLL. The linker will tell you which libraries cause conflicts. The most frequent ones are
libc.lib and msvcrt.lib, as well as their debug versions, libcd.lib and msvcrtd.lib.
8115
Go to the "Source file" folder. Right click on this folder and choose "Add files to folder". Browse to
your source files (Types and possibly the utility routines they require) and add them.
Add the "TRNDll.lib" file that you will find in %TRNSYS16%\Exe to the project (e.g. in a
"Libraries" folder that you create). This will allow your DLL to use all the symbols exported by
TRNSYS.
8116
will
create
the
file
%TRNSYS16%\Compilers\Ivf81-Mvs2003\Ivf81-
8117
Click OK.
This will launch the "Fortran Dynamic Link Library Wizard".
Select "DLL Settings" under "Overview", in the left frame, and choose "Empty Project" as
the DLL Type.
Click "Finish".
This
will
create
the
following
Project
file
with
%TRNSYS16%\Compilers\Ivf81-Mvs2003\TRNDll\TRNDll.vfproj
default
settings:
Branch
Category
Parameter
Value
General
Data
Floating
Point
TRNSYS_MULTI_DLL; TRNSYS_WIN32
All variables SAVE
Fortran
Run-time
Yes
Yes
Yes
Yes
Yes
In the "configuration" drop-down list box, select "Debug". We will now choose the settings that
only apply to the Debug configuration. Here again, only the settings that must be changed from
their default values are mentioned.
Table 8.4.11.3-2: TRNDll Settings IVF 8.1, Win32 Debug
Branch
Category
Debugging
Parameter
Value
Command
..\..\..\Exe\TRNExe.exe
You can optionally enter the name of the deck file
that you wish to debug here, to bypass the file/open
dialog in TRNExe.exe
Command arguments
Fortran
Libraries
Build
events
Post-build
Event
Runtime library
Command Line
Description
In the "configuration" drop-down list box, select "Release". We will now choose the settings that
only apply to the Release configuration. Here again, only the settings that must be changed from
their default values are mentioned.
8118
Branch
Category
Parameter
Value
Fortran
Libraries
Runtime library
Single-threaded DLL
Build
events
Post-build
Event
Command Line
Description
Notes:
The post-build step makes sure the required files are copied to the Exe folder without adding
unnecessary compiler files to that folder and making sure a copy of those files stays in the
Debug or Release directory
8119
8120
8.5. References
Engineering Equation Solver, F-Chart Software, 4406 Fox Bluff Road, Middleton WI, 1994.
www.fchart.com
ASHRAE. 2001. Handbook of Fundamentals. American Society of Heating Refrigeration, and Air
Conditioning Engineers, Atlanta, Ga.
8121