Sie sind auf Seite 1von 187

TRNSYS 17

a TRaNsient SYstem Simulation program

Volume 7

Programmer's Guide

Solar Energy Laboratory, Univ. of Wisconsin-Madison


http://sel.me.wisc.edu/trnsys

TRANSSOLAR Energietechnik GmbH


http://www.trnsys.de

CSTB Centre Scientifique et Technique du Btiment


http://software.cstb.fr

TESS Thermal Energy Systems Specialists


http://www.tess-inc.com
TRNSYS 17 Programmer's Guide

About This Manual


The information presented in this manual is intended to provide a reference to users who want to
create their own TRNSYS 17 components or want to understand the TRNSYS 17 simulation
engine. This manual is not intended to provide information about other utility programs in
TRNSYS 17. More information concerning these programs can be found in other parts of the
TRNSYS documentation set. The latest version of this manual is always available for registered
users on the TRNSYS website (see here below).

Revision history
2004-09 For TRNSYS 16.00.0000
2005-02 For TRNSYS 16.00.0037
2006-01 For TRNSYS 16.01.0000
2007-02 For TRNSYS 16.01.0003
2010-04 For TRNSYS 17.00.0013
2012-03 For TRNSYS 17.01.0000
2014-05 For TRNSYS 17.01.0002

Where to find more information


Further information about the program and its availability can be obtained from the TRNSYS
website or from the TRNSYS coordinator at the Solar Energy Lab:

TRNSYS Coordinator Email: TechSupport@tess-inc.com


Thermal Energy System Specialists, LLC Phone: +1 (608) 274 2577
22 North Carroll Street suite 370 Fax: +1 (608) 278 1475
Madison, WI 53703 U.S.A.

TRNSYS website: http://sel.me.wisc.edu/trnsys

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.

2014 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.

72
TRNSYS 17 Programmer's Guide

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

D.A. Arias M.J. Duffy

Additional contributors who developed components that have been included in the Standard
Library are listed in the Volume 04 Mathematical Reference manual.

Contributors to the building model (Type 56) and its interface (TRNBuild) are listed in the Volume
05 Multizone Building manual.

73
TRNSYS 17 Programmer's Guide

Contributors to the TRNSYS Simulation Studio are listed in the Volume 02 Simulation Studio
manual.

74
TRNSYS 17 Programmer's Guide

Table of contents
7. PROGRAMMER'S GUIDE 712
7.1. Introduction and Overview 712
7.2. Updating TRNSYS 16 Components to the TRNSYS 17 Coding Standard 713
7.2.1. The Subroutine Call 713
7.2.2. Set Global Simulation Variables 714
7.2.3. Identify the Types Coding Standard (version signing) 714
7.2.4. Perform Last Call Manipulations 714
7.2.5. Perform End of Time Step Manipulations 715
7.2.6. Perform First Call Manipulations 715
7.2.7. Perform Start Time Manipulations 718
7.2.8. Rereading Parameters 719
7.2.9. Retrieving Input Values 720
7.2.10.Other Considerations 720
7.3. How to Create New Components 721
7.3.1. Fundamentals 721
7.3.2. The First Line 723
7.3.3. DLL Export 724
7.3.4. USE Statements 724
7.3.5. Variable Declarations 725
7.3.6. Data Statements 726
7.3.7. Global Constants and Variables 726
7.3.8. Version Signing 726
7.3.9. Last Call Manipulations 727
7.3.10.End of Time Step Manipulations 728
7.3.10.1. Resetting Counters 728
7.3.10.2. Updating Storage Variables 728
7.3.11.Initialization Call Manipulations 729
7.3.12.Start Time Manipulations 731
7.3.13.Multiple Unit Manipulations 733
7.3.14.Every Time Step Manipulations 733
7.3.14.1. Retrieve Stored Values 734
7.3.14.2. Retrieve Input Values 734
7.3.14.3. Perform Calculations 734
7.3.14.4. Set Storage Values 735
7.3.14.5. Set Outputs 735
7.3.14.6. Return Control 735

75
TRNSYS 17 Programmer's Guide

7.3.15.Complete Code 737


7.3.16.Implementing Data Storage between Time Steps 740
7.3.17.Including your new component in an external DLL 740
7.4. Reference 741
7.4.1. Global constants 741
7.4.1.1. Constants settings limits on TRNSYS simulations 741
7.4.1.2. Constants used for string length 742
7.4.2. Access functions 743
7.4.2.1. function getMaxDescripLength( ) 743
7.4.2.2. function getmaxFileWidth( ) 743
7.4.2.3. function getMaxLabelLength( ) 743
7.4.2.4. function getMaxPathLength( ) 744
7.4.2.5. function getnMaxStorageSpots( ) 744
7.4.2.6. function CheckStability( ) 744
7.4.2.7. function ErrorFound( ) 745
7.4.2.8. function getConvergenceTolerance( ) 745
7.4.2.9. function getDeckFileName( ) 745
7.4.2.10. function getFormat(i,j ) 745
7.4.2.11. function getLabel(i,j) 746
7.4.2.12. function getListingFileLogicalUnit( ) 746
7.4.2.13. function getLUfileName (i) 746
7.4.2.14. function getMinimumTimestep( ) 747
7.4.2.15. function getNextAvailableLogicalUnit( ) 747
7.4.2.16. function getnMaxIterations( ) 747
7.4.2.17. function getnMaxWarnings( ) 747
7.4.2.18. function getnTimeSteps( ) 747
7.4.2.19. function getNumberOfErrors( ) 748
7.4.2.20. function getNumberOfWarnings( ) 748
7.4.2.21. function getNumericalSolver( ) 748
7.4.2.22. function getSimulationTime() 749
7.4.2.23. function getSimulationStartTime( ) 749
7.4.2.24. function getSimulationStartTimeV15( ) 749
7.4.2.25. function getSimulationStopTime( ) 749
7.4.2.26. function getSimulationTimeStep( ) 749
7.4.2.27. function getTrnsysExeDir( ) 750
7.4.2.28. function getTrnsysInputFileDir( ) 750
7.4.2.29. function getTrnsysRootDir( ) 750

76
TRNSYS 17 Programmer's Guide

7.4.2.30. function getTrnsysUserLibDir( ) 750


7.4.2.31. function getTrnsysDebugLibDir( ) 751
7.4.2.32. function getTrnsysReleaseLibDir( ) 751
7.4.2.33. function getVariableDescription(i,j) 751
7.4.2.34. function getVariableUnit(i,j) 751
7.4.2.35. function getVersionNumber( ) 752
7.4.2.36. function getMinorVersionNumber( ) 752
7.4.2.37. function LogicalUnitIsOpen(LU) 752
7.4.2.38. function getTimeReport() 753
7.4.2.39. function getConnectedOutputNumber(i,j) 753
7.4.2.40. function getConnectedOutputNumberS1(i,j) 753
7.4.2.41. function getConnectedUnitNumber(i,j) 753
7.4.2.42. function getConnectedUnitNumberS1(i,j) 754
7.4.2.43. function getConnectedTypeNumber(i,j) 754
7.4.2.44. function getConnectedTypeNumberS1(i,j) 754
7.4.2.45. function getConnectedVariableType(i,j) 754
7.4.2.46. function getConnectedVariableTypeS1(i,j) 755
7.4.2.47. function getConnectedVariableUnit(i,j) 755
7.4.2.48. function getConnectedVariableUnitS1(i,j) 755
7.4.2.49. function getCurrentUnit() 756
7.4.2.50. function getCurrentType() 756
7.4.2.51. function getIsLastCallofSimulation() 756
7.4.2.52. function getIsEndOfTimestep() 756
7.4.2.53. function getIsFirstCallofSimulation() 757
7.4.2.54. function getIsStartTime () 757
7.4.2.55. function getIsReReadParameters() 758
7.4.2.56. function getIsVersionSigningTime() 758
7.4.2.57. function getDynamicArrayValueLastTimestep(j) 758
7.4.2.58. function getStaticArrayValue(j) 759
7.4.2.59. function getOverallIteration(i) 759
7.4.2.60. function getTimestepIteration() 759
7.4.2.61. function getInputValue(i) 760
7.4.2.62. function getOutputValue(i) 760
7.4.2.63. function getParameterValue(i) 760
7.4.2.64. function getNumberOfParameters() 760
7.4.2.65. function getNumberOfDerivatives() 761
7.4.2.66. function getNumberOfInputs() 761

77
TRNSYS 17 Programmer's Guide

7.4.2.67. function getNumberOfOutputs() 761


7.4.2.68. function getPreviousControlState(i) 761
7.4.2.69. function getNumericalSolution(i) 762
7.4.2.70. function closeFileIVF(lu) 762
7.4.2.71. function getNFiles(unitNum) 762
7.4.2.72. function getExtFilePath(unitNum,fileNum,extFilePath) 762
7.4.2.73. function getTypeVersion() 763
7.4.2.74. function getNumericalDerivative(i) 763
7.4.2.75. setOutputValue(i,Value) 763
7.4.2.76. setNumberofOutputs(i) 764
7.4.2.77. setNumberofDiscreteControls(i) 764
7.4.2.78. setDesiredDiscreteControlState(i,j) 764
7.4.2.79. setIterationMode(i) 765
7.4.2.80. setTypeVersion(i) 765
7.4.2.81. setNumberofParameters(i) 765
7.4.2.82. setNumberofInputs(i) 766
7.4.2.83. setNumberofDerivatives(i) 766
7.4.2.84. foundBadParameter(i,Severity,Message) 766
7.4.2.85. foundBadInput(Input,Severity,Message) 767
7.4.2.86. setInputUnits(i,String) 767
7.4.2.87. setOutputUnits(i,String) 768
7.4.2.88. setNumericalDerivative(i,derVal) 768
7.4.2.89. writeToList(message) 768
7.4.2.90. addExternalFile(LUN, FileName) 769
7.4.2.91. readNextChar(lun) 769
7.4.2.92. Access Functions for (really, really) Expert Users 769
7.4.3. The INFO array Typical calling sequence 774
7.4.3.1. INFO(1:5) 774
7.4.3.2. INFO(6) 775
7.4.3.3. INFO(7) 775
7.4.3.4. INFO(8) 775
7.4.3.5. INFO(9) and Types calling sequence 776
7.4.3.6. INFO(10) 777
7.4.3.7. INFO(11) 777
7.4.3.8. INFO(12) 777
7.4.3.9. INFO(13) 777
7.4.3.10. Typical calling sequence for an iterative Type 777

78
TRNSYS 17 Programmer's Guide

7.4.4. Utility subroutines 779


7.4.4.1. CallProgram (Calling External Programs) 779
7.4.4.2. Enclosure_17 (formerly ENCLOSURE and ENCL) 780
7.4.4.3. Fluid_Properties (formerly FLUID_PROPS and FLUIDS) 782
7.4.4.4. getIncidentRadiation 785
7.4.4.5. InterpolateData (formerly DynamicData, DYNDATA and DATA) 798
7.4.4.6. LinearRegression (formerly DFIT and FIT) 7101
7.4.4.7. LINKCK 7104
7.4.4.8. InvertMatrix (formerly MATRIX_INVERT, INVERT and DINVRT) 7106
7.4.4.9. Messages 7107
7.4.4.10. ParRead 7109
7.4.4.11. MoistAirProperties (formerly PSYCHROMETRICS and PSYCH) 7110
7.4.4.12. Rcheck 7113
7.4.4.13. Rewind 7120
7.4.4.14. SolarCellPerformance (formerly SOLCEL) 7121
7.4.4.15. SolveDiffEq (formerly DIFFERENTIAL_EQN, and DIFFEQ) 7123
7.4.4.16. Steam_Properties (formerly STEAM_PROPS and STEAM) 7126
7.4.4.17. Storage of Data between Time Steps 7128
7.4.4.18. ASHRAE_Coefs (formerly TABLE_COEFS and TABLE) 7136
7.4.4.19. Tau_Alpha (formerly TALF) 7138
7.4.4.20. TYPECK 7140
7.4.4.21. View_Factors (formerly VIEW) 7141
7.4.5. Solving Differential Equations 7147
7.4.6. Use of the Alternate Return (RETURN 1) 7149
7.4.7. Use of the ICNTRL Array 7150
7.4.8. Converting Types from earlier TRNSYS Versions 7152
7.4.8.1. Converting components from version 13.x to version 14.1 7152
7.4.8.2. Converting components from version 14.1 to version 14.2 7152
7.4.8.3. Converting components from version 14.2 to version 15.x 7153
7.4.8.4. Converting components from version 15.x to version 16.x 7153
7.5. Instructions to rebuild TRNDll.dll and other dynamic link libraries 7162
7.5.1. Instructions to rebuild TRNDll.dll with Compaq Visual Fortran 6.6 7162
7.5.1.1. Cvf66 Workspace 7162
7.5.1.2. TRNDll project 7163
7.5.1.3. Project settings 7163
7.5.1.4. Project files 7164
7.5.1.5. Building the TRNSYS DLL (TRNDll.dll) 7165

79
TRNSYS 17 Programmer's Guide

7.5.1.6. Debugging TRNSYS 7165


7.5.1.7. Known issues with CVF 6.6 7166
7.5.2. Instructions to add a new project to the CVF66 workspace 7168
7.5.2.1. Cvf66 workspace 7168
7.5.2.2. New Project 7168
7.5.2.3. Project settings 7168
7.5.2.4. Project files 7170
7.5.2.5. Building the new DLL 7170
7.5.2.6. Troubleshooting multiple DLL's 7171
7.5.3. Rebuilding the TRNDll.dll with Intel Visual Fortran 11.x and MS Visual Studio 200x 7172
7.5.3.1. Ivf11x Solution 7172
7.5.3.2. TRNDll project 7172
7.5.3.3. Project settings 7173
7.5.3.4. Project files 7175
7.5.3.5. Building TRNDll.dll 7175
7.5.4. Instructions to add a new project to the Ivf11.x Solution 7176
7.5.4.1. Ivf11.x Solution 7176
7.5.4.2. New Project 7176
7.5.4.3. Project settings 7177
7.5.4.4. Project files 7178
7.5.4.5. Building MyDLL 7178
7.5.5. Rebuilding the TRNDll.dll with Intel Visual Fortran Composer XE 2011 7179
7.5.5.1. IvfCXE2008 Solution 7179
7.5.5.2. TRNDll project 7179
7.5.5.3. Project settings 7179
7.5.5.4. Project files 7182
7.5.5.5. Building TRNDll.dll 7182
7.5.6. Instructions to add a new project to the IvfCXE2011 Solution 7183
7.5.6.1. Ivf11.x Solution 7183
7.5.6.2. New Project 7183
7.5.6.3. Project settings 7184
7.5.6.4. Project files 7185
7.5.6.5. Building MyDLL 7185
7.6. References 7187

710
TRNSYS 17 Programmer's Guide

711
TRNSYS 17 Programmer's Guide

7. PROGRAMMER'S GUIDE
7.1. Introduction and Overview
This manual is intended for users who are familiar with constructing and running TRNSYS
simulations and who wish to write and make use of their own TRNSYS components. In order to
accomplish this task, the user must have access to a FORTRAN compiler capable of generating
a 32-bit dynamic link library (also called a DLL). NOTE that technically, it is not entirely necessary
to write and compile components in FORTRAN; because of the structure of DLLs, components
can be written in other languages such as C++ as well. In these cases, the user must have a
compiler capable of turning code in the programming language of their choice into a 32-bit DLL.
This manual focuses almost entirely on guiding users through the process of writing components
in FORTRAN.

TRNSYSs source code is split into two parts: the kernel contains all of the brains while the Types
calculate the performance of the various components that may be used in a given simulation. The
Types and kernel are not physically distinct from one another but are compiled and linked
together in a file called the TRNDll.dll.

TRNSYS users will be familiar with the idea that TRNSYS components are all structured in a very
similar way as viewed from the outside; they take input information in the form of INPUTS and
PARAMETERS and they calculate OUTPUTS. This generic structuring extends into the code of
the components themselves; all components deal with the information that they are passed from
the TRNSYS kernel in the same way and moreover, in the same order. This generic structure
means that users can build on existing components and can copy existing components to suit
their own needs. Section 7.3 explains in detail how to structure components.

There are 3 main sections in this guide:


Section 7.2 explains how to update TRNSYS 16 components to the recommended TRNSYS
17 coding standard. Note that while these changes are recommended, they are not required.
Section 7.4.8 of this manual contains information on how to update TRNSYS components
written for earlier versions to more recent coding standards.
Section 7.3 describes the process of creating a new component from scratch
Section 7.4 Provides detailed reference on the TRNSYS kernel:
Calling sequence of Types and structure of the INFO array (7.4.2.49)
Available global constants (7.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 7.4.1.2.
Access functions that allow Types to access kernel variables (7.4.2)
Utility subroutines (7.4.4)
Instructions to recompile the TRNSYS DLL and add new DLL's to UserLib using different
compilers (Sections 0, 7.5.2 and above)

712
TRNSYS 17 Programmer's Guide

7.2. Updating TRNSYS 16 Components to


the TRNSYS 17 Coding Standard
There are no required changes that a user must make to components that were written in the
TRNSYS 16 coding standard in order for them to work the same in TRNSYS 17. However, a
major effort was made in developing TRNSYS 17 to simplify the structure of components so it
may be worth the users effort to update to the most recent standard. Furthermore, while every
effort is made to maintain backwards compatibility from one major TRNSYS version release to
the next, there may come a time when the developers decide to sunset backwards compatibility
for older and older versions.

Since fewer and fewer users have experience in writing programs in FORTRAN, one of the main
focuses of TRNSYS 17 development was the simplification of the interaction between the
TRNSYS kernel and the TRNSYS types. For example, where a user was previously required to
identify a bad PARAMETER value by using the following call to the TYPECK subroutine:
IF (NODES_F.LT.1) CALL TYPECK(-4,INFO,0,19,0)

The user now implements the following:


If (NODES_X < 1) Call foundBadParameter(19,Fatal,The number of nodes in the
x direction cannot be fewer than 1.)

The code -4 that told TYPECK what action to take is replaced by a more intuitive subroutine
name, the TYPECK routine goes and gets the information that it needs from the INFO array by
itself, two of the three index arguments are gone; only the index number of the bad PARAMETER
remains (in this case, it is PARAMETER 19 that has been identified as having a bad value).
TYPECKs generic and somewhat cryptic message saying simply that PARAMETER 19 has a
bad value is replaced by a more specific message and the user is able to decide whether this bad
parameter value should be a warning to the user or whether it should result in a fatal error and
stop the simulation.

The following sections go over the recommended modifications to update a TRNSYS 16


component to the TRNSYS 17 coding standard.

7.2.1. The Subroutine Call


The TRNSYS kernel no longer automatically passes information to the TRNSYS components;
components are required to get the information that they need from the TRNSYS kernel using
Access Functions (see Section 7.4.2 for a complete list of Access Functions). As a result of this
change, the very first line of the Type should be changed from
SUBROUTINE TYPEnnn(TIME,XIN,OUT,T,DTDT,PAR,INFO,ICNTRL,*)
to
Subroutine TYPEnnn

where nnn is the Type number in both cases.

713
TRNSYS 17 Programmer's Guide

7.2.2. Set Global Simulation Variables


The current value of the simulation time used to be passed to Types by the kernel through the
subroutine argument list. Since the argument list has been removed, Types now need to go and
get various values. Almost all Types will need to go and get the current simulation time. Most
types will also need to know their UNIT and TYPE number. The following lines need to be added
Time = getSimulationTime()
currentUnit = getCurrentUnit()
currentType = getCurrentType()

7.2.3. Identify the Types Coding Standard (version


signing)
A new access function was added to simplify the method by which the Type identifies its coding
standard to the kernel. The following section of the Type should be changed from
C SET THE VERSION INFORMATION FOR TRNSYS
IF(INFO(7).EQ.-2) THEN
INFO(12)=16
RETURN 1
ENDIF

to
!Set the Version Number for This Type
If (getIsVersionSigningTime()) Then
Call setTypeVersion(17)
Return
EndIf
Note that the RETURN 1 statement is replaced by a simple RETURN. Use of the alternate
return was abandoned with TRNSYS 17. Refer to section 7.4.6 for additional information
concerning alternate return statements in FORTRAN.

7.2.4. Perform Last Call Manipulations


A new access function was added to simplify the method by which the Type knows that the
current call is the very last call in the simulation. The following section of the Type should be
changed from
C PERFORM LAST CALL MANIPULATIONS
IF(INFO(8).EQ.-1) THEN
...
RETURN 1
ENDIF
to
! Do All of the Last Call Manipulations Here
If (getIsLastCallofSimulation()) Then
...
Return
EndIf

The ellipsis () is used to indicate that any actual manipulations performed by the component
should stay the same between the TRNSYS 16 and 17 coding standards.

714
TRNSYS 17 Programmer's Guide

NOTE that the Return 1 statement in the TRNSYS 16 coding standard is replaced by a simple
Return in the TRNSYS 17 coding standard.

7.2.5. Perform End of Time Step Manipulations


A new access function was added to simplify the method by which the Type knows that this is the
end of timestep call that the kernel makes to each Type at the end of a time step after
convergence has been reached (or after the kernel has decided that convergence cannot be
reached) but before the simulation time has advanced. The following section of the Type should
be changed from
C PERFORM POST CONVERGENCE MANIPULATIONS
IF(INFO(13).GT.0) THEN
...
RETURN 1
ENDIF
to
! Perform Any "End of Timestep" Manipulations That May Be Required
If (getIsEndOfTimestep()) Then
...
Return
EndIf

Again, the ellipsis () is used to indicate that any actual manipulations performed by the
component should stay the same between the two coding standards.

7.2.6. Perform First Call Manipulations


In the TRNSYS 16 coding standard, Types were expected to carry out a series of steps to
introduce themselves to the TRNSYS kernel (before time has begun to advance). These were as
follows:
Set the first and second spots in the INFO() array to local variables IUNIT and ITYPE
Reserve space in the global OUT() array
Set the Types place in the global Type-calling structure (the ninth spot in the INFO() array).
Call the TYPECK() subroutine to check and make sure that the user had provided the
correct number of PARAMETERS, INPUTS, and DERIVATIVES.
Set the 3-digit codes for the Types INPUTS and OUTPUTS and call the RCHECK() routine
so that the kernel can check the users input/output connections.
Reserve space in the kernels single-precision global storage structure (ONLY for legacy
TRNSYS 15 coding standard Types)
Reserve space in the kernels double-precision global storage structure (if necessary)

As with the other TRNSYS coding standard updates discussed in this section, the manipulations
that are made in the TRNSYS 17 coding standard are unchanged. The modifications are all in
how the manipulations are made.
The first step, of course, is to check whether or not the current call is the first call. In the
TRNSYS 16 coding standard, this was accomplished by checking whether the value of the
7th INFO() array spot was equal to -1. In the TRNSYS 17 standard, an access function is
provided:

715
TRNSYS 17 Programmer's Guide

IF (INFO(7).EQ.-1) THEN
TRNSYS 16 coding standard: ...
ENDIF
If (getIsFirstCallofSimulation()) Then
TRNSYS 17 coding standard: ...
EndIf

The IUNIT and ITYPE variables are no longer needed. They were replaced by a global
simulation variable call (see section 7.2.2).
IUNIT=INFO(1)
TRNSYS 16 coding standard: ITYPE=INFO(2)

TRNSYS 17 coding standard:

Reserving space in the OUT() array using the 6th spot in the INFO array becomes a call to
an access function. Note the 5 in the following example should be replaced by the actual
number of outputs for the Type in question.

TRNSYS 16 INFO(6)= 5
coding standard:

TRNSYS 17 Call SetNumberofOutputs(5)


coding standard:

Setting the Types place in the global Type-calling structure changes from setting the 9th spot
of the INFO() array to a call to an access function. Note that 1 in the following example
denotes that the Type should be called along with others until convergence is reached. Refer
to section 7.4.2.80 for information on other possible argument values to the
setIterationMode() subroutine.

TRNSYS 16 INFO(9)= 1
coding standard:

TRNSYS 17 Call SetIterationMode(1)


coding standard:

Setting up data storage is the one spot where there is not a one-to-one correspondence
between calling a subroutine in the TRNSYS 16 standard and calling an access function in
the TRNSYS 17 standard. The TRNSYS 16 standard offered a one size fits all solution to
data storage between time steps; components reserved space, placed, and removed
whatever variables they wanted in storage at whatever time was appropriate to their
purposes. TRNSYS 17 offers two data storage options (called static and dynamic). Refer
to section 7.4.4.17 for additional information. In converting a TRNSYS 16 type to TRNSYS
17, set the number of items that you were storing (nItems in the example below) as the
second argument in the setNumberStoredVariables() subroutine call.

TRNSYS 16 CALL setStorageSize(xFer,nItems,INFO)


coding standard:

TRNSYS 17 Call setNumberStoredVariables(0,nItems)


coding standard:

716
TRNSYS 17 Programmer's Guide

A call to the TYPECK() subroutine in the TRNSYS 16 coding standard was used for various
purposes; the action that TYPECK() took was determined by the first argument (the IOPT
mode see section 7.4.4.20 for additional details). In the TRNSYS 17 coding standard,
each mode is replaced by one or more specific task subroutine calls. Typically the first call to
TYPECK() was used to check that the user specified the correct number of inputs,
parameters, and derivatives in the input file. This was accomplished by calling TYPECK()
with an IOPT mode of 1. In the TRNSYS 17 coding standard, the call to TYPECK is replaced
by calls to three subroutines as shown below. Note that in the example below, nI denotes the
number of INPUTS specified/expected, nP denotes the number of PARAMETERS and nD
denotes the number of DERIVATIVES.

TRNSYS 16 CALL TYPECK(1,INFO,nI,nP,nD)


coding standard:
Call SetNumberofParameters(nP)
TRNSYS 17 Call SetNumberofInputs(nI)
coding standard: Call SetNumberofDerivatives(nD)

The RCHECK() subroutine was used in the TRNSYS 16 coding standard to check and make
sure whether the user had connected only INPUTS and OUTPUTS whose units match. For
example to make sure that temperature outputs in C are connected to inputs in C. The
recommended methodology was to set up two arrays (YCHECK and OCHECK) each
containing a three letter code designating the units of each input and output employed by the
Type. For example, if a Type has three inputs: temperature in [C], mass flow rate in [kg/h],
and pressure in [atm] then the corresponding three-letter codes placed in the YCHECK()
array would be TE1 (for C), MF1 (for kg/h) and PR1 (for atm). Once the YCHECK() and
OCHECK() arrays had been set up, the user called the RCHECK subroutine.
The recommended methodology in the TRNSYS 17 coding standard is to call the
setInputUnits() and setOutputUnits() subroutines, sending the three letter code for a
particular input or output each time. In the following example, the Type has 5 inputs and 4
outputs.
DATA YCHECK/'TE1','MF1','CF1','TE1','TE1'/
TRNSYS 16 DATA OCHECK/'TE1','MF1','PW1','PW1'/
coding standard: CALL RCHECK(INFO,YCHECK,OCHECK)
Call SetInputUnits(1,'TE1')
Call SetInputUnits(2,'MF1')
Call SetInputUnits(3,'CF1')
Call SetInputUnits(4,'TE1')
TRNSYS 17 Call SetInputUnits(5,'TE1')
coding standard:
Call SetOutputUnits(1,'TE1')
Call SetOutputUnits(2,'MF1')
Call SetOutputUnits(3,'PW1')
Call SetOutputUnits(4,'PW1')

Certain Types require calls to additional access functions and utility routines during the first
call. For example, Types employing the numerical differential equation solver should also
set the expected number of derivatives. The present discussion is limited to the
manipulations that all components must make. Refer to the relevant sections of this manual
for additional information on first call manipulations required by specific kernel features.
The RETURN 1 statement is replaced by a simple RETURN

TRNSYS 16 RETURN 1
coding standard:

717
TRNSYS 17 Programmer's Guide

TRNSYS 17 Return
coding standard:

7.2.7. Perform Start Time Manipulations


In both the TRNSYS 16 and TRNSYS 17 coding standards, the component reads it parameters at
the initial time step and sets output initial values. It should NOT read its inputs or simulate
performance since simulation time has not yet advanced.
The first step, again, is to check whether or not the current call is the initial time step call. In
the TRNSYS 16 coding standard, this was accomplished by checking whether time had
advanced yet. Note that again the RETURN 1 is replaced with a simple RETURN In the
TRNSYS 17 standard, an access function is provided:
IF(TIME.LT.(TIME0+DELT/2.)) THEN
TRNSYS 16 coding standard: ...
RETURN 1
ENDIF
If (getIsStartTime()) Then
TRNSYS 17 coding standard: ...
Return
EndIf

The IUNIT and ITYPE variables are no longer needed. They were replaced by a global
simulation variable call (see section 7.2.2).

TRNSYS 16 IUNIT=INFO(1)
coding standard: ITYPE=INFO(2)

TRNSYS 17 ! there is no code required to replace these lines.


coding standard:

Next, the Type reads its parameters and stores them as local variables. In the following
example, the Type has 4 parameters:
QMAX = PAR(1)
TRNSYS 16 CP = PAR(2)
coding standard: UA = PAR(3)
HTREFF = PAR(4)
qmax = getParameterValue(1)
TRNSYS 17 cp = getParameterValue(2)
coding standard: ua = getParameterValue(3)
htreff = getParameterValue(4)

After reading the parameters, the TRNSYS 16 Type checks their values using another call to
TYPECK(), this time with an IOPT mode of -4. By contrast, the TRNSYS 17 Type calls an
access function with a more specific message:
!Check the parameters for problems
IF(QMAX.LT.0.) CALL TYPECK(-4,INFO,0,1,0)
TRNSYS 16 IF(CP.LT.0.) CALL TYPECK(-4,INFO,0,2,0)
coding standard: 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
!Check the parameters for problems
TRNSYS 17 If (qmax < 0.) Call foundBadParameter(1,'Fatal', &

718
TRNSYS 17 Programmer's Guide

coding standard: 'The heater capacity must be positive.')


If (cp < 0.) Call foundBadParameter(2,'Fatal', &
'The fluid specific heat must be positive.')
If (ua < 0.) Call foundBadParameter(3,'Fatal', &
'The heater UA must be positive.')
If ((htreff < 0.).or.(htreff > 1.)) Call foundBadParameter(4, &
'Fatal','The heater efficiency must be between 0 and 1.')
If (ErrorFound() ) Return

The final task for the initial time call is for the Type to set output initial values. In the
TRNSYS 16 coding standard, a Type did so by setting values of the OUT() array. The
TRNSYS 17 coding standard Type calls an access function instead:
! Set the Initial Values of the Outputs
OUT(1) = XIN(1) !outlet temperature = inlet temperature [C]
OUT(2) = XIN(2) !mass flowrate out = mass flowrate in [kg/hr]
TRNSYS 16 OUT(3) = 0. !required heating rate [kJ/hr]
coding standard: OUT(4) = 0. !rate of losses to environment [kJ/hr]
OUT(5) = 0. !rate of energy delivered to stream [kJ/hr]
!the first timestep is for initialization - exit
RETURN 1
! Set the Initial Values of the Outputs
Call SetOutputValue(1,getInputValue(1))
Call SetOutputValue(2,getInputValue(2))
TRNSYS 17 Call SetOutputValue(3,0.d0)
coding standard: Call SetOutputValue(4,0.d0)
Call SetOutputValue(5,0.d0)
! Return to the TRNSYS kernel
Return

7.2.8. Rereading Parameters


If two or more instances of a given Type are to be used in a simulation, it is necessary to reread
the parameter values so that the local variables within the Types code reflect the values
associated with the current instance. In the TRNSYS 16 coding standard, this was accomplishd
by checking whether the 1st spot of the INFO() array was equal to the local variable iUnit. Again,
this check is replaced by an access function call.
!ReRead the Parameters if another Unit of this Type was
called last
IF(INFO(1).NE.IUNIT) THEN
!reset the unit number
IUNIT = INFO(1)
TRNSYS 16 ITYPE = INFO(2)
coding standard: !read the parameter values
QMAX = PAR(1)
CP = PAR(2)
UA = PAR(3)
HTREFF = PAR(4)
ENDIF
!ReRead the Parameters if another Unit of this Type was
called last
If (getIsReReadParameters()) Then
TRNSYS 17 qmax = getParameterValue(1)
coding standard: cp = getParameterValue(2)
ua = getParameterValue(3)
htreff = getParameterValue(4)
Endif

719
TRNSYS 17 Programmer's Guide

7.2.9. Retrieving Input Values


Each Type retrieves its own inputs. In the TRNSYS 16 coding standard, this involved reading the
contents of the XIN() array to local variables. In TRNSYS 17 coding, an access function is
employed:
!Get the Current Inputs to the Model
TIN = XIN(1)
TRNSYS 16 FLOW = XIN(2)
coding standard: IGAM = JFIX(XIN(3)+0.1)
TSET = XIN(4)
TAMB = XIN(5)
!Get the Current Inputs to the Model
tin=getInputValue(1)
TRNSYS 17 flow=getInputValue(2)
coding standard: igam=JFIX(getInputValue(3)+0.1)
tset=getInputValue(4)
tamb=getInputValue(5)

7.2.10. Other Considerations


User written Types often make use of other utility subroutines (such as steam or psychrometric
properties), solve differential equations (using either analytical or numerical solution techniques),
or use inter-time step data storage. If such features are relevant to the Type you are converting,
please refer to the corresponding section of this manual for information about the access
functions that have replaced many of the direct calls to utility subroutines. The present discussion
is limited to those manipulations that are common to every TRNSYS component.

720
TRNSYS 17 Programmer's Guide

7.3. How to Create New Components


One of TRNSYSs major strengths is the ease with which users may write new components to
expand upon the capabilities of the program. Three features provide the foundation of this
expandability. First is TRNSYSs open architecture. With one exception, all standard components
are provided along with their source code to act as a reference and to act as the basis for adding
new components. Second, all components whether standard components or user written
components are formulated in the same manner and follow the same steps and progression
throughout the code; writing new components becomes a matter of using a template and adding
the appropriate functions, utility calls and equations to write a model of your own. Thirdly, and
perhaps most importantly, the TRNSYS kernel does not impose any hierarchy whatsoever on the
components that are used in a simulation. Nor does it make any assumptions regarding the order
in which components should be solved to simulate the system. Many other simulation packages
do impose such a hierarchy. To take the example of simulating a building, they often solve the
building loads using one part of their kernel, then proceed to solve the system with another part of
their kernel and finally solve the plant aspect of the system last. Many do not revise a previous
step based on calculations in a subsequent step. Thus the system could well not meet the load at
a given time step. However, the building, at the next time step, has no idea that the load was not
met. TRNSYS, by contrast, continues to iterate through all components (whether by successive
substitution or Powells method) until convergence is reached. While this can make controls in a
TRNSYS simulation somewhat more cumbersome, it has a major advantage from the point of
view of someone writing a new component; that is that there is no need for the component writer
to modify the TRNSYS kernel in any way in order to accommodate and include their new
component. There is no need, for example to decide where in the management hierarchy the new
component that you are writing fits best. Components in TRNSYS are automatically called by the
kernel as soon as they are found in a given simulation. By assigning a number to each
component, the TRNSYS kernel anticipates and automatically calls all component numbers that it
finds in a simulation input file. If a particular Type number is found in the input file but is not found
in the compiled code by the TRNSYS kernel, a dummy place holding component is called in its
stead and the simulation ends with an error.

The following sections of this manual will step the new TRNSYS Type programmer through the
process of filling in a Type template in order to create a new model for use in TRNSYS
simulations.

7.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. The kernel takes care of solving the system of black boxes. 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. Examples of inputs that do not change with time are area or 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.

721
TRNSYS 17 Programmer's Guide

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.

With TRNSYS v. 14.2 and lower, the TRNSYS kernel and Types were all written in FORTRAN
and were compiled together into a run-time executable that offered nothing in terms of a graphical
interface, online plotting or even a progress bar. As the Microsoft Windows operating system
gained popularity and functionality, the TRNSYS structure shifted to that of an exe/dll. In this
scenario, a comparatively small executable was written and provided by the TRNSYS developers
to handle all of the Windows operating system requirements. The kernel and Types were still
written in FORTRAN but were now compiled into a construct called a dynamic link library (or
DLL for short). The exe and dll spoke back and forth, made use of Windows functionality such as
graphical online plotting, yet did not confuse the Type programmer with any of the Windows
trivialities. With TRNSYS versions between 14.2 and 16.0, one complexity was that a user
wishing to include a non standard Type in their project had to recompile the DLL to include both
the standard code and the non-standard Type (and, incidentally needed a Fortran compiler to do
so). With the release of TRNSYS v.16.0, a major effort was made to allow for a multiple dll
structure. That is to say that the main exe/dll structure remained but the standard dll could also
call out to other dlls and load Types and routines found therein.

With TRNSYS v. 16.x and lower, the kernel passed certain pieces of information to each Type
and recuperated information set by the Types by means a list of arguments in the Type calling
statement. Not all of the information required by Types was available by means of the argument
list, however. Types got that other information by a hodgepodge of methods such as subroutines,
COMMON blocks, access functions, USE statements, and data modules. With the release of
TRNSYS 17, the argument list was removed and new access functions were added; Types were
expected to use access functions to get all of the data that they need from the kernel.

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

Q& = m& C p (Tset Tin ) Eq. 7.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
& should obviously be an output, while m& , Tset, and
its inlet condition to its outlet condition, then Q
Tin should be INPUTS. Cp could be designated as either a PARAMETER or as an INPUT
depending upon whether or not the liquid specific heat can be assumed to be constant or whether
it varies significantly with liquid temperature. If, on the other hand, the goal of the component is

722
TRNSYS 17 Programmer's Guide

for the end user to provide inlet conditions, a control signal and a heater output that is full ON
whenever the control signal is set to ON, then perhaps the output of the model would be Tout,
& , Tin, and Q& .
and the inputs would be m

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.

7.3.2. The First Line


Every Type begins with the same line:
SUBROUTINE TYPEn
Where n in TYPEn is a number between 1 and 9999. To avoid problems with more than one
component being assigned the same number, the following conventions have been adopted:
Type1 Type200: reserved for library of Standard TRNSYS Components
Type201 Type300 : reserved for user written components
Type301 Type500: reserved for add-on components commercially available from
Transsolar Energietechnik, GmbH
Type501 Type1700: reserved for add-on components commercially available from Thermal
Energy System Specialists, LLC (TESS)
Type1701 Type1800: reserved for add-on components commercially available from
Auiguasol
Type1801 Type2000: reserved for add-on components commercially available from CSTB.
Type2001 Type2200: reserved for components from TRNLib, the freely available online
resource of user-written components.
Type2201 Type2300: reserved for additional add-on components commercially available
from TESS.
Type2301 Type2400: reserved for components in the Solar Thermal Electric Components
(STEC) library
Type2401 Type2500: reserved for components in the TRNAUS library
Type2501 Type2600: reserved for components in the System Advisor Module (SAM)
library.
Type2601 Type3000: unreserved.
Type3001 Type3500: reserved for add-on components commercially available from CSTB.
Type3501 Type7000: unreserved.
Type7001 Type8000: reserved for components in the Solar Ratings and Certification
Corporation (SRCC) library.
Type8001 Type9999: unreserved

For this example, Type number 201 will arbitrarily be chosen. Thus the first line of the subroutine
should be:

723
TRNSYS 17 Programmer's Guide

SUBROUTINE TYPE201

7.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 (and later) 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 7.3.16 and 7.5.2 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 (Type201) we would have the following line added:
...
!DEC$ATTRIBUTES DLLEXPORT :: TYPE201
...
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. This kind of syntax is
called a compiler directive; it indicates something to the compiler about how to compile the code
without affecting the executable FORTRAN itself.

7.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 the variables that are
accessible by various subroutines (Types, and kernel routines) within a program all in one
location. 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 7.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 or functions contained within the
module in your Type. Alternatively, if you only want to use a particular variable or function 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

724
TRNSYS 17 Programmer's Guide

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 7.4.1,
7.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
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.

7.3.5. Variable Declarations


Having defined the subroutine, 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. 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.
...
! LOCAL VARIABLE DECLARATIONS
Integer iGam
Double Precision time, & !the current simulation time [hr]
Timestep, & !the simulation time step [hrs]
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]
...
For those less familiar with FORTRAN syntax, blue text indicates a keyword that is recognized as
a declaration or a function by the compiler. Green text indicates a comment (comment lines in
FORTRAN begin with an exclamation mark). The & simply indicates a line continuation.

725
TRNSYS 17 Programmer's Guide

7.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 7.3.5 above. While no DATA statements are
necessary for our Type201 water heater, a DATA statement setting the value of pi and the
conversion factor between degrees and radians would look like the following:
Data rdconv/0.017453/,pi/3.1415927/

7.3.7. Global Constants and Variables


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. Users familiar with coding standard prior to TRNSYS17
will recall that a good bit of information was passed to the component through the argument list.
In the TRNSYS 17 coding standard, some of this information must now be obtained using
AccessFunctions. Variables such as the simulation time, the time step, the simulation start time,
and the simulation stop time, the current Unit number, the current Type number must be retrieved
on an as needed basis. Almost all Types, this one included, need to know the simulation time
and the simulation time step. These two variables are used later to control Type functionality (see
section 0 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 Timestep and the local variable name for the simulation time is
simply Time The code that should be added to Type201 is as follows:

!----------------------------------------------------------------------
!Get the Global Trnsys Simulation Variables
Time = getSimulationTime()
Timestep = getSimulationTimeStep()

7.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 using a given TRNSYS coding
standard. 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

726
TRNSYS 17 Programmer's Guide

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). The same was true of the TRNSYS 17 release; TRNSYS 16 and
TRNSYS 15 components (and their specific needs) can be handled by the TRNSYS 17 kernel
provided that the Types log themselves properly during the version signing step. In order for the
kernel to know how to treat a Type, however, each Type must log itself as having been written
with TRNSYS 17, TRNSYS 16, or the TRNSYS 15 (and earlier) conventions. For additional
information about the differences in conventions, please refer to section 7.4.8 of this manual.

For the purposes of the liquid heater example, we are writing a TRNSYS 17 style component so
we must add lines of code that version sign our Type as complying with the TRNSYS 17 coding
requirements. The code lines that must be added are:
...
!----------------------------------------------------------------------
!Set the Version Number for This Type
If (getIsVersionSigningTime()) Then
Call SetTypeVersion(17)
Return
Endif
...
If a Type fails to register the coding standard for which it was written, the TRNSYS kernel will not
allow the simulation to proceed and will generate an error, writing it to the simulation list and log
files.

7.3.9. Last Call Manipulations


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 Type201 is as follows:
...
!----------------------------------------------------------------------
!Do All of the Last Call Manipulations Here
If (getIsLastCallofSimulation()) Then
Return
Endif
You may want your component to actually do something at the end of the simulation. It could, for
instance 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 AccessFunction getIsLastCallOfSimulation() also returns a true result if the simulation


terminates with a fatal error. In that case, the component that generates the error returns control
to the TRNSYS kernel, 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 the last call as follows:

727
TRNSYS 17 Programmer's Guide

If (getIsLastCallOfSimulation() ) Then
! Exit immediately if this call is the result of a fatal error
If (getNumberOfErrors() > 0) Then
Return
! Otherwise, print the nb of "stuck" timesteps
Else
... printing manipulations
...
EndIf
Return ! Exit
EndIf
Notes:
If the simulation ends without errors, the last call manipulations 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.

7.3.10. End of Time Step Manipulations


At the end of each time step, each Type in a simulation is recalled. The Type should call the
AccessFunction getIsEndOfTimestep(). Note that the function will return true even if a
converged solution was not found at the current time step. In this case of the liquid heater
example, no post convergence manipulations are needed. Therefore, we can enter the following
code at this point in the component:
...
!----------------------------------------------------------------------
!Perform Any "End of Time Step" Manipulations That May Be Required
If (getIsEndOfTimestep()) Then
Return
Endif...

In more complex components than the one detailed by this example, the end of time step call
allows a number of different manipulations to be performed such as resetting counters. For users
familiar with the concept of manually updating storage variables, the concept of dynamic and
static storage variables were introduced with TRNSYS 17. Refer to section 7.4.4.17

7.3.10.1. Resetting Counters


It is sometimes advantageous to count the number of times that a particular event has occurred
during a given time step. One example might be a controller that counts the number of times that
it has calculated a different value of its control signal during a given time step. After a certain
number of different decisions, the controller sticks and the calculated output state no longer
changes. At the end of the time step after all components have converged, it is necessary to reset
the iteration counter to zero. This could be done as one of the end of time step manipulations
when the call to the GetIsEndOfTimestep() AccessFunction returns true.

7.3.10.2. Updating Storage Variables


In TRNSYS versions prior to 17.1, another common end of timestep manipulation was to update
variables that had been stored in the global storage structure during the Types iterations. With

728
TRNSYS 17 Programmer's Guide

the addition of the concept of dynamic storage, this step is no longer needed. Refer to section
7.4.4.17.1.2 for information on implementing dynamic storage.

7.3.11. Initialization Call Manipulations


At the very start of each simulation, after all Types have version signed themselves (see section
7.3.8 or section 7.4.3.3 for more information), each Type should initialize itself. Types should call
the getIsFirstCallOfSimulation() AccessFunction to determine when these initializations should
take place. There is a very specific set of steps that each Type should take at this point in the
simulation. With the release of TRNSYS version 16, the steps taken by a Type during the
initialization step changed from what had been done previously. The most important thing to keep
in mind concerning the initialization call is that a Type should NOT read its parameter list, nor
should it perform ANY calculation of output values. It should perform the following operations

Tell the kernel how many PARAMETERS are expected to be found in the input file by calling the
SetNumberOfParameters() AccessFunction as follows:
Call setNumberOfParameters(4)

Tell the kernel how many INPUTS are expected to be found in the input file by calling the
SetNumberOfInputs() AccessFunction as follows:
Call setNumberOfInputs(5)

Tell the kernel how many DERIVATIVES are expected to be found in the input file by calling the
SetNumberOfDerivatives() AccessFunction as follows:
Call setNumberOfDerivatives(0)

Reserve the required amount of space in the global output array by calling the
SetNumberOfOutputs() AccessFunction as follows:
Call setNumberOfOutputs(5)

Set how the Type should be called using a call to SetIterationMode(). Most Types will call this
AccessFunction with 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 call the
function with different values. Users programming this kind of Type should refer to section 7.4.3.5
for more information. The call to SetIterationMode() is as follows:
Call setIterationMode(1)

Set the number of static and dynamic storage spots required using a call to the
setNumberStoredVariables() AccessFunction. Refer to section 7.4.4.17 for fundamental
information about static and dynamic data storage between time steps. 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. For the water heater component, the following statement
reserves the required space:
Call setNumberStoredVariables(0,0)

Call the routines that set three-character codes for the units of the INPUT and OUTPUT variables
and make sure that the units of the OUTPUTS that are connected to the INPUTS of this Type are
correct. Refer to section 7.4.4.12 for additional information on these three letter codes. Our list of
inputs, their units, and our list of outputs and their units is as follows:

Table 7.3.10.2-1: Inputs, Outputs, and their Units

Input Input Description Units Output Output Description Units


Number Number

729
TRNSYS 17 Programmer's Guide

1 Liquid inlet temperature C 1 Liquid outlet temperature C


2 Liquid inlet mass flow rate kg/hr 2 Liquid outlet flow rate kg/hr
3 Control signal 0..1 3 Required heating rate kJ/hr
4 Temperature set point C 4 Energy lost to ambient kJ/hr
5 Ambient temperature C 5 Energy to liquid stream kJ/hr

Referring to Table 7.3.10.2-1 and to Table 7.4.4.12-1 through Table 7.4.4.12-22, the following
AccessFunction calls 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.
! Set the Correct Input and Output Variable Types
Call setInputUnits(1,'TE1')
Call setInputUnits(2,'MF1')
Call setInputUnits(3,'CF1')
Call setInputUnits(4,'TE1')
Call setInputUnits(5,'TE1')
Call setOutputUnits(1,'TE1')
Call setOutputUnits(2,'MF1')
Call setOutputUnits(3,'PW1')
Call setOutputUnits(4,'PW1')
Call setOutputUnits(5,'PW1')

By calling the setInputUnits() and setOutputUnits() AccessFunctions, 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)

Return control to the TRNSYS kernel. Again, there are NO iterations performed during this time
step. Therefore there should be NO calculations performed. To return control, add the following
line:
Return
The code required for the above steps in the context of Type201 is as follows. Please note that
the following code is fairly 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. The user will, of course,
have to correctly adjust the arguments to the various AccessFunctions so that they correspond to
the requirements of their Type.
...
!----------------------------------------------------------------------
!Do All of the " First Call of the Simulation Manipulations Here
If (getIsFirstCallofSimulation()) Then

! Tell the TRNSYS Engine How This Type Works


Call SetNumberofParameters(4)
Call SetNumberofInputs(5)
Call SetNumberofDerivatives(0)
Call SetNumberofOutputs(5)
Call SetIterationMode(1)
Call SetNumberStoredVariables(0,0)

! Set the Correct Input and Output Variable Types


Call SetInputUnits(1,'TE1')
Call SetInputUnits(2,'MF1')
Call SetInputUnits(3,'CF1')
Call SetInputUnits(4,'TE1')
Call SetInputUnits(5,'TE1')

730
TRNSYS 17 Programmer's Guide

Call SetOutputUnits(1,'TE1')
Call SetOutputUnits(2,'MF1')
Call SetOutputUnits(3,'PW1')
Call SetOutputUnits(4,'PW1')
Call SetOutputUnits(5,'PW1')

Return

EndIf
...

7.3.12. Start Time Manipulations


Once the initialization steps (discussed in section 7.3.11 above) were completed, control was
returned to the TRNSYS kernel. The next time that each Type is called is when the simulation
time is equal to the simulation start time. Throughout much of TRNSYSs history (through version
15) there was no call to components at the simulation start time. After being called when
getIsFirstCallOfSimulation() returned true for initialization (as described in section 7.3.11) Types
were next called at the end of the first time step (TIME = InitialTime + TimeStep). With the release
of TRNSYS 16.0, an important distinction was made by calling all Types once after they have
been initialized but before time has advanced in the simulation. The point of this initial time call is
to perform the following actions:

First, read the local parameter list and set each parameter to a local variable. Parameter values
can (and should) be read only at two places in a Type. The first is during this Start Time call
before time has progressed. The other is during the multiple unit manipulations section
(discussed below in section 7.3.13). Only reading parameters at these two stages of the
simulation saves a great deal of computational time because in this manner, parameters (which
do not change with time) are read only when they must be. In each of these two sections, each
parameter value is set equal to a local variable name that has been declared as a double
precision variable among the Types local variables as discussed in section 7.3.5. The
generalized code for setting a parameter value to a local variable name is
LocalVariable = getParameterValue(n)
Type201 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 is set to a local variable name:
QMAX, CP, UA, and HTREFF respectively as follows:
! Read in the Values of the Parameters from the Input File
qmax = getParameterValue(1)
cp = getParameterValue(2)
ua = getParameterValue(3)
htreff = getParameterValue(4)
The second step performed during the start time 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 foundBadParameter()
AccessFunction. 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 = getParameterValue(2)
If (SpecHeat < 0.0) Call foundBadParameter (2,'Fatal', &
'The fluid specific heat must be positive.')
...

731
TRNSYS 17 Programmer's Guide

Once foundBadParameter() AccessFunction 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 foundBadParameter() with a bad parameter to
immediately return control to the TRNSYS kernel without completing its start time 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() AccessFunction to determine whether foundBadParameter wrote any error
messages to the simulation list and log files. For more information on the ErrorFound()
AccessFunction, please refer to section 7.4.2.6. The code for returning control in this manner is:
...
If (ErrorFound()) Return
...
Next, it is necessary to set the initial values of any static or dynamic 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 storage structure, then
calling the setStaticArrayValue() and setDynamicArrayValueThisIteration() subroutines. The code
used to set four initial storage values might look like the following:
...
Call setStaticArrayValue(1,localVar1)
Call setStaticArrayValue(2,localVar2)
Call setDynamicArrayValueThisIteration(1,localVar3)
Call setDynamicArrayValueThisIteration(2,localVar4)
...
Since our Type201 does not require any storage variable spots, there is no need to include the
above step in this section of the Type201 code.

The final step performed during the Start Time 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
outlet flow rate of the fluid can often be set to the inlet temperature and inlet flow rate
respectively. In the case of Type201, 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 Start Time Manipulations section of Type201.
...
!------------------------------------------------------------------------------
!Do All of the First Timestep Manipulations Here - There Are No Iterations at
! the Intial Time
If (getIsStartTime()) Then
! Read in the Values of the Parameters from the Input File
qmax = getParameterValue(1)
cp = getParameterValue(2)
ua = getParameterValue(3)
htreff = getParameterValue(4)
! Check the Parameters for Problems
If (qmax < 0.) Call foundBadParameter(1,'Fatal', &
'The heater capacity must be positive.')
If (cp < 0.) Call foundBadParameter(2,'Fatal', &
'The fluid specific heat must be positive.')
If (ua < 0.) Call foundBadParameter(3,'Fatal', &
'The heater UA must be positive.')

732
TRNSYS 17 Programmer's Guide

If ((htreff < 0.).or.(htreff > 1.)) Call foundBadParameter(4,'Fatal', &


'The heater efficiency must be between 0 and 1.')
If (ErrorFound()) Return
! Set the Initial Values of the Outputs
Call setOutputValue(1,getInputValue(1))
Call setOutputValue(2,getInputValue(2))
Call setOutputValue(3,0.d0)
Call setOutputValue(4,0.d0)
Call setOutputValue(5,0.d0)
Return
EndIf
...

7.3.13. Multiple Unit Manipulations


Only one more special manipulation section is required before we begin actually simulating the
performance of the liquid heater. In this Multiple Unit manipulations section, we must reread our
components parameter list if and only if there is more than one instance of the component in the
users simulation.

As usual, we begin by querying an AccessFunction:


If (getIsReReadParameters()) Then
...
EndIf
If the function returns true 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:
...
!------------------------------------------------------------------------------
!ReRead the Parameters if Another Unit of This Type Has Been Called Last
If (getIsReReadParameters()) Then
qmax = getParameterValue(1)
cp = getParameterValue(2)
ua = getParameterValue(3)
htreff = getParameterValue(4)
EndIf
...
There is no need to recheck the parameters for validity since this was done already during the
Start Time manipulations section.

7.3.14. Every Time Step Manipulations


At last we have come to the meat of writing new components. It is in this final section that the
performance of the component is simulated. Because every component is different, the rules for
what steps go in this section become much more flexible. That said the Every Time Step
manipulations section can be broken up into four basic categories which proceed in order as
follows.

733
TRNSYS 17 Programmer's Guide

7.3.14.1. Retrieve Stored Values


At each iteration, a call should be made to the getDynamicArrayValueLastTimestep() and
getStaticArrayValue() subroutines to retrieve stored values that are needed in calculations. The
call might look like the following:
...
Call getStaticArrayValue(1,localVar1)
Call getStaticArrayValue(2,localVar2)
localVar3 = getDynamicArrayValueLastTimestep(1)
localVar4 = getDynamicArrayValueLastTimestep(2)
...

7.3.14.2. Retrieve Input Values


Retrieving input values follows much the same pattern as that of retrieving parameter values. The
inputs are available to each Type by means of the getInputValue() AccessFunction. The values
are typically read to local variable names for convenience and then can be checked for validity in
much the same way as parameters.

Our Type201 has five inputs. However, only two of them have restrictions on their values.
Namely, the flow rate should not be negative, and the heater control signal cannot be less than
zero or greater than one. The section that sets the inputs to local variables and checks them
might look like the following.
...
!----------------------------------------------------------------------
!Get the Current Inputs to the Model
tin = getInputValue(1)
flow = getInputValue(2)
igam = JFIX(getInputValue(3)+0.1)
tset = getInputValue(4)
tamb = getInputValue(5)

If (flow < 0.) Call foundBadInput(2,Fatal, &


The input mass flow rate cannot be negative)
If ((igam > 1.).or.(igam < 0.)) Call foundBadInput(3,Fatal, &
The heater control signal must be between 0 and 1.)
If (ErrorFound() ) Return
...
Here the 2 and the 3 in the foundBadInput() call indicate the input number that is the problem in
each case.

7.3.14.3. Perform Calculations


Once all of the input values have been retrieved, the heater performance calculations and control
logic can be performed. Each line in the following code is commented to show its purpose.

!------------------------------------------------------------------------------
!Perform All of the Calculations
If (flow <= 0.0) Then !if the flow rate is zero...
! There is no flow through the heater
Call setOutputValue(1,tin) !set the outlet temperature to the inlet
!temperature
Call setOutputValue(2,0.d0) !set the outlet flow rate to zero.
Call setOutputValue(3,0.d0) !set the auxiliary energy use to zero.
Call setOutputValue(4,0.d0) !set the thermal losses to zero.

734
TRNSYS 17 Programmer's Guide

Call setOutputValue(5,0.d0) !set the energy imparted to the liquid to zero.


Else
! Check inlet temperature and control function
If ((tin < tset).and.(igam == 1)) Then !if the inlet temperature is below
!the set point temperature AND the
!input control signal is set to ON
! Heater on
!calculate the outlet temperature assuming that the heater 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)
Else
! Heater off
tout = tin !set the outlet temperature equal to the inlet temperature
qaux = 0. !set the auxiliary energy required to zero.
qloss = 0. !set the thermal losses to zero.
qfluid = 0. !set the energy imparted to the liquid to zero.
EndIf

7.3.14.4. Set Storage Values


Before exiting the Type at each iteration, it is good practice to update all appropriate storage
variables. Obviously, if one or more of the storage variables is an initial value to be used for all
iterative calculations at a given time step until convergence has been reached then it is not
appropriate to update this value until the End of Timestep call (see sections 7.3.10 and 7.4.3.9
for additional information.

7.3.14.5. Set Outputs


In much the same way that we took the TRNSYS kernel provided parameter and input values and
set them to local variable names, we now have to set the calculated local variables to the
appropriate TRNSYS global output array. The code to do so for Type201 is as follows:
...
! Set outputs
Call SetOutputValue(1,tout)
Call SetOutputValue(2,flow)
Call SetOutputValue(3,qaux)
Call SetOutputValue(4,qloss)
Call SetOutputValue(5,qfluid)
...

7.3.14.6. Return Control


The very last requirement is that a Type return control to the TRNSYS kernel after its
computations are complete.

735
TRNSYS 17 Programmer's Guide

...
Return
End Subroutine Type201
...

736
TRNSYS 17 Programmer's Guide

7.3.15. Complete Code


The entire code of Type201 is reproduced here below as a complete reference.
Subroutine Type6

!------------------------------------------------------------------------------
Use TrnsysConstants
Use TrnsysFunctions
!------------------------------------------------------------------------------

!export this subroutine for its use in external DLLs.


!DEC$ATTRIBUTES DLLEXPORT :: TYPE6

!Variable Declarations
Implicit None !force explicit declaration of local variables
Double Precision Timestep,Time
Integer igam
Double Precision tin !temperature of fluid at heater inlet [C]
Double Precision tout !temperature of fluid at heater outlet [C]
Double Precision tbar !average temperature of fluid in heater [C]
Double Precision tamb !ambient temperature of heater surroundings [C]
Double Precision tset !heater setpoint temperature [C]
Double Precision ton !set temporarily to outlet temperature before check on
! TOUT>TSET [C]
Double Precision qmax !heater capacity [kJ/hr]
Double Precision qaux !required heating rate [kJ/hr]
Double Precision qloss !rate of thermal losses to surroundings [kJ/hr]
Double Precision flow !fluid flow rate through heater [kg/hr]
Double Precision cp !fluid specific heat [kJ/kg.K]
Double Precision htreff !heater efficiency [-]
Double Precision ua !overall loss coefficienct for heater during operation
! [kJ/hr.K]
Double Precision qfluid !rate of energy delivered to fluid [kJ/hr]

!------------------------------------------------------------------------------
!Get the Global Trnsys Simulation Variables
Time = getSimulationTime()
Timestep = getSimulationTimeStep()
!------------------------------------------------------------------------------

!------------------------------------------------------------------------------
!Set the Version Number for This Type
If (getIsVersionSigningTime()) Then
Call SetTypeVersion(17)
Return
EndIf
!------------------------------------------------------------------------------

!------------------------------------------------------------------------------
!Do All of the Last Call Manipulations That May Be Required
If (getIsLastCallofSimulation()) Then
Return
EndIf
!------------------------------------------------------------------------------

!------------------------------------------------------------------------------
!Perform Any "End of Timestep" Manipulations That May Be Required
If (getIsConvergenceReached()) Then
Return

737
TRNSYS 17 Programmer's Guide

EndIf
!------------------------------------------------------------------------------

!------------------------------------------------------------------------------
!Do All of the "Very First Call of the Simulation Manipulations Here
If (getIsFirstCallofSimulation() ) Then
! Tell the TRNSYS Engine How This Type Works
Call setNumberofParameters(4)
Call setNumberofInputs(5)
Call setNumberofDerivatives(0)
Call setNumberofOutputs(5)
Call setIterationMode(1)
Call setNumberStoredVariables(0,0)
! Set the Correct Input and Output Variable Types
Call setInputUnits(1,'TE1')
Call setInputUnits(2,'MF1')
Call setInputUnits(3,'CF1')
Call setInputUnits(4,'TE1')
Call setInputUnits(5,'TE1')
Call setOutputUnits(1,'TE1')
Call setOutputUnits(2,'MF1')
Call setOutputUnits(3,'PW1')
Call setOutputUnits(4,'PW1')
Call setOutputUnits(5,'PW1')
! Return control to the kernel
Return
EndIf
!------------------------------------------------------------------------------

!------------------------------------------------------------------------------
!Do All of the First Timestep Manipulations Here - There Are No Iterations at
! the Intial Time
If (getIsFirstTimestep() ) Then
! Read in the Values of the Parameters from the Input File
qmax = getParameterValue(1)
cp = getParameterValue(2)
ua = getParameterValue(3)
htreff = getParameterValue(4)
! Check the Parameters for Problems
If (qmax < 0.) Call FoundBadParameter(1,'Fatal', &
'The heater capacity must be positive.')
If (cp < 0.) Call FoundBadParameter(2,'Fatal', &
'The fluid specific heat must be positive.')
If (ua < 0.) Call FoundBadParameter(3,'Fatal', &
'The heater UA must be positive.')
If ((htreff < 0.).or.(htreff>1.)) Call FoundBadParameter(4,'Fatal', &
'The heater efficiency must be between 0 and 1.')
If (ErrorFound()) Return
! Set the Initial Values of the Outputs
Call setOutputValue(1,getInputValue(1))
Call setOutputValue(2,getInputValue(2))
Call setOutputValue(3,0.d0)
Call setOutputValue(4,0.d0)
Call setOutputValue(5,0.d0)
! Return control to the kernel
Return
EndIf
!------------------------------------------------------------------------------

!------------------------------------------------------------------------------
!ReRead the Parameters if Another Unit of This Type Has Been Called Last
If (getIsReReadParameters()) Then
qmax = getParameterValue(1)

738
TRNSYS 17 Programmer's Guide

cp = getParameterValue(2)
ua = getParameterValue(3)
htreff = getParameterValue(4)
EndIf
!------------------------------------------------------------------------------

!------------------------------------------------------------------------------
!Get the Current Inputs to the Model
tin = getInputValue(1)
flow = getInputValue(2)
igam = JFIX(getInputValue(3)+0.1)
tset = getInputValue(4)
tamb = getInputValue(5)
!------------------------------------------------------------------------------

!------------------------------------------------------------------------------
!Check the Inputs for Validity
If (flow < 0.) Call foundBadInput(2,Fatal, &
The input mass flow rate cannot be negative)
If ((igam > 1.).or.(igam < 0.)) Call foundBadInput(3,Fatal, &
The heater control signal must be between 0 and 1.)
If (ErrorFound() ) Return
!------------------------------------------------------------------------------

!------------------------------------------------------------------------------
!Perform All of the Calculations Here
If (flow <= 0.0) Then
! No flow
Call SetOutputValue(1,tin)
Call SetOutputValue(2,0.d0)
Call SetOutputValue(3,0.d0)
Call SetOutputValue(4,0.d0)
Call SetOutputValue(5,0.d0)
Else
! Check inlet temperature and control function
If ((tin < tset).and.(igam == 1) ) Then
! Heater on
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)
Else
! Heater off
tout = tin
qaux = 0.
qloss = 0.
qfluid = 0.
EndIf
! Set outputs
Call SetOutputValue(1,tout)
Call SetOutputValue(2,flow)
Call SetOutputValue(3,qaux)
Call SetOutputValue(4,qloss)
Call SetOutputValue(5,qfluid)
EndIf
Return

End Subroutine Type201

739
TRNSYS 17 Programmer's Guide

7.3.16. Implementing Data Storage between Time Steps


Whenever two or more instances of a Type are used in a single simulation, some care must be
taken to make sure that the local variables in a Type have the values that are associated with the
current Unit. For parameters and inputs, this is not a problem; inputs are read at every iteration
and parameters are reread when a new Unit is encountered (see section 7.3.13). Values that are
calculated from parameters are also no problem; the calculations can be redone at each iteration.
What if those calculations are time consuming? It would be nice to be able to do them once and
store the result for each Unit (for each instance of the Type in the simulation) and then to retrieve
the value instead of redoing the calculation. The concept of static storage is used. The Type
programmer uses the setNumberStoredVariables() AccessFunction to reserve space in the global
storage structure, and then uses the AccessFunctions setStaticArrayValue() and
getStaticArrayValue() as appropriate. Refer to section 7.4.4.17.1.1 for additional information.

In another scenario, Types often need to compute a final value based on an initial value but they
need that initial value to be the final value at the previous time step, not the final value at the
previous iteration. Then at the end of the time step, the Type needs to take the final value
calculated at the last iteration and put it into the final value at the last time step spot. This can be
accomplished manually using two static storage spots or it can be accomplished more
automatically using dynamic storage. In this scenario, the Type programmer again uses the
setNumberStoredVariables() AccessFunction to reserve space in the global storage structure, at
the end of each iteration, (s)he then uses the result of a call to the
getDynamicArrayValueLastTimestep() function as the basis of calculations and then uses the
function setDynamicArrayValueThisIteration() to record the calculated result. At the end of the
time step, the TRNSYS kernel takes care of moving the stored variables around so that the Type
always gets the appropriate one. Refer to section 7.4.4.17.1.2 for additional information.

7.3.17. Including your new component in an external


DLL
This step is covered by section 7.5.2, which explains how to create and configure a new project
that will generate a DLL in the UserLib folder.

Note that if you start from the TRNSYS Studio and generate a skeleton for your Type using the
"Export as Fortran" command, the Studio will automatically create a Project with the correct
settings for you.

740
TRNSYS 17 Programmer's Guide

7.4. Reference

7.4.1. Global constants

7.4.1.1. Constants settings limits on TRNSYS simulations

Constant Default Comment

nMaxUnits 1000 Maximum number of units


nMaxEquations 500 Maximum number of equations
nMaxDerivatives 100 Maximum number of derivatives
nMaxOutputs 3000 Maximum number of Outputs
nMaxParameters 2000 Maximum number of Parameters
nMaxStorageSpots 10000 Number of Storage places in the S array
nMaxFiles 300 Maximum number of files that can be opened by TRNSYS
nMaxDescriptions 750 Maximum number of descriptions in an input file
nMaxVariableUnits 750 Maximum number of input variable types in an input file
nMaxLabels 100 Maximum number of labels in an input file
nMaxFormats 100 Maximum number of format statements in an input file
nMaxChecks 20 Maximum number of chek statements in an input file
nMaxCheckCodes 30 Maximum number of outputs per CHECK statement
nMaxUnitConversions 250 Max. number of unit conversions allowed in units.lab file
nMaxUnitTypes 250 Maximum number of unit types allowed in units.lab file
nMaxCardValues 250 Max. nb. of values allowed in one TRNSYS input file card
E.g. a component with 500 parameters would require
nMaxCardValues to be greater or equal to 500

minTimeStep 0. 1 Minimum Simulation Time Step [in hours] (0.1 second)


3600
nMaxTimeSteps 109 Maximum number of time steps in a simulation (1 billion)
nMaxPlottedTimeSteps 525601 Maximum number of time steps plotted by the online plotter
Note: This constant is set in TRNExe. Do not edit
nMaxErrorMessages 1000 Maximum number of standard error messages in TrnsysErrors
Note: If you increase this constant, additional messages
will not be initialized. Add lines in TrnsysErrors.f90

741
TRNSYS 17 Programmer's Guide

7.4.1.2. Constants used for string length

Constant Default Comment

maxPathLength 300 Maximum length of variables containing path- and filenames


Note: DFWIN defines MAX_PATH as 260 but Windows XP
can actually use much longer pathnames.
ATTENTION: TRNExe must be adapted if this constant is
modified. Users should not change maxPathLength

maxFileWidth 1000 Maximum file width, i.e. maximum length of any line in a text
file that must be read from / written to by TRNSYS
maxFileWidth should be >= maxPathLength. This constant is
also used for strings, e.g. error messages

maxDescripLength 25 Maximum length of a variable description, e.g. descriptions for


printers and plotters

maxVarUnitLength 20 Maximum length of units associated with variables

maxEqnNameLength 20 Maximum length of variable names in equations

maxLabelLength 300 Maximum length of labels. Some labels are file- and
pathnames so a suggested value is maxLabelLength =
maxPathLength

maxMessageLength 800 Maximum length of notices, warnings and error messages


Error messages and any text printed on the same line must
fit within the maximum file width (maxFileWidth).
It is recommended to set maxMessageLength to
maxFileWidth-200

742
TRNSYS 17 Programmer's Guide

7.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 7.4.4.17.

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 Fortran-
written Types can access them more easily through an "use" statement: use TrnsysConstants.
Those access functions are provided for non-Fortran Types.

7.4.2.1. function getMaxDescripLength( )


[ maxDescripLength is also available through "use TrnsysConstants" ]

An integer function that returns the maximum allowable length of a variable description, e.g. input
descriptions for printers and plotters. The value of the maximum allowable length of a variable
description can be set in the TrnsysConstants file. If the value is modified, the trnlib.dll must then
be recompiled in order for the change to take effect.

Example Usage
INTEGER DescripLen
...
DescripLen = getMaxDescripLength ()

7.4.2.2. function getmaxFileWidth( )


[ maxFileWidth is also available through "use TrnsysConstants" ]

An integer function that returns the maximum allowable width (in characters or columns) of line in
any text file that must be read by TRNSYS. This includes both the input file and external data files
read by the DynamicData utility routine. The value of the maximum allowable line length can be
set in the TrnsysConstants file. If the value is modified, the trnlib.dll must then be recompiled in
order for the change to take effect.

Example Usage
INTEGER FileWidth
...
FileWidth = getmaxFileWidth()

7.4.2.3. function getMaxLabelLength( )


[ maxLabelLength is also available through "use TrnsysConstants" ]

An integer function that returns the maximum allowable length (in characters) of variables that
contain pathnames and filenames. The value of the maximum allowable label length can be set in
the TrnsysConstants file. If the value is modified, the trnlib.dll must then be recompiled in order
for the change to take effect.

743
TRNSYS 17 Programmer's Guide

Example Usage
INTEGER LabLen
...
LabLen = getMaxLabelLength()

7.4.2.4. function getMaxPathLength( )


[ maxPathLength is also available through "use TrnsysConstants" ]

An integer function that returns the maximum allowable length (in characters) of pathnames. The
value of the maximum allowable path length can be set in the TrnsysConstants file. If the value is
modified, the trnlib.dll must then be recompiled in order for the change to take effect.

Example Usage
INTEGER PathLen
...
PathLen = getMaxPathLength()

7.4.2.5. function getnMaxStorageSpots( )


[nMaxStorageSpots is also available through "use TrnsysConstants" ]

An integer function that returns the maximum total number of storage spots that may be
requested in a given simulation. Note that this function is used by the setStorageSize subroutine
and that therefore it is not necessary for the Type programmer to check whether the required
number of storage spots for his/her Type will exceed the maximum allowable number of storage
spots. The value of the maximum allowable number of storage spots can be set in the
TrnsysConstants file. If the value is modified, the trnlib.dll must then be recompiled in order for
the change to take effect.

Example Usage
INTEGER StorSpots
...
StorSpots = getnMaxStorageSpots()

7.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 06, 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

744
TRNSYS 17 Programmer's Guide

7.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

7.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()

7.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()

7.4.2.10. function getFormat(i,j )


A character function that returns the jth format statement associated with unit i. The length of the
returned string is maxFileWidth. For example, in certain modes, Type9 takes a single Format
statement.. To access the format of the data file line that is to be read, Type9 contains the
following code:

Example Usage
Use TrnsysConstants, Only: maxFileWidth
...
Character (len=maxFileWidth) :: myFormat
...

745
TRNSYS 17 Programmer's Guide

myFormat = getFormat(INFO(1),1)
...
! Print or read using myFormat
write(luPrint,myFormat) ... variables to be printed

7.4.2.11. function getLabel(i,j)


A character function that returns the jth label of unit i. The length of the returned string is
maxLabelLength. For example, Type66 takes two LABELs; the first is the location of the EES
executable, the second is the name and location of the EES file that is to be solved. To access
these labels, Type66 contains the following code:

Example Usage:
Use TrnsysConstants, Only: maxLabelLength

Integer ThisInstance,currentUnit
Character (len=maxLabelLength) EESLocation,EESFile(10)
...
currentUnit = getCurrentUnit()
EESLocation = getLabel(currentUnit,1)
EESFile(ThisInstance) = getLabel(currentUnit,2)

7.4.2.12. function getListingFileLogicalUnit( )


An integer function that returns the logical unit of the TRNSYS list file.

Example Usage
Integer LUW
...
LUW = getListingFileLogicalUnit()

7.4.2.13. function getLUfileName (i)


A character function that returns the name of the file corresponding to the logical unit i. If the file
logical unit number has not been assigned, it returns an error message.

External files such as output reports or performance data can be referenced in the input in two
ways. If the external file is associated with a logical unit number by means of an ASSIGN
statement, the TRNSYS kernel will automatically open the external file. External components then
do not have to open their external files and do not even need to know the external files name; all
they need know is the logical unit of the file (usually passed as a parameter). If the external file is
associated with a logical unit number by means of a DESIGNATE statement, the TRNSYS kernel
will not open the external file and it is left to the component to do so. The getLUFileName()
function is then needed to retrieve the name and location of the external file associated with the
logical unit (usually passed to the component as a parameter).

Example Usage
Integer LU
Character (len=maxLabelLength) fileName
...
fileName = getLUfileName(LU)

746
TRNSYS 17 Programmer's Guide

7.4.2.14. function getMinimumTimestep( )


Double precision function that returns the minimum allowable TRNSYS time step. The minimum
allowable TRNSYS time step can be set in the TrnsysConstants file. If the value is modified, the
trnlib.dll must then be recompiled in order for the change to take effect.

Example Usage
Double Precision minStep
...
minStep = getMinimumTimestep()

7.4.2.15. function getNextAvailableLogicalUnit( )


Integer function that returns an available logical unit number and logs the logical unit number in a
global list of assigned logical unit numbers. The getNextAvailableLogicalUnit function can be
used to find an available logical unit number for temporary files, scratch files, or for data files
accessed by components that do not require a logical unit number among their list of parameters.

Example Usage
LU = getNextAvailableLogicalUnit()
! Write some data to a temporary file
open(UNIT=LU,FILE='TmpFileForMyType.tmp',status='new')
write(LU,*) ... Data to be written ...
close(LU,status='keep')

7.4.2.16. function getnMaxIterations( )


An integer function that returns the maximum allowable number of iterations in one time step
before the simulation continues with the current values and a warning is issued. The maximum
allowable number of iterations can be set in a Limit statement (or in the Studio's Control Cards).

Example Usage
Integer maxIter
...
maxIter = getnMaxIterations()

7.4.2.17. function getnMaxWarnings( )


An integer function that returns the maximum allowable number of warnings written to the
simulation list and log files before the simulation stops in error. The maximum allowable number
of warnings can be set in a Limit statement (or in the Studio's Control Cards).

Example Usage
Integer maxWarns
...
maxWarns = getnMaxWarnings()

7.4.2.18. function getnTimeSteps( )


An integer function that returns the total number of time steps in the simulation being run.

Example Usage

747
TRNSYS 17 Programmer's Guide

Integer nSteps
...
nSteps = getnTimeSteps()

7.4.2.19. function getTimeStepNumber


An integer function that returns the time step number in the current simulation being run.

Example Usage
Integer StepNumber
...
StepNumber = getTimeStepNumber()

7.4.2.20. function getNumberOfErrors( )


An integer function that returns the total number of errors that have occurred thus far in the
simulation.

Example Usage
Integer NumErrs
...
NumErrs = getNumberOfErrors()

7.4.2.21. function getNumberOfWarnings( )


An integer function that returns the total number of warnings that have occurred thus far in the
simulation.

Example Usage
Integer numWarns
...
numWarns = getNumberofWarnings()

7.4.2.22. function getNumericalSolver( )


An integer function that returns the Solver used by TRNSYS. More information on TRNSYS
solvers can be found in Volume 06, TRNEdit (check the section on the Solver statement).
Handling of discrete control signals is different with Solver 0 and Solver 1. See Type 2 for a n
example.

Example Usage
Integer TRNSolver
...
If (TRNSolver == 0) Then
... Do things required for successive substitution
Else

748
TRNSYS 17 Programmer's Guide

... Do things required for Powell's solver


EndIf

7.4.2.23. function getSimulationTime()


Double precision function that returns the hour of the year at which the current simulation time.

Example Usage
Double Precision TIME
...
TIME = getSimulationTime()

7.4.2.24. function getSimulationStartTime( )


Double precision function that returns the hour of the year at which the simulation began.

Example Usage
Double Precision TIME0
...
TIME0 = getSimulationStartTime()

7.4.2.25. function getSimulationStartTimeV15( )


Double precision function that returns the hour of the year at which the simulation began. The
returned value is the original start time in a Version 15 deck file (Start time is changed by
TRNSYS 16 to adapt it to the new start time definition)

Example Usage
Double Precision TIME0V15
...
TIME0V15 = getSimulationStartTimeV15()

7.4.2.26. function getSimulationStopTime( )


Double precision function that returns the hour of the year at which the simulation is set to end.

Example Usage
Double Precison TFINAL
...
TFINAL = getSimulationStopTime()

7.4.2.27. function getSimulationTimeStep( )


Double precision function that returns the simulation time step (in hours).

Example Usage
Double Precision DELT
...
DELT = getSimulationTimeStep()

749
TRNSYS 17 Programmer's Guide

7.4.2.28. function getTrnsysExeDir( )


A character function that returns the path in which the TRNSYS executable (TrnExe.exe) is
located (default = "C:\Program Files\Trnsys16\Exe"). The length of the returned string is
maxPathLength.

Example Usage
Use TrnsysConstants, Only: maxPathLength

Character (len= maxPathLength) ExeLoc


...
ExeLoc = getTrnsysExeDir()

7.4.2.29. function getTrnsysInputFileDir( )


A character function that returns the path in which the input file being run is contained. 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) DeckLoc


...
DeckLoc = getTrnsysInputFileDir()

7.4.2.30. function getTrnsysRootDir( )


A character function that returns the path to the root TRNSYS directory (default = "C:\Program
Files\Trnsys16 "). The length of the returned string is maxPathLength.

Example Usage
Use TrnsysConstants, Only: maxPathLength

Character (len=maxPathLength) RootDir

RootDir = getTrnsysRootDir()

7.4.2.31. function getTrnsysUserLibDir( )


A character function that returns the path and directory in which the debug mode and release
mode subdirectories, which in turn contain loadable user dlls are located (default = "C:\Program
Files\Trnsys17\UserLib"). The length of the returned string is maxPathLength.

Example Usage
Use TrnsysConstants, Only: maxPathLength

Character (len=maxPathLength) UsrLibDir


...
UsrLibDir = getTrnsysUserLibDir()

750
TRNSYS 17 Programmer's Guide

7.4.2.32. function getTrnsysDebugLibDir( )


A character function that returns the path and directory in which all of the debug mode loadable
user dlls are located (default = "C:\Program Files\Trnsys17\UserLib\DebugDLLs"). NOTE: when
compiled in debug mode, the TRNDll.dll will search for loadable user dlls in this directory. The
length of the returned string is maxPathLength.

Example Usage
Use TrnsysConstants, Only: maxPathLength

Character (len=maxPathLength) DbgLibDir


...
DbgLibDir = getTrnsysDebugLibDir()

7.4.2.33. function getTrnsysReleaseLibDir( )


A character function that returns the path and directory in which all of the release mode loadable
user dlls are located (default = "C:\Program Files\Trnsys17\UserLib\ReleaseDLLs"). NOTE: when
compiled in release mode, the TRNDll.dll will search for loadable user dlls in this directory. The
length of the returned string is maxPathLength.

Example Usage
Use TrnsysConstants, Only: maxPathLength

Character (len=maxPathLength) RlsLibDir


...
RlsLibDir = getTrnsysReleaseLibDir()

7.4.2.34. function getVariableDescription(i,j)


String function that returns the variable descriptor for the jth variable of Unit i. Variable descriptors
are strings that give the "name" of the variable in printers and other output devices. The length of
the returned string is maxDescripLength.

Example usage
Character (len=maxDescripLength) :: columnHeader
...
Do j = 1, nVariables
columnHeader = getVariableDescription(INFO(1),j)
... write column header to a file, etc...
EndDo

7.4.2.35. function getVariableUnit(i,j)


String function that returns the variable unit string for the jth variable of Unit i. Variable descriptors
are strings that give the "name" of the variable in printers and other output devices. The length of
the returned string is maxVarUnitLength.

Example usage
Character (len=maxVarUnitLength) :: varUnitString
...

751
TRNSYS 17 Programmer's Guide

Do j = 1, nVariables
varUnitString = getVariableDescription(INFO(1),j)
... write units to a file, etc...
EndDo

7.4.2.36. function getVersionNumber( )


Integer function that returns the TRNSYS major version number (i.e, if the version number is
XX.Y, it will return XX). This function is primarily useful in allowing for backward compatibility
between versions of a component. Say, for example that a Type required 14 parameters in an
input file written for TRNSYS version 16 but requires 15 parameters in an input file written for
TRNSYS version 17. The Type programmer could access the getVersionNumber function and
know whether the input file being run was written for TRNSYS version 16 or 17, and could read
the corresponding parameter list.

Example Usage
Integer VERSNUM
...
VERSNUM = getVersionNumber()

7.4.2.37. function getMinorVersionNumber( )


Integer function that returns the TRNSYS minor version number (if the version number is XX.Y, it
will return Y). This function is primarily useful in allowing for backward compatibility between
versions of a component, when changes have occurred between minor release versions. For
example, a Type required 14 parameters in an input file written for TRNSYS version 17.0 but
requires 15 parameters in an input file written for TRNSYS version 17.1. The Type programmer
could access the getMinorVersionNumber function and know whether the input file being run was
written for TRNSYS version 17.0 or 17.1, and could read the corresponding parameter list.

Example Usage
Integer minorVersNum
...
minorVersNum = getMinorVersionNumber()

7.4.2.38. function LogicalUnitIsOpen(LU)


Logical function that returns true if the Logical unit has been assigned in the deck file and opened
by TRNSYS.

Example usage
Logical :: luOk
Integer :: lu
...
lu = nint(par(1))
luOk = LogicalUnitIsOpen(lu)
If (luOk) Then
... !it's OK to print to / read from the file
Else
... !Probably an error in parameters
EndIf

752
TRNSYS 17 Programmer's Guide

7.4.2.39. function getTimeReport()


Logical function that returns the value of the global variable TIME_REPORT. This global variable
is set to false by default, but may be set to true in the input file.

Example usage
Logical :: timereport
...
timereport = getTimeReport()

7.4.2.40. function getConnectedOutputNumber(i,j)


An integer function that returns the output number connected to the jth input of Unit i. When using
the Powells Method solver (SOLVER 1), you should call the getConnectedOutputNumberS1()
function instead of this one.

Example usage
Integer:: getConnectedOutputNumber
Integer:: i,j
...
getConnectedOutputNumber = getConnectedOutputNumber (i,j)

Related Functions: getConnectedOutputNumberS1()

7.4.2.41. function getConnectedOutputNumberS1(i,j)


An integer function that returns the output number connected to the jth input of Unit i. When using
the Successive Substitution solver (SOLVER 0), you should call the
getConnectedOutputNumber() function instead of this one.

Example usage
Integer:: getConnectedOutputNumber
Integer:: i,j
...
getConnectedOutputNumber = getConnectedOutputNumberS1(i,j)

Related Functions: getConnectedOutputNumber()

7.4.2.42. function getConnectedUnitNumber(i,j)


An integer function that returns the unit connected to jth input of Unit i. When using the Powells
Method solver (SOLVER 1), you should use the similar function getConnectedUnitNumberS1().

Example usage
Integer:: getConnectedUnitNumber
Integer:: i,j
...
getConnectedOutputNumber = getConnectedUnitNumber(i,j)

Related Functions: getConnectedUnitNumberS1()

753
TRNSYS 17 Programmer's Guide

7.4.2.43. function getConnectedUnitNumberS1(i,j)


An integer function that returns the unit connected to jth input of Unit i. When using the
Successive Substitution solver (SOLVER 0), you should use the similar function
getConnectedUnitNumber().

Example usage
Integer:: getConnectedUnitNumber
Integer:: i,j
...
getConnectedOutputNumber = getConnectedUnitNumberS1(i,j)

Related Functions: getConnectedUnitNumber()

7.4.2.44. function getConnectedTypeNumber(i,j)


An integer function that returns the type number of the unit connected to jth input of Unit i. When
using the Powells Method solver (SOLVER 1), you should use the similar function
getConnectedTypeNumberS1().

Example usage
Integer:: getConnectedTypeNumber
Integer:: i,j
...
getConnectedTypeNumber = getConnectedTypeNumber(i,j)

Related Functions: getConnectedTypeNumberS1()

7.4.2.45. function getConnectedTypeNumberS1(i,j)


An integer function that returns the type number of the unit connected to jth input of Unit i. When
using the Successive Substitution solver (SOLVER 0), you should use the similar function
getConnectedTypeNumber().

Example usage
Integer:: getConnectedTypeNumber
Integer:: i,j
...
getConnectedTypeNumber = getConnectedTypeNumberS1(i,j)

Related Functions: getConnectedTypeNumber()

7.4.2.46. function getConnectedVariableType(i,j)


A character function that returns the three-character description of the type of variable that is
connected to jth input of Unit i. This information is stored the array OCHECK. When using the
Powells Method solver (SOLVER 1), you should use the similar function
getConnectedVariableTypeS1().

Example usage

754
TRNSYS 17 Programmer's Guide

Character*3:: getConnectedVariableType
Integer:: i,j
...
getConnectedVariableType = getConnectedVariableType (i,j)

Related Functions: getConnectedVariableTypeS1()

7.4.2.47. function getConnectedVariableTypeS1(i,j)


A character function that returns the three-character description of the type of variable that is
connected to jth input of Unit i. This information is stored the array OCHECK. When using the
Successive Substitution solver (SOLVER 0), you should use the similar function
getConnectedVariableType().

Example usage
Character*3:: getConnectedVariableType
Integer:: i,j
...
getConnectedVariableType = getConnectedVariableTypeS1(i,j)

Related Functions: getConnectedVariableType()

7.4.2.48. function getConnectedVariableUnit(i,j)


A character function that returns the corresponding units (e.g., kJ/kg-h) of the variable that is
connected to jth input of Unit i. When using the Powells Method solver (SOLVER 1), you should
use the similar function getConnectedVariableUnitS1().

Example usage
Character (len=maxVarUnitLength):: getConnectedVariableUnit
Integer:: i,j
...
getConnectedVariableUnit = getConnectedVariableUnit(i,j)

Related Functions: getConnectedVariableUnitS1()

7.4.2.49. function getConnectedVariableUnitS1(i,j)


A character function that returns the corresponding units (e.g., kJ/kg-h) of the variable that is
connected to jth input of Unit i. When using the Successive Substitution solver (SOLVER 0), you
should use the similar function getConnectedVariableUnit().

Example usage
Character (len=maxVarUnitLength):: getConnectedVariableUnit
Integer:: i,j
...
getConnectedVariableUnit = getConnectedVariableUnitS1(i,j)

Related Functions: getConnectedVariableUnit()

755
TRNSYS 17 Programmer's Guide

7.4.2.50. function getCurrentUnit()


Integer function that returns the current (or most recently called) Unit number. This return value is
the first spot in the INFO( ) array.

Example usage
Integer:: currentUnit
...
currentUnit = getCurrentUnit()

7.4.2.51. function getCurrentType()


Integer function that returns the current (or most recently called) Type number. This return value
is the second spot in the INFO( ) array.

Example usage
Integer:: currentType
...
currentType = getCurrentType()

7.4.2.52. function getIsLastCallofSimulation()


Integer function that returns a 1 if the TRNSYS kernel is calling the Types the very last time
before the end of the simulation. The return value corresponds to the condition when the 8th spot
in the INFO( ) array is equal to -1.

Example usage
Integer :: lastCall
Logical :: drinkUp,orderAnother
...
lastCall = getIsLastCallofSimulation()
If (lastCall == 1) Then
drinkUp = .true.
Else
orderAnother = .true.
EndIf

7.4.2.53. function getIsEndOfTimestep()


Integer function that returns a 1 if the TRNSYS kernel is calling the Types at the current time step
one final time after convergence has been reached (or after it has determined that convergence
cannot be reached) but before the start of the next time step. The return value corresponds to the
condition when the 13th spot in the INFO( ) array is equal to 1.

Example usage(s)
Integer :: endOfTimestep
...
endOfTimestep = getIsEndOfTimestep()

~or~

756
TRNSYS 17 Programmer's Guide

If ( getIsEndOfTimestep() ) Then
...
EndIf

NOTE: in the second usage example, it is not necessary to declare a variable; FORTRAN
understands the use of an integer function that returns a 1 or 0 in place of a logical test.

7.4.2.54. function getIsFirstCallofSimulation()


Integer function that returns a 1 if the TRNSYS kernel is calling the Types before time has begun
to advance This is the call at which components perform their initializations: setting where they
should be called in the calling sequence (using the setIterationMode() function), setting how many
parameters (using the setNumberofParameters() function), inputs (using the setNumberofInputs()
function), and derivatives (using the setNumberOfDerivatives() function) they expect, reserving
space in the output array (using the setNumberofOutputs() function) and in the various storage
structures (using the setNumberStoredVariables() function). The return value corresponds to the
condition when the 7th spot in the INFO( ) array is equal to -1.

Example usage(s)
Integer :: firstCall
...
firstCall = getIsFirstCallofSimulation()

~or~

If (getIsFirstCallofSimulation()) Then
...
EndIf

NOTE: in the second usage example, it is not necessary to declare a variable; FORTRAN
understands the use of an integer function that returns a 1 or 0 in place of a logical test.

7.4.2.55. function getIsStartTime ()


Integer function that returns a 1 if the TRNSYS kernel is calling the Types before time has begun
to advance. This is the call at which components read their parameter values and check them for
validity.

Example usage(s)
Integer :: readPars
...
readPars = getIsStartTime()

~or~

If (getIsStartTime()) Then
...
EndIf

NOTE: in the second usage example, it is not necessary to declare a variable; Fortran
understands the use of an integer function that returns a 1 or 0 in place of a logical test.

757
TRNSYS 17 Programmer's Guide

7.4.2.56. function getIsReReadParameters()


Integer function that returns a 1 if the current Type needs to reread its parameters (usually
because multiple instances of the same Type exist in the same TRNSYS project). There is no
need to recheck parameter values for validity since they were already checked previously.
Variables that are calculated based only on parameter values must be recalculated unless they
are stored globally using the setNumberStoredVariables() function.

Example usage(s)
Integer :: rereadPars
...
rereadPars = getIsReReadParameters()

~or~

If (getIsReReadParameters()) Then
...
EndIf

NOTE: in the second usage example, it is not necessary to declare a variable; FORTRAN
understands the use of an integer function that returns a 1 or 0 in place of a logical test.

Related Functions: none

7.4.2.57. function getIsVersionSigningTime()


Integer function that returns 1 if the current Type needs to set which coding standard it uses. The
coding standard is set using the setTypeVersion() function. The return value corresponds to the
7th spot of the INFO() array being set to -2.

Example usage(s)
Integer :: versSign
...
versSign = getIsVersionSigningTime()

~or~

If (getIsVersionSigningTime()) Then
...
EndIf

NOTE: in the second usage example, it is not necessary to declare a variable; FORTRAN
understands the use of an integer function that returns a 1 or 0 in place of a logical test.

Related Functions: none

7.4.2.58. function getDynamicArrayValueLastTimestep(j)


A double precision function that returns the jth value from the dynamic double-precision global
storage structure. Note that this value is the one that was calculated at the end of the previous
time step. It will not change until the end of the current time step, at which point it will be replaced
by the most recent value that was stored using a call to the setDynamicArrayValueThisIteration()

758
TRNSYS 17 Programmer's Guide

function. Refer to section 7.4.4.17 for a discussion of the proper use of this function and those
related to it.

Example usage(s)
Double Precision :: value
Integer :: j
...
value = getDynamicArrayValueLastTimestep(j)

Related Functions: setDynamicArrayValuethisIteration(:), setNumberStoredVariables(:,:)

7.4.2.59. function getStaticArrayValue(j)


A double precision function that returns the jth value from the static double-precision global
storage structure. Refer to section 7.4.4.17 for a discussion of the proper use of this function and
those related to it.

Example usage(s)
Double Precision :: value
Integer :: j
...
value = getStaticArrayValue(j)

Related Functions: setStaticArrayValue(:), setNumberStoredVariables(:,:)

7.4.2.60. function getOverallIteration(i)


An integer function that returns the number of times that the current Unit has been called thus far
in the simulation. The return value corresponds to the value carried in the 8th spot of the INFO()
array.

Example usage(s)
Integer :: overallIteration,i
...
overallIteration = getOverallIteration(i)

Related Functions: setTimestepIteration(), getTimestepIteration()

7.4.2.61. function getTimestepIteration()


An integer function that returns the number of times that the current Unit has been called thus far
in the current time step. The return value corresponds to the value carried in the 7th spot of the
INFO() array.

Example usage(s)
Integer :: iteration,i
...
iteration = getTimestepIteration(i)

Related Functions: setTimestepIteration(), getOverallIteration()

759
TRNSYS 17 Programmer's Guide

7.4.2.62. function getInputValue(i)


A double precision function that returns the current value of the current Types ith input.

Example usage(s)
Double Precision :: inputValue1, inputValue2
...
inputValue1 = getInputValue(1)
inputValue2 = getInputValue(2)

7.4.2.63. function getOutputValue(i)


A double precision function that returns the last calculated value of the current Units ith output.

Example usage(s)
Double Precision :: outputValue1, outputValue2
...
outputValue1 = getOutputValue(1)
outputValue2 = getOutputValue(2)

7.4.2.64. function getParameterValue(i)


A double precision function that returns the value of the current Units ith parameter.

Example usage(s)
Integer :: parValue1
Double Precision :: parValue2, parValue3
...
parValue1 = jfix(getParameterValue(1)+0.1)
parValue2 = getParameterValue(2)
parValue3 = getParameterValue(3)

7.4.2.65. function getNumberOfParameters()


An integer function that returns the number of parameters provided for the current Unit in the
input file being run. Note that if a user provided the incorrect number of parameters in the input
file, then this function will not return the correct number of parameters; it will return the number of
parameters that the user specified. The return value corresponds to the 4th value in the INFO()
array.

Example usage(s)
Integer :: nPars
...
nPars = getNumberOfParameters()

Related Functions: setNumberofParameters(), getParameterValue()

760
TRNSYS 17 Programmer's Guide

7.4.2.66. function getNumberOfDerivatives()


An integer function that returns the number of derivatives provided for the current Unit in the input
file being run. Note that if a user provided the incorrect number of derivatives in the input file, then
this function will not return the correct number of derivatives; it will return the number of
derivatives that the user specified. The return value corresponds to the 5th value in the INFO()
array.

Example usage(s)
Integer :: nDerivs
...
nDerivs = getNumberOfDerivatives()

Related Functions: setNumberofDerivatives()

7.4.2.67. function getNumberOfInputs()


An integer function that returns the number of inputs provided for the current Unit in the input file
being run. Note that if a user provided the incorrect number of inputs in the input file, then this
function will not return the correct number of inputs; it will return the number of inputs that the
user specified. The return value corresponds to the 3rd value in the INFO() array.

Example usage(s)
Integer :: nInputs
...
nInputs = getNumberOfInputs()

Related Functions: setNumberofInputs(), getInputValue()

7.4.2.68. function getNumberOfOutputs()


An integer function that returns the number of outputs that have been reserved by the current Unit
for the current Unit. Note that it is the Types responsibility to reserve its own output space using
a call to the setNumberOfOutputs() function discussed in section 7.4.2.77. The return value
corresponds to the 6th value in the INFO() array.

Example usage(s)
Integer :: nOutputs
...
nOutputs = getNumberOfOutputs()

Related Functions: setNumberofOutputs(), getOutputValue()

7.4.2.69. function getPreviousControlState(i)


An integer function that returns the last calculated value of the ith spot in the ICNTRL() array.
Please refer to section 7.4.7 for additional information on the use of the ICNTRL() array.

Example usage(s)

761
TRNSYS 17 Programmer's Guide

Integer :: lastState,i
...
lastState = getPreviousControlState(i)

7.4.2.70. function getNumericalSolution(i)


An double precision function that returns the value of the ith spot in the T() array. This return value
is the numerical solution to the ith derivative value set by the Type in the DTDT() array. Refer to
section 7.4.5 for additional information on solving differential equations numerically.

Example usage(s)
Double Precision :: T(:)
Integer :: i,j
...
T(j) = getNumericalSolution(i)
Related Functions: setNumberofDerivatives(), setNumericalDerivative(), getNumericalDerivative()

7.4.2.71. function closeFileIVF(lu)


An integer function that closes the file associated with a specified logical unit number. The
function always returns a value of 1. This function is typically used by Types that are located in an
external DLL (i.e. not in the TRNDll) but which need to read an external file that has been
associated with the Unit by means of an ASSIGN statement. With certain Fortran compilers, since
the file has already been opened by the TRNDll, the external DLL is prevented from also opening
it. This function gives the user the ability to tell the TRNSYS kernel to close the file. The calling
Type would then open the file itself and read the data. NOTE: files that are intended to be read
(and interpolated) by the InterpolateData (formerly DynamicData) routine do not need to make
use of this function since it is a TRNSYS kernel routine that will be performing the file read.

Example usage(s)
Integer :: dummyReturn,logicalUnit
...
dummyReturn = closeFileIVF(logicalUnit)

7.4.2.72. function getNFiles(unitNum)


An integer function that returns the number of external files that are associated with a particular
Unit through the use of the FILES keyword. Note this function does not return the number of files
associated with a particular Unit by use of an ASSIGN statement.

Example usage(s)
Integer :: nFiles,currentUnit
...
nFiles = getNFiles(currentUnit)

7.4.2.73. function getExtFilePath(unitNum,fileNum,extFilePath)


An integer function that returns the length of the string variable needed to contain the path and
name of an external file that is associated with a particular Unit through the use of the FILES

762
TRNSYS 17 Programmer's Guide

keyword. Note this function does not return the path and name of files associated with a particular
Unit by use of an ASSIGN statement. The function also returns a string variable containing the
name and location of the requested file.

Example usage(s)
Use TrnsysConstants, Only :: maxPathLength
Integer :: currentUnit,length,i
Character (len=maxPathLength) :: fileLocation
...
length = getExtFilePath(currentUnit,i,extFilePath)

7.4.2.74. function getTypeVersion()


An integer function that returns the coding standard set for the current Unit by the current Unit.
Note that it is the Types responsibility to set the coding standard for which it was written using a
call to the setTypeVersion() function discussed in section 7.4.2.81. The return value is the 12th
spot of the INFO() array.

Example usage(s)
Integer :: typeVersion
...
typeVersion = getTypeVersion()

Related Functions: setTypeVersion()

7.4.2.75. function getNumericalDerivative(i)


A double precision function that returns the ith numerically solved derivative for the current Unit. In
TRNSYS versions 16 and prior, this value would be the ith spot in the DTDT() array. Refer to
section 7.4.5 for additional information on solving differential equations numerically in TRNSYS.
NOTE that only very rarely would a Type ever call this function. Normally a Type sets the
derivatives and calls the getNumericalSolution() function to obtain the results. The
getNumericalDerivative() function is included for cases in which it is not the TRNSYS kernel but
another engine (such as Matlab or the TRNSYS Studio) that calls the Type directly.

Example usage(s)
Double Precision :: localDTDT(:)
Integer :: i,j
...
DTDT(i) = getNumericalDerivative(j)

Related Functions: setNumberofDerivatives(), setNumericalDerivative(), getNumericalSolution()

7.4.2.76. setOutputValue(i,Value)
Once a Type has computed an output value, this function is called in order to send that value
back to the TRNSYS kernel for global storage.

Example usage(s)
Integer :: i

763
TRNSYS 17 Programmer's Guide

Double Precision :: value


...
Call setOutputValue(i,value)

Related Functions: getOutputValue(), setNumberofOutputs()

7.4.2.77. setNumberofOutputs(i)
A function used by Types to inform the TRNSYS kernel of how many OUTPUTS they will be
setting. The kernel reserves this many spots in the global output array structure. This function is
typically called once during the first call manipulations section.

Example usage(s)
Integer :: i
...
Call setNumberofOputputs(i)

Related Functions: getNumberofOutputs()

7.4.2.78. setNumberofDiscreteControls(i)
A function used by Types to inform the kernel of the number of discrete control variables required
by the current Unit. This function is called during the first call manipulations and sets the 11th
spot of the current Units INFO() array. Refer to section 7.4.3.7 for additional information. This
function is only called by those components that make use of the Powells Method solver. Refer
to the SOLVER keyword description in the 06-TRNEdit manual for additional information on the
Powells Method solver.

Example usage(s)
Integer :: i
...
Call setNumberofDiscreteControls(i)

Related Functions: setDesiredDiscreteControlState()

7.4.2.79. setDesiredDiscreteControlState(i,j)
A function used by controller components that make use of the Powells Method solver. At each
iteration, these components should use this function call to tell the TRNSYS kernel what their
control decision would be given the current inputs to the controller. The Powells Method solver
will not actually make a control decision until the end of the time step. In this function call, i
designates the ith controller for the current Unit (see section 7.4.2.78 for information on how to set
the number of discrete controllers for a given Unit) while j denotes the desired state for the ith
controller. As is standard in TRNSYS, a controller state of 0 indicates that the controlled device
should be off while a controller state of 1 indicates that the controlled device should be on.

Example usage(s)
Integer :: i ,nControllers
...
! turn OFF all of the controllers
Do i=1,nControlers

764
TRNSYS 17 Programmer's Guide

Call setDesiredControlState(i,0)
EndDo

Related Functions: setNumberofDiscreteControls()

7.4.2.80. setIterationMode(i)
A function that sets where a Type will be placed in the Type calling sequence. Various options
are available: the Type is a normal (iterative) component, the Type is an integrator and should be
called after convergence has been reached, the Type is a printer and should be called after the
integrators, etc. Refer to section 7.4.3.5 for additional information. This function is typically called
once during the first call manipulations section.

Example usage(s)
Integer :: i
...
Call setIterationMode(i)

Related Functions: none

7.4.2.81. setTypeVersion(i)
A function that sets the coding standard set for the current Unit. Note that it is the Types
responsibility to set the coding standard for which it was written by calling this function.

Example usage(s)
Integer :: typeVersion
...
If (getIsVersionSigningTime() ) Then
Call setTypeVersion(typeVersion)
Return
EndIf

Related Functions: getTypeVersion()

7.4.2.82. setNumberofParameters(i)
This function is called once by each Type during the first call manipulations. It is used to tell the
TRNSYS kernel how many Parameter values the Type expects there to be in the input file.

Example usage(s)
Integer :: i
...
If (getIsFirstCallofSimulation() ) Then
...
Call setNumberofParameters(i)
...
EndIf

Related Functions: getNumberofParameters(), getParameterValue()

765
TRNSYS 17 Programmer's Guide

7.4.2.83. setNumberofInputs(i)
This function is called once by each Type during the first call manipulations. It is used to tell the
TRNSYS kernel how many Input values the Type expects there to be in the input file.

Example usage(s)
Integer :: i
...
If (getIsFirstCallofSimulation() ) Then
...
Call setNumberofInputs(i)
...
EndIf

Related Functions: getNumberofInputs(), getInputValue()

7.4.2.84. setNumberofDerivatives(i)
This function is called once by each Type during the first call manipulations. It is used to tell the
TRNSYS kernel how many Derivative values the Type expects there to be in the input file.

Example usage(s)
Integer :: i
...
If (getIsFirstCallofSimulation() ) Then
...
Call setNumberofDerivatives(i)
...
EndIf

Related Functions: getNumberofDerivatives(), getNumericalDerivative()

7.4.2.85. foundBadParameter(i,Severity,Message)
This function is used to write a message concerning a bad Parameter value to the TRNSYS *.log
and *.lst files. It replaces a call to the TYPECK() subroutine with an IOPT value of 4 (refer to
section 7.4.4.20). The three arguments to the foundBadParameter() function are the index
number of the Parameter whose value has been found to be bad, the severity of the error (notice,
warning, or fatal), and a text string containing the message that should be printed. Note that the
action taken by the kernel (whether the simulation stops or not) is dictated by the selected
severity of the error. Once all Parameters have been checked and any bad ones have been
flagged by a call to the foundBadParameter() function, the ErrorFound() function should be called
to exit the Type properly if required. This function need only be called once during the first
timestep manipulations call. In the following example, the first Parameter is read to a local
variable called parValue, the value of which must be positive.

Example usage(s)
Integer :: i
Double Precision :: parValue
...
parValue = getParameterValue(i)
...
If (parValue < 0.d0) Call foundBadParameter(i,fatal, &

766
TRNSYS 17 Programmer's Guide

the value of this parameter cannot be negative)


...
If (ErrorFound() ) Return

Related Functions: none

7.4.2.86. foundBadInput(Input,Severity,Message)
This function is used to write a message concerning a bad Input value to the TRNSYS *.log and
*.lst files. It replaces a call to the TYPECK() subroutine with an IOPT value of 3 (refer to section
7.4.4.20). The three arguments to the foundBadInput() function are the index number of the Input
whose value has been found to be bad, the severity of the error (notice, warning, or fatal), and a
text string containing the message that should be printed. Note that the action taken by the kernel
(whether the simulation stops or not) is dictated by the selected severity of the error. Once all
Inputs have been checked and any bad ones have been flagged by a call to the foundBadInput()
function, the ErrorFound() function should be called to exit the Type properly if required. Unlike
the foundBadParameter() function, this function should be called at every iteration since Input
values change with time. In the following example, the first Input is read to a local variable called
inpValue, the value of which must be positive.

Example usage(s)
Integer :: i
Double Precision :: inpValue
...
inpValue = getInputValue(i)
...
If (inpValue < 0.d0) Call foundBadInput(i,fatal, &
the value of this input cannot be negative)
...
If (ErrorFound() ) Return

Related Functions: none

7.4.2.87. setInputUnits(i,String)
This function registers a three character code as the units of the ith Input of the current Unit. It
replaces a DATA statement setting the YCHECK array and a direct call to the RCHECK()
subroutine. The function must be called once per Input during the first call manipulations; it does
not need to be called at each step of the simulation. The TRNSYS kernel registers all of the three
character codes for all connected Inputs and Outputs in the simulation and warns the user if any
Input-Output connections have mismatched units. Refer to the Type57 section of the 04-
Mathematical Reference manual for a complete list of allowable three-character codes. Refer to
section 7.4.4.12 of this manual for information about the functionality of the RCHECK()
subroutine. In the following example, the component has two Inputs: a temperature and a mass
flow rate. Their units are designated by the three-character codes for temperature in degrees C
(TE1) and mass flow rate in kilograms per hour (MF1).

Example usage(s)
If (getIsFirstCallOfSimulation) Then
...
Call setInputUnits(1,TE1)
Call setInputUnits(2,MF1)
...
EndIf

767
TRNSYS 17 Programmer's Guide

Related Functions: setOutputUnits()

7.4.2.88. setOutputUnits(i,String)
This function registers a three character code as the units of the ith Output of the current Unit. It
replaces a DATA statement setting the OCHECK array and a direct call to the RCHECK()
subroutine. The function must be called once per Output during the first call manipulations; it
does not need to be called at each step of the simulation. The TRNSYS kernel registers all of the
three character codes for all connected Inputs and Outputs in the simulation and warns the user if
any Input-Output connections have mismatched units (for example if a power output is connected
to a pressure input). Refer to the Type57 section of the 04-Mathematical Reference manual for a
complete list of allowable three-character codes. Refer to section 7.4.4.12 of this manual for
information about the functionality of the RCHECK() subroutine. In the following example, the
component has thee Outputs: two temperatures and a mass flow rate. Their units are designated
by the three-character codes for temperature in degrees C (TE1), temperature in degrees K
(TE3) and mass flow rate in kilograms per hour (MF1).

Example usage(s)
If (getIsFirstCallOfSimulation) Then
...
Call setOutputUnits(1,TE1)
Call setOutputUnits(2,TE3)
Call setOutputUnits(3,MF1)
...
EndIf

Related Functions: setInputUnits()

7.4.2.89. setNumericalDerivative(i,derVal)
This function sets the ith numerical derivative to derVal. Calling this function sets the ith spot in the
global DTDT() array to derVal; the TRNSYS kernel will use its innate ability to solve mathematical
problems iteratively to compute corresponding values of the T() array. The T() array values are
then accessed by means of a call to the getNumericalSolution

Example usage(s)
Integer :: i
Double Precision :: derVal
...
Call setNumericalDerivative(i,derVal)

Related Functions: setNumberOfDerivatives(), getNumberOfDerivatives(),


getNumericalSolution(), getNumericalDerivative(), setNumericalSolution()

7.4.2.90. writeToList(message)
A function that allows Types to write directly to a simulations list file (*.lst) without a call to the
Messages() subroutine (refer to section 7.4.4.9 for additional information about the Messages()
routine). Note that a message written directly to the *.lst file will NOT be written to the *.log file.

768
TRNSYS 17 Programmer's Guide

Example usage(s)
Use TrnsysConstants, Only :: maxMessageLength
...
Character (len=maxMessageLength) :: messageText
...
Call writeToList(messageText)

Related Functions: none

7.4.2.91. addExternalFile(LUN, FileName)


A function that adds an additional file to the list of files that the kernel opens and then asks the
kernel to open that file. The kernel automatically opens various files. These include the *.lst, *.log,
and those files that are referenced by a Type through an ASSIGN statement. Note: the files that
are referenced by a Type through a DESIGNATE statement are not opened by the kernel. For
additional information about the ASSIGN and DESIGNATE statements, refer to the 06-TRNEdit
manual.

A call to the addExternalFile() function is structured as follows:

Example usage(s)
Use TrnsysConstants, Only :: maxPathLength
...
Integer :: lu
Character (len=maxPathLength) :: pathAndFileName
...
Call addExternalFile(lu,pathAndFileName)

Related Functions: none

7.4.2.92. readNextChar(lun)
A function that reads the next line of the external file associated with logical unit number LUN.
The function returns a 1 if it succeeded, a 2 if it got to the end of the file, and a 3 if it failed.
Somewhat incomprehensibly, it does not return the line that it read. The person writing the access
function comments that this is necessary in cases where a Type is directly called from an
external program such as the Studio or Matlab. It seems a bit pointless to the person writing this
documentation, however.

Example usage(s)
Integer :: lun
...
Call readNextChar(lun)

Related Functions: none

7.4.2.93. Access Functions for (really, really) Expert Users


The TRNSYS kernel contains a number of access functions that are only used under very rare
circumstances because using them incorrectly can have significant adverse effects on your
simulation. Situations in which these access functions may be useful include calling Types from

769
TRNSYS 17 Programmer's Guide

some other software tool (i.e. something other than the TRNSYS kernel). In many cases, the
following access functions would be called not by a user-written Type but by a user-written engine
that is intended to call Types.

initTrnsys(deckVersionNumber)

A function that sets a number of kernel variables that need to exist before a Type can be called
directly from an external program (ie not from the TRNSYS kernel).

Example usage(s)
Integer :: i
...
Call initTrnsys(i)

Related Functions: none

setTimestepIteration(i)

A function that resets the current iteration number for the current time step. Under normal
circumstances, the TRNSYS kernel continues calling all of the components in the system until it
decides that convergence has been reached. Each time the kernel recalls the component set, it
increments a counter that keeps track of the number of iterations that have gone by in the current
time step. This function supersedes the kernel-set iteration number for the current Unit (ie not for
all Units). At the next iteration, the kernel will reset the value for the current Unit so that it matches
that of all the rest.

Example usage(s)
Integer :: i
...
Call setTimestepIteration(i)

Related Functions: getTimestepIteration(), getOverallIteration()

setSimulationStartTime(newStart)

A function that resets the simulation start time, superseding the value that was read from the
TRNSYS input file.

Example usage(s)
Double Precision :: newStart
...
Call setSimulationStartTime(newStart)

Related Functions: getSimulationStartTime()

setSimulationStopTime(newStop)

A function that resets the simulation stop time, superseding the value that was read from the
TRNSYS input file.

770
TRNSYS 17 Programmer's Guide

Example usage(s)
Double Precision :: newStop
...
Call setSimulationStopTime(newStop)

Related Functions: getSimulationStopTime()

setSimulationTimeStep(newStep)

A function that resets the simulation time step, superseding the value that was read from the
TRNSYS input file.

Example usage(s)
Double Precision :: newStep
...
Call setSimulationTimeStep(newStep)

Related Functions: getSimulationTimeStep()

setSimulationTime(SimTime)

A function that resets the simulation time, superseding the value that was set by the kernel.

Example usage(s)
Double Precision :: simTime
...
Call setSimulationTimeStep(simTime)

Related Functions: getSimulationTime()

setCurrentUnit(UnitNum)

A function that resets the current Unit. Many other access functions (particularly the get
functions) access information about the current Unit. Normally, the kernel decides what the
current Unit is (based on where it is in the calling order and its iterations at the current time step).
This function supersedes the kernel-set Unit number, changing it to the one set as the integer
argument to the function.

Example usage(s)
Integer :: currentUnit
...
Call setCurrentUnit(currentUnit)

Related Functions: getCurrentUnit()

setCurrentType(TypeNum)

A function that resets the current Type. Many other access functions (particularly the get
functions) access information about the current Type. Normally, the kernel decides what the

771
TRNSYS 17 Programmer's Guide

current Type is (based on where it is in the calling order and its iterations at the current time
step). This function supersedes the kernel-set Tnit number, changing it to the one set as the
integer argument to the function.

Example usage(s)
Integer :: currentType
...
Call setCurrentType(currentType)

Related Functions: getCurrentType()

setInputValue(i,InValue)

A function that sets the ith input value of the current Unit to InValue. Under normal circumstances,
Types use the getInputValue() function to obtain the current values of their inputs from the
TRNSYS kernel. The setInputValue() function would be used if some engine other than the
TRNSYS kernel were directing the simulation.

Example usage(s)
Integer :: i
Double Precision :: newInputValue
...
Call setInputValue(i,newInputValue)

Related Functions: getInputValue()

setNumericalSolution(i,tValue)

A function that sets the ith value of the current Units T() array to tValue. Under normal
circumstances, Types use the getNumericalSolution() function to obtain the current values of their
T() array from the TRNSYS kernel. The setNumericalValue() function would be used if some
engine other than the TRNSYS kernel were solving numerical differential equations in place of
the TRNSYS kernel.

Example usage(s)
Integer :: i
Double Precision :: tValue
...
Call setNumericalSolution(i,tValue)

Related Functions: getNumericalSolution()

setPreviousControlState(i,controlState)

A function that sets the ith value of the current Units ICNTRL() array to controlState. Under
normal circumstances, Types use the getPreviousControlState() function to obtain the current
values of their ICNTRL() array from the TRNSYS kernel. The setPreviousControlState() function
would be used if some engine other than the TRNSYS kernel were determining the Powells
Method control states.

Example usage(s)

772
TRNSYS 17 Programmer's Guide

Integer :: i,controlState
...
Call setInputValue(i,controlState)

Related Functions: getPreviousControlState()

resetErrors()

A function that resets the value of the TRNSYS kernels IERROR variable. IERROR is global
variable containing the number of errors encountered in the simulation

Example usage(s)
...
Call resetErrors()
...

Related Functions: none

setParameterValue(i,Value)

A rarely used function that sets the ith parameter of the current Unit to a particular value. This
function is rarely used because under normal circumstances, the parameter values for all Units
are set in the input file, are read by the kernel and are made available to be read by the Types.
Hardly ever would a Type set a parameter value as this would supersede information in the input
file.

Example usage(s)
Integer :: i
Double Precision :: value
...
Call setParameterValue(i,value)

Related Functions: getParameterValue()

getLABEL2(i,j, outLabel)

This function is similar to the getLabel() function discussed in section 7.4.2.11. It is used by
external programs that call TRNSYS Types. getLabel2() is a character function that returns the jth
label of unit i. The length of the returned string is maxLabelLength. For example, Type66 takes
two LABELs; the first is the location of the EES executable, the second is the name and location
of the EES file that is to be solved. To access these labels, Type66 contains the following code:

Example Usage:
Use TrnsysConstants, Only: maxLabelLength

Integer ThisInstance,currentUnit
Character (len=maxLabelLength) EESLocation,EESFile(10)
...
currentUnit = getCurrentUnit()
EESLocation = getLabel(currentUnit,1)
EESFile(ThisInstance) = getLabel(currentUnit,2)

773
TRNSYS 17 Programmer's Guide

7.4.3. The INFO array Typical calling sequence


The INFO array is an integer array of 15 values. It contains a great deal of information about the
UNIT that is currently being called by the kernel. In TRNSYS version 16 and earlier, the contents
of the INFO array was passed to each Type through the argument list. With the release of
TRNSYS 17, however the information was accessed by Types when needed through the use of
Access Functions. The contents of the INFO array for a given unit are given in Table 7.4.2.93-1
(see text for detailed explanations).

Table 7.4.2.93-1: INFO array contents

INFO(n) Role
1 Unit number
2 Type number
3 Number of Inputs in the input file (.dck) for this Unit
4 Number of Parameters in the input file (.dck) for this Unit
5 Number of Derivatives in the input file (.dck) for this Unit
6 Number of outputs (set by the Type)
7 Number of iterative calls to this Unit in the current time step. Special values: -1, -2
8 Total number of calls to this unit. Special values: -1
9 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 Used in storage management for TRNSYS 15 Types (not used by TRNSYS 16
Types)
11 Indicates number of discrete control variables
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 Reserved for future use
15 Reserved for future use

7.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.

774
TRNSYS 17 Programmer's Guide

7.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.

7.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 7.4.3.3-1.

Table 7.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)
0 First call in the current time step for this Unit.
1 First iterative call (second call) in the current time step for this Unit
2 Second iterative call (third call) in the current time step for this Unit
+n nth iterative call ((n+1)th call) in the current time step for this Unit

7.4.3.4. 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
7.4.3.4-1.

Table 7.4.3.4-1: INFO(8) values

INFO(8) Role
1 Very first call in the simulation (version signing call)
2 Initialization call (INFO(7) = -1)
3 Initial conditions at Time = Start time (no iteration for this time step)
4 First call of the first time step (Time = Start time + Time step)
5 Second call of the first time step (Time = Start time + Time step)
6 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.

775
TRNSYS 17 Programmer's Guide

7.4.3.5. INFO(9) and Types calling sequence


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 7.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 7.4.3.5-1: INFO(9) values

INFO(9) Role
0 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 The Type's outputs depend upon the passage of time and the Type must therefore
(default) be called at least once every time step even if the values of inputs do not change
3 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.
4 Standard integrators
5 Standard printers
2 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)

776
TRNSYS 17 Programmer's Guide

Initialization call (INFO(7) = -1)


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)

7.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 7.4.4.17.

7.4.3.7. INFO(11)
INFO(11) sets the number of discrete control variables in the Type. It should only be set to a non-
zero 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 06, TRNEdit manual.

7.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).

7.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.

7.4.3.10. Typical calling sequence for an iterative Type


Table 7.4.3.10-1 shows the time and INFO array values for an iterative Type in a typical
simulation. Please note the following:
INFO(1:5) are set by TRNSYS before calling the Type from information in the input (.dck) file
and should not be modified by the Type. For that reason they are omitted in the table.
It is assumed that convergence is reached after 2 iterations (after the 3rd call in a time steps)
for all time steps.
Start, Stop and Step are respectively the simulation start time, stop time and time step. nO is
the number of outputs set by the Type.
S is the value set by the Type for INFO(9).
Values that change are in bold and especially meaningful values have a dark background.

777
TRNSYS 17 Programmer's Guide

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 7.4.3.10-1: Typical INFO calling sequence for an iterative Type

INFO element
Call description Time
6 7 8 9 10 11 12 13
Version signing call Start 0 -2 1 1 -10 0 0 0
Initialization call Start 0 -1 2 1 -10 0 16 0
Start (initial conditions) Start nO 0 3 S 0 0 16 0
st st
1 step, 1 call Start+Step nO 0 4 S 0 0 16 0
st nd st
1 step, 2 call (1 iter.) Start+Step nO 1 5 S 0 0 16 0
st rd nd
1 step, 3 call (2 iter.) Start+Step nO 2 6 S 0 0 16 0
st
1 step, post-convergence Start+Step nO 3 7 S 0 0 16 1
nd st
2 step, 1 call Start+2*Step nO 0 8 S 0 0 16 0
nd nd st
2 step, 2 call (1 iter.) Start+2*Step nO 1 9 S 0 0 16 0
nd rd nd
2 step, 3 call (2 iter.) Start+2*Step nO 2 10 S 0 0 16 0
nd
2 step, post-convergence Start+2*Step nO 3 11 S 0 0 16 1
etc. S 0 0 16
st
Last step, 1 call Stop nO 0 nCalls-3 S 0 0 16 0
nd st
Last step, 2 call (1 iter.) Stop nO 1 nCalls-2 S 0 0 16 0
rd nd
Last step, 3 call (2 iter.) Stop nO 2 nCalls-1 S 0 0 16 0
Last step, post-converg. Stop nO 3 nCalls S 0 0 16 1
Very last call (after "OK") Stop nO 0 -1 S 0 0 16 1

778
TRNSYS 17 Programmer's Guide

7.4.4. Utility subroutines

7.4.4.1. CallProgram (Calling External Programs)

GENERAL DESCRIPTION

In order to allow calls to external programs, a utility subroutine named CallProgram was been
added to TRNSYS with the release of version 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 is a logical variable that determines whether TRNSYS will wait
for the second program to finish running or not.
-If BWAIT = .TRUE., then TRNSYS does not proceed until the
second program is finished and closed.
-If BWAIT = .FALSE., then TRNSYS proceeds once the second
program is done initializing but still running.
PROCHAND is the Windows process handle for the new program. This is a
value returned by the CALLPROGRAM routine.
THRDHAND is the Windows thread handle for the new program. This is a
value returned by the CALLPROGRAM routine.
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 == 0) THEN
Write(CHCKWHY,*) GETLASTERROR()
EndIf
...
See the source code of Type 66 (CALL EES MODELS) for an example of the use of CallProgram.

779
TRNSYS 17 Programmer's Guide

7.4.4.2. Enclosure_17 (formerly ENCLOSURE and ENCL)

GENERAL DESCRIPTION

The utility routine Enclosure_17 calculates 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_17 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 Enclosure_17 are also double precision. In TRNSYS versions 15.x and below, Enclosure_17
was known simply as ENCL, which was a single precision routine. In TRNSYS version 16.x, a
double precision version called ENCLOSURE was written. ENCLOSURE and ENCL were
retained for backwards compatibility and every effort should be made to use the double precision
Enclosure_17 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 :: currentUnit, currentType
...
Call Enclosure_17(SPAR,WPAR,FV,currentUnit,currentType)
where

SPAR a double precision array of 10 values containing the 10 zone


geometry parameters described in the TYPE 19 documentation
(parameters 2-11 of geometry Mode 1).
WPAR a double precision array dimensioned to 54, containing the
complete list of window or door geometry parameters described
in the TYPE 19 section for geometry Mode 1.
FV a double precision array containing the view factors for all
surfaces as calculated by the subroutine.
currentUnit (integer) the Unit number of the component calling the
Enclosure_17 subroutine.
currentType (integer) the Type number of the component calling the
Enclosure_17 subroutine.
The subroutines ENCLOSURE and ENCL did not require the currentUnit or currentType
arguments but DID require the following:
INFO the calling TYPE's INFO array.
N is the corresponding line number to jump to if the subprogram is
present.
Subroutine Enclosure_17 outputs a table of the view factors between surfaces. The surface
numbers are as specified in the SPAR array.

MATHEMATICAL DESCRIPTION

Subroutine Enclosure_17 utilizes function subroutine View_Factors 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.

780
TRNSYS 17 Programmer's Guide

Consider the general case of m windows located on a surface i and n windows on a surface j as
shown in Figure 7.4.4.2-1.

jW Wj2 Wj3
j1
W i3
W i2
W i1 W jn

W im

Figure 7.4.4.2-1

In general, the view factor between i and j is

Fi j = Fi ( j + W ji + ... + W jn ) Fi (W jk )
n
Eq. 7.4.4-1
k =1

where

Fi ( j +W j1 + ... +W jn ) =
(A j )
+ AW j1 + ... + AW jn F( j +W j1 + ...+W jn ) i
Eq. 7.4.4-2
Ai

m
F( j +W j1 + ...+W jn ) i = F( j +W j1 + ...+W jn ) ( i +Wi1 + ... +Wim ) F( j +W j1 + ...+W jn ) Wik Eq. 7.4.4-3
k =1

AW jk F(W jk ) i
Fi W jk = Eq. 7.4.4-4
Ai

m
FW jk i = FW jk ( i +Wi1 + ...+Wim ) FW jk Wil Eq. 7.4.4-5
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 subscript.

781
TRNSYS 17 Programmer's Guide

7.4.4.3. Fluid_Properties (formerly FLUID_PROPS and FLUIDS)


The double precision utility routine called Fluid_Properties is used to calculate the thermodynamic
properties of various refrigerants based on correlations. In TRNSYS version 15.x and earlier, the
routine was known as FLUIDS. In TRNSYS v16.x, a double precision version was added called
FLUID_PROPS. Arguments to the Fluid_Properties routine should be declared in the calling
Type as DOUBLE PRECISION variables. Given two state properties, the Fluid_Properties routine
will return the complete state of the refrigerant. A call to Fluid_Properties is of the form
Integer :: nRef,iType,iFlagr
Double Precision :: prop(9)
Character (len=2) :: units
...
Call Fluid_Properties(units,prop,nRef,iType,iFlagr)
where

UNITS (character) two character variable denoting unit system to be


employed by the fluids routine; SI for metric units and EN for
english units
PROP double precision array holding the two known thermodynamic
properties of the refrigerant in question upon entry and the
complete state of the refrigerant upon return from the
Fluid_Properties routine. This array must be dimensioned to 9 in
the routine that calls Fluid_Properties. Each location in this array
is described below:
PROP(1) temperature of refrigerant (F, C)
PROP(2) pressure of refrigerant (psi, MPa)
PROP(3) enthalpy of refrigerant (Btu/lbm, kJ/kg)
PROP(4) entropy of refrigerant (Btu/lbm R, kJ/kg K)
PROP(5) quality (0 < x < 1)
PROP(6) specific volume (ft3/lbm, m3/kg)
PROP(7) internal energy (Btu/lbm, kJ/kg)
PROP(8) dynamic viscosity (lbm/ft hr, N s/m2)
PROP(9) thermal conductivity (Btu/hr ft R, kJ/hr m K)
nREF an integer variable denoting the refrigerant to be analyzed.
Available refrigerants are listed along with the required nREF
code number:
R-11 (11)
R-12 (12)
R-13 (13)
R-14 (14)
R-22 (22)
R-114 (114)
R-134A (134)
R-500 (500)

782
TRNSYS 17 Programmer's Guide

R-502 (502)
AMMONIA (717)

ITYPE integer variable denoting which two properties are supplied as


known properties. ITYPE = 10* PROP indicator 1 + PROP
indicator 2 (12 to 98)
IFLAGR an integer variable returning the error messages from the
Fluid_Properties call:
0 - no error found, calculations completed
1 - error found, calculations could not be completed
The subroutines FLUID_PROPS and FLUIDS also required the following:
*N the corresponding line number to jump to if the subprogram is
present.
An example illustrating the use of the Fluid_Properties routine is shown below. In the example,
two inputs (temperature and quality) are read and are placed in the PROP() array. The
Fluid_Properties routine is called. When Fluid_Properties returns, the example checks to make
sure that no errors were reported by Fluid_Properties by calling an Access Function called
ErrorFound( ) (refer to section 7.4.2.6 for more information). If errors were detected, execution of
the Type that called Fluid_Properties 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.
Use TrnsysFunctions
...
Character (len=2) :: units
Double Precision :: prop(9),temp,quality,pressure,enthalpy
Integer :: nRef,iFlag
...
units = SI !SI units are desired.
nRef = 12 !Refrigerant R12
...
temp = getInputValue(1)
quality = getInputValue(2)
...
prop(1) = temp
prop (5) = quality
Call Fluid_Properties(units,prop,nRef,15,iFlag)
If (ErrorFound()) Return
...
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.

Enthalpies for all other refrigerants are based on the reference state: enthalpy equal to zero at
0C

783
TRNSYS 17 Programmer's Guide

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 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.

784
TRNSYS 17 Programmer's Guide

7.4.4.4. getIncidentRadiation
With TRNSYS releases prior to version 17.0, numerous Types were available for processing solar
radiation data. Historically data was read by Type9 and Type16 was the radiation processor of
choice. With the release of TRNSYS 15, standard format weather data such as TMY2, IWEC,
and EnergyPlus weather became more widely available (read by Type89 but still processed by
Type16). Users and developers alike expressed frustration with constantly remaking the
connections between Types 89 and 16. Late in the TRNSYS 16 version cycle, two Types were
introduced to combine the data reading and solar radiation processing tasks (Type109 and
Type15). The various radiation processing sections of all these Types began to diverge;
enhancements were made in one version and not another, bugs were fixed here and not there.
With the release of TRNSYS 17, all of the solar radiation processing functionality was moved to a
TRNSYS kernel routine called getIncidentRadiation. A call to getIncidentRadiation is of the form:
Integer :: hMode,trackMode,tiltMode,iSolarTime,iErrRad
Double Precision :: time,radInput(6),rhoG,slope,azimuth,lat,elev,shift,solConst
Double Precision :: td1,td2,solar(16)
...
Call getIncidentRadiation(time,hMode,radInput,rhoG,slope,azimuth,trackMode, &
tiltMode,lat,elev,shift,iSolartime,solConst,td1,td2,solar,iErrRad)
where

time (double precision) the current simulation time [hrs]


hMode (integer) the horizontal radiation mode indicates what input data
is provided as the basis for tilted surface algorithms (1: total
horizontal only. 2: total horizontal, ambient temperature and
humidity, 3: horizontal beam and horizontal diffuse, 4: total
horizontal and direct normal, 5: total horizontal and diffuse
horizontal, 6: direct normal and diffuse horizontal)
radInput (double precision array) contains the six values that are used as
inputs to the tilted surface radiation calculation algorithms.
NOTE: not all 6 values are used during each call, only those
corresponding to the selected hMode.
radInput(1) total solar radiation on the horizontal [kJ/h.m2]
radInput(2) beam solar radiation on the horizontal [kJ/h.m2]
radInput(3) diffuse solar radiation on the horizontal [kJ/h.m2]
radInput(4) direct normal solar radiation [kJ/h.m2]
radInput(5) ambient temperature [C]
radInput(6) ambient relative humidity [%]
rhoG (double precision) ground reflectance [0..1]
slope (double precision) slope of the surface for which calculations are
being performed. Slope is measured up from the horizontal.
[deg]
azimuth (double precision) azimuth of the surface for which calculations
are being performed. The sign convention is 0: facing the
equator, 180: facing away from the equator, -90: east, 90: west
[deg]
trackMode (integer) surface tracking mode. (1: fixed surface (no tracking), 2:
the surface rotates about a vertical axis, 3: the surface rotates

785
TRNSYS 17 Programmer's Guide

about a fixed (user-defined) axis, 4: the surface 2-axis tracks


such that the beam radiation is always normal to the surface.)
tiltMode (integer) the desired tilted surface radiation processing algorithm
(1: Isotropic Sky model, 2: Hay and Davies model, 3: Reindl
model, 4: Perez 1988 model. 5: Perez 1999 model.)
lat (double precision) the latitude of the location for which the solar
radiation calculations are being performed. [deg]
elev (double precision) the elevation of the location for which the solar
radiation calculations are being performed. [m]
shift (double precision) the shift between local and solar time. The
shift is calculated by the equation shift = Lst - Lloc where Lst is the
standard meridian for the local time zone, and Lloc is the
longitude of the location in question. Longitude angles are
positive towards West, negative towards East. [deg]
iSolarTime (integer) flag indicating whether the input data being passed is in
solar time or local time. (-1: data is in solar time, 1: data is in
local time) [-1/1]
solConst (double precision) the solar constant [kJ/h.m2]
td1 (double precision) the time of the last solar radiation data point
[hr]
td2 (double precision) the time of the next solar radiation data point
[hr]
solar (double precision array) contains the sixteen values that are
returned by getIncidentRadiation.
solar(1) extraterrestrial solar [kJ/h.m2]
solar(2) solar zenith angle [deg]
solar(3) solar azimuth angle [deg]
solar(4) slope of the tilted surface [deg]
solar(5) azimuth of the tilted surface [deg]
solar(6) incidence angle of beam radiation on the tilted surface [deg]
solar(7) total solar radiation on the horizontal [kJ/h.m2]
solar(8) beam solar radiation on the horizontal [kJ/h.m2]
solar(9) diffuse solar radiation on the horizontal [kJ/h.m2]
solar(10) total solar radiation on the tilted surface [kJ/h.m2]
solar(11) beam solar radiation on the tilted surface [kJ/h.m2]
solar(12) diffuse solar radiation on the tilted surface [kJ/h.m2]
solar(13) ground reflected solar radiation on the tilted surface [kJ/h.m2]
solar(14) isotropic sky diffuse radiation on the tilted surface (part of
solar(12) sky diffuse) [kJ/h.m2]
solar(15) circumsolar diffuse radiation on the tilted surface (part of
solar(12) sky diffuse) [kJ/h.m2]
solar(16) horizon brightening diffuse radiation on the tilted surface (part of
solar(12) sky diffuse) [kJ/h.m2]

786
TRNSYS 17 Programmer's Guide

iErrRad (integer) error condition returned by getIncidentRadiation (1:


illegal tracking mode specified, 2: sunup/sundown time issue, 3:
horizontal beam calculation greater than extraterrestrial radiation
on the horizontal surface, 4: time step/data time step
inconsistency, 5: horizontal diffuse calculation greater than
extraterrestrial radiation on the horizontal surface, 6: total
horizontal calculation greater than extraterrestrial radiation on
the horizontal surface, 7: total horizontal calculation greater than
extraterrestrial radiation on the horizontal surface due to sum of
beam and diffuse, ratios used to set beam and diffuse, 8: direct
normal radiation greater than solar constant (hdn=SC), 9:
calculated value of beam radiation on the horizontal is greater
than provided total horizontal radiation (hb=hhor), 10: calculated
value of beam radiation on the horizontal is less than 0, set
horizontal diffuse to total horizontal and horizontal beam to zero,
11: illegal tilt mode specified, 12: illegal latitude specified, 13:
illegal shift value specified, 14: illegal ground reflectance mode
specified.

GENERAL DESCRIPTION

Solar insolation data is generally recorded at one hour intervals and on a horizontal surface. In
some TRNSYS simulations, estimates of radiation at time intervals other than one hour are
required. This routine interpolates solar radiation data, calculates several quantities related to the
position of the sun, and estimates insolation on a surface of either fixed or variable orientation.

There are several possible methods of interpolating radiation data. One fairly simple method is to
linearly interpolate hourly data to obtain estimates of radiation over shorter time intervals. This
approach, which was used in TRNSYS prior to Version 10.1, has several drawbacks. The most
readily apparent problem is that positive radiation values are produced before sunrise and after
sunset. If sunrise is at 6:30 a.m., then an hourly radiation data file may have a value of zero at
6:00 and 40 watts/m2 at 7:00. Linear interpolation will give 10 watts/m2 at 6:15, fifteen minutes
before sunrise. This problem is compounded by the fact that the ratio of beam radiation on a tilted
surface to that on a horizontal, Rb, may become very large near sunrise and sunset. If the
estimate of radiation on the horizontal is too large near sunrise, the calculated radiation on a tilted
surface will be immense. Thus, the current radiation processor uses the curve for extraterrestrial
radiation to interpolate radiation data. This seems to relieve the problems encountered with linear
interpolation.

Total radiation on a tilted surface is usually required for solar energy system simulations. The
models used in this subroutine to estimate the total tilted surface radiation require knowing the
division of total horizontal radiation into its beam and diffuse components. If only total horizontal
radiation is measured, correlations are provided to estimate the beam or diffuse radiation on a
horizontal surface. The horizontal components are then projected onto the tilted surface. The
getIncidentRadiation routine has several options for calculating the horizontal radiation
components as well as estimating the total radiation on a tilted surface.

NOMENCLATURE
AI - Anisotropy index
a/c weighted circumsolar solid angle
E Factor accounting for the eccentricity of the earth's orbit
f Modulating factor for Reindl titlted surface model
F 1' Reduced brightness coefficient (circumsolar)

787
TRNSYS 17 Programmer's Guide

F 2' Reduced brightness coefficient (horizon brightening)


Io Extraterrestrial radiation
Ion Extraterrestrial radiation at normal incidence
Ib Beam radiation on horizontal surface
Ibn Beam radiation at normal incidence
IbT Beam radiation on tilted surface
Id Diffuse radiation on horizontal surface
Idn Direct normal beam radiation
IdT Diffuse radiation on tilted surface
I Total radiation on a horizontal surface
IT Total radiation on a tilted surface
IgT Ground reflected radiation on a tilted surface
kT Ratio of total radiation on a horizontal surface to extraterrestrial radiation
Lloc Longitude of a given location
Lst Standard meridian for time zone
n Day of year of the start of the simulation
Rb Ratio of beam radiation on tilted surface to beam on horizontal
Rd Ratio of diffuse radiation on tilted surface to diffuse on horizontal
Rr Ratio of reflected radiation on tilted surface to total radiation on horizontal
rh relative humidity [%]
Sc Solar constant
SHFT Shift in solar time relative to the nominal time of data reading
Ta Ambient temperature
t1 Time of start of time step
t2 Time of end of time step
td1 Time of last data reading
td2 Time of next data reading
Solar altitude angle (90 - qz)
Slope of surface, positive when tilted in the direction of the azimuth specification
Slope of tracking axis
Solar declination angle
Sky brightness parameter
Sky clearness parameter
Azimuth angle of surface; angle between the projection of the normal to the surface
into the horizontal plane and the local meridian. (facing equator = 0, west positive,
east negative)
' Azimuth angle of axis; angle between the projection of the axis line onto the
horizontal plane and local meridian. (Same sign convention as for )
s Solar azimuth angle
Angle of incidence of beam radiation on surface
Solar zenith angle
Z
g Ground reflectance
Latitude
Mean hour angle of time step (0 at noon, mornings negative)
1 Hour angle at start of time step, or sunrise hour angle if sunrise occurs during time
step
2 Hour angle at end of time step, or sunset hour angle if sunset occurs during time step.

d1 Hour angle at start of data


d2 Hour angle at end of data

MATHEMATICAL DESCRIPTION

788
TRNSYS 17 Programmer's Guide

In practice, most solar radiation data are actually integrated totals of instantaneous
measurements. The TYPE 9 data reader interpolates data linearly. This is not appropriate for
radiation (see above): Whatever solar radiation data is passed to this routine should NOT be
interpolated. The getIncidentRadiation routine uses the total radiation between times td1 and td2
that is passed to it. Then, by summing integrals if necessary, the total radiation between hour
angles d1 and d2 is found. The hour angles d1 and d2 are chosen so that d1 1 and d2
2. Here 1 is the angle of the start of the time step and 2 is the angle of the end of the time
step. If sunrise or sunset occurs during the time step, then the portion of the time step when the
sun is below the horizon is ignored.

The total extraterrestrial radiation between hour angles and is found from:



Io |
= Sc E (cos cos cos + sin sin) d Eq. 7.4-6

I|

d2
Given d1, a reasonable estimate of the actual insolation over the time step is

Io |

2
I| d2
1 = I|d1 *
2 1
Eq. 7.4-7
Io |d2
d1
This calculation scales integrated radiation data using the ratio of extraterrestrial radiation over
the time step to extraterrestrial radiation over the period which corresponds to the data. Since
other TRNSYS routines require the rate of solar radiation, the integrated radiation is converted to
the average rate over the time step.

7.4.4.4.1.1. Horizontal Radiation Mode

The getIncidentRadiation routine has five methods for obtaining beam and diffuse radiation on a
horizontal surface from total radiation on a horizontal surface data. Horizontal Radiation Modes 1
and 2 are based on the relationships developed by Reindl (9a). Both modes provide estimates of
the diffuse fraction of the total horizontal radiation (Id/I). Mode 1 is a reduced form of the full
correlation given in Mode 2. Mode 1 uses the clearness index and the solar altitude angle to
estimate the diffuse fraction. The correlation is given by the following equations:

Interval: 0 kT 0.3 ; Constraint: Id/I 1.0

Id/I = 1.020 - 0.254 kT + 0.0123 sin () Eq. 7.4-8

Interval: 0.3 < kT < 0.78 ; Constraint: 0.1 Id/I 0.97

Id/I = 1.400 - 1.749 kT + 0.177 sin () Eq. 7.4-9

Interval: 0.78 < kT; Constraint: 0.1 Id/I

Id/I = 0.486 kT - 0.182 sin () Eq. 7.4-10

789
TRNSYS 17 Programmer's Guide

Horizontal Radiation Mode 2 estimates the diffuse fraction as a function of the clearness index,
solar altitude angle, ambient temperature, and relative humidity. The correlation is given by the
following equations:

Interval: 0 kT 0.3 ; Constraint: Id/I 1.0

Id/I = 1.000 - 0.232 kT + 0.0239 sin () - 0.000682 Ta + 0.0195 (rh/100) Eq. 7.4-11

Interval: 0.3 < kT < 0.78 ; Constraint: 0.1 Id/I 0.97

Id/I = 1.329 - 1.716 kT + 0.267 sin () - 0.00357 Ta + 0.106 (rh/100) Eq. 7.4-12

Interval: 0.78 < kT; Constraint: 0.1 Id/I

Id/I = 0.426 kT - 0.256 sin () + 0.00349 Ta + 0.0734 (rh/100) Eq. 7.4-13

Rather than constrain each variable in the above correlations, a subsequent constraint is placed
on the overall estimate of the diffuse fraction. The constraints limit the diffuse fraction estimates
to values that are physically possible.

For the above Horizontal Radiation Modes, beam radiation on a horizontal surface is calculated
by the difference between the total radiation and the diffuse component,

Ib = I - Id Eq. 7.4-14

In Horizontal Radiation Mode (hMode) 3, beam and diffuse radiation on a horizontal surface are
Input directly. For Horizontal Radiation Mode (hMode) 4, total horizontal and direct normal
radiation are Inputs and Horizontal Radiation Mode (hMode) 5 has Inputs of total and diffuse
radiation on a horizontal surface.

If measurements of global horizontal and beam or diffuse radiation are available, then Horizontal
Radiation Mode (hMode) 3, 4 or 5 should be used. Horizontal Radiation Mode 4 can be used with
SOLMET (4) data, since direct normal radiation values have been estimated for this data using
the algorithm developed by Randall and Whitson (5). When beam and diffuse radiation
measurements are not available, Horizontal Radiation Modes 1 or 2 must be used. If total
radiation on a horizontal surface, ambient temperature and relative humidity data are available,
Horizontal Radiation Mode 2 is recommended. (Note that the temperature and relative humidity
data sent to the getIncidentRadiation routine may be interpolated values. They will not be
interpolated by getIncidentRadiation.) If only total radiation is available, then it is recommended
that Horizontal Radiation Mode 1 be used.

The above recommendations are based on evaluation of the existing correlations with several
sets of measurements (9a).

7.4.4.4.1.2. Position of Sun in Sky

The position of the sun in the sky can be specified by giving the solar zenith and solar azimuth
angles. The zenith angle is the angle between the vertical and the line of sight of the sun. This is
90 minus the angle between the sun and the horizontal (solar altitude angle). The solar azimuth
angle is the angle between the local meridian and the projection of the line of sight of the sun
onto the horizontal plane. A solar azimuth value of zero is facing the equator, west is positive,
while east is negative. Facing away from the equator is 180. Both zenith and solar angles can

790
TRNSYS 17 Programmer's Guide

be determined from trigonometric relationship given in Chapter 2 of Duffie and Beckman (6) or
ASHRAE (7), or by Braun and Mitchell (8).

cos Z = sin sin + cos cos cos Eq. 7.4-15

sins = cos sin Eq. 7.4-16


sin Z

7.4.4.4.1.3. Surface Tracking Mode

Four Surface Tracking Modes (trackMode) are incorporated into TRNSYS for handling various
surfaces for which determination of incident radiation is often needed. Tracking Mode 1 is for
surfaces that do not track to maximize incoming radiation. The slope and azimuth Inputs denote
the position of the surface. These may vary with time as with any TRNSYS Inputs or may be
constant. Tracking Modes 2-4 handle various kinds of optimally tracked surfaces. An optimally
tracked collector will be maneuvered to maximize radiation at all times. In general, this amounts
to maximizing beam radiation, or cos .

Tracking Mode 2 handles a tracking surface with a fixed surface slope and variable surface
azimuth rotating about a vertical axis as denoted in Figure 7.4.42. For this case, beam radiation
is maximized when = s. The azimuth Input in this situation is ignored.

Vertical

East

South

Figure 7.4.42: Tracking Mode 2 Surface

Tracking Mode 3 handles the general case of a surface rotating about a single axis that is always
parallel to the surface. An illustration of this scheme is presented in Figure 7.4.43. For a
horizontal axis, the surface slope at any instant is given by

= tan-1 (tan Z cos(s - )) Eq. 7.4-17

where the surface azimuth is given in terms of the axis azimuth as

= + 90 if s - > 0 Eq. 7.4-18

791
TRNSYS 17 Programmer's Guide

= - 90 if s - < 0 Eq. 7.4-19

If a surface tracks about a single axis that is always parallel to the surface, but is not vertical or
horizontal, both azimuth and slope of the surface vary with time. In this case,

sin Z sin(s - )
= + tan-1 Eq. 7.4-20
sin cos

tan
= tan-1 Eq. 7.4-21
cos(-)

where ' is the incidence angle for a surface with slope and azimuth equal to those of the axis.

The slope and azimuth Inputs for Mode 3 refer to the position of the axis.

Vertical

East


'
Surface Normal

'
'

South

Figure 7.4.43: Tracking Mode 3 Surface

In Tracking Mode 4, two-axis tracking surfaces are considered. Beam radiation is maximized for a
surface adjusted such that the sun's rays are always at normal incidence (i.e. cos = 1). This is
accomplished when = s and = z. Both slope and azimuth Inputs are ignored. The derivations
of the trigonometric relationships for the class of tracking collectors presented here are given in
Reference 8.

7.4.4.4.1.4. Tilted Surface Radiation Mode

For most surfaces, an estimate of the total radiation incident on the surface is of interest. The
getIncidentRadiation routine provides five models for estimating the total radiation on a tilted
surface. Each model requires knowledge of total and diffuse (or beam) radiation on a horizontal
surface as well as the sun's position. In general the total tilted surface radiation is calculated by
estimating and adding beam, diffuse and reflected radiation components on the tilted surface.

792
TRNSYS 17 Programmer's Guide

All tilted surface radiation models use the same techniques for projecting the beam and ground
reflected radiation onto a tilted surface; they differ only in the estimate of diffuse radiation on a
tilted surface. The contribution of beam radiation on a tilted surface (in short time intervals) can
be calculated by using the geometric factor Rb (6):

Rb = cos Eq. 7.4-22


cos Z
where

cos = cos Z cos + sin Z cos(s - ) sin Eq. 7.4-23

In the above equation, is the slope of the surface defined as the angle between the surface and
the horizontal, while is the surface azimuth or the angle between the projection of the normal to
the surface into the horizontal plane and the local meridian. The sign convention for surface
azimuth is identical to that for solar azimuth (zero if facing the equator, positive if west, negative if
east). Slope is measured as a positive value when tilted in the direction of the azimuth
specification.

Once Rb is found,

IbT = Ib Rb Eq. 7.4-24

The contribution of reflected radiation on a titled surface is calculated by assuming the ground
acts as an isotropic reflector and defining Rr as the ratio of reflected radiation on a tilted surface
to the total radiation on a horizontal surface is:

Rr = 0.5 (1 - cos ) g Eq. 7.4-25

IgT = I Rr Eq. 7.4-26

The contribution of diffuse radiation on a tilted surface is determined by using one of the five
models provided in the getIncidentRadiation routines Tilted Surface Radiation Mode. Tilted
Surface Radiation Mode 1 uses the isotropic sky model. This is the model that has been used by
default in previous versions of TRNSYS. The isotropic sky model assumes that the diffuse
radiation is uniformly distributed over the complete sky dome. A factor Rd, the ratio of diffuse
radiation on a tilted surface to that on a horizontal, is given by:

Rd = 0.5 (1 + cos ) Eq. 7.4-27

Thus the diffuse radiation on a tilted surface assuming isotropic sky is:

IdT = Id Rd Eq. 7.4-28

Tilted Surface Radiation Mode 2 uses a model developed by Hay and Davies (10). The Hay and
Davies model accounts for both circumsolar and isotropic diffuse radiation. Under clear sky
conditions, there is an increased intensity of diffuse radiation in the area around the sun
(circumsolar diffuse). Hay and Davies weight the amount of circumsolar diffuse by using an
anisotropy index; AI The anisotropy index defines a portion of the diffuse radiation to be treated
as circumsolar with the remaining portion of diffuse radiation considered isotropic. The Hay and
Davies tilted surface diffuse radiation model is given by:

793
TRNSYS 17 Programmer's Guide

AI = Ibn Eq. 7.4-29


Ion

IdT = Id 0.5 1 - AI 1 + cos + AI Rb Eq. 7.4-30

The first term in bracket represents the contribution of isotropic diffuse radiation while the second
term represents the contribution of circumsolar diffuse radiation.

Tilted Surface Radiation Mode 3 uses a model developed by Reindl (9b) based on the work of
several previous authors. This model adds a horizon brightening diffuse term to the Hay and
Davies model. The horizon brightening is lumped with the isotropic diffuse term and its magnitude
is controlled by a modulating factor, f.

The Reindl tilted surface diffuse radiation model is given by:

f= Ib Eq. 7.4-31
I

IdT = Id 0.5 1 - AI 1 + cos 1 + f sin3( /2) + AI Rb Eq. 7.4-32

The first term in brackets represents the contribution of isotropic and horizon diffuse and the
second term represents the contribution of circumsolar diffuse.

Tilted Surface Radiation Mode 4 uses a version of the tilted surface model developed Perez, et al
in 1988 (11). This model accounts for circumsolar, horizon brightening, and isotropic diffuse
radiation by empirically derived "reduced brightness coefficients". The reduced brightness
coefficients, F1, F2, are functions of sky clearness, e, and sky brightness, , parameters.

Id + Idn 3
+ 1.041 Z
Id Eq. 7.4-33
3
1 + 1.041 Z

Where z is in radians:

Id m = Id Eq. 7.4-34
Ion Io
The sky clearness and sky brightness parameters are used to calculate the reduced brightness
coefficients from the relationships and table given below.

F 1 = F11() + F 12() + F13() Z Eq. 7.4-35

F 2 = F21() + F 22() + F23() Z Eq. 7.4-36

The Perez coefficients (F11, etc.) are given in the following table (11):
Bin Upper Cases F11 F12 F13 F21 F22 F21
Limit for (%)

1 1.065 13.60 -0.196 1.084 -0.006 -0.114 0.180 -0.019
2 1.230 5.60 0.236 0.519 -0.180 -0.011 0.020 -0.038
3 1.500 7.52 0.454 0.321 -0.255 0.072 -0.098 -0.046

794
TRNSYS 17 Programmer's Guide

4 1.950 8.87 0.866 -0.381 -0.375 0.203 -0.403 -0.049


5 2.800 13.17 1.026 -0.711 -0.426 0.273 -0.602 -0.061
6 4.500 21.45 0.978 -0.986 -0.350 0.280 -0.915 -0.024
7 6.200 16.06 0.748 -0.913 -0.236 0.173 -1.045 0.065
8 - 13.73 0.318 -0.757 0.103 0.062 -1.698 0.236
The magnitude of the reduced brightness coefficients weight the respective circumsolar, horizon
brightening, and isotropic diffuse radiation components. The angular location of the circumsolar
region is determined by the ratio a/c.

max 0, cos
a/c = Eq. 7.4-37
max cos 85, cos Z

The tilted surface diffuse radiation can be estimated by the following

IdT = Id 0.5 1-F1 1+cos + F1 ac + F2 sin Eq. 7.4-38

Thus the total radiation incident on a tilted flat surface for all tilted surface radiation modes is

IT = IbT + IdT + IgT Eq. 7.4-39

With the release of TRNSYS v17 Tilted Radiation Mode 5 was added. This model was developed
by Perez, et al in 1999 (12). The Perez 1999 model is identical in formulation to the Perez 1988
model. It differs only in the curve fit coefficients. The coefficients for the Perez 1999 model are:
Bin F11 F12 F13 F21 F22 F21
1 -0.0083117 0.5877285 -0.0620636 -0.0596012 0.0721249 -0.0220216
2 0.1299457 0.6825954 -0.1513752 -0.0189325 0.0659650 -0.0288748
3 0.3296958 0.4868735 -0.2210958 0.0554140 -0.0639588 -0.0260542
4 0.5682053 0.1874525 -0.2951290 0.1088631 -0.1519229 -0.0139754
5 0.8730280 -0.3920403 -0.3616149 0.2255647 -0.4620442 -0.0012448
6 1.1326077 -1.2367284 -0.4118494 0.2877813 -0.8230357 0.0558651
7 1.0601591 -1.5999137 -0.3589221 0.2642124 -1.1272340 0.1310694
8 0.6777470 -0.3272588 -0.2504286 0.2642124 -1.3765031 0.2506212
In general, the anisotropic sky models (Hay and Davies, Reindl, and Perez, et al) provide
comparable estimates of the total radiation on a tilted surface and are recommended for general
use. The Hay and Davies and the Reindl models are computationally simple when compared to
the Perez model. The isotropic sky model (mode 1) under predicts the total radiation on a tilted
surface and is not recommended for general use; it is included to permit consistency with
simulations performed with earlier versions of TRNSYS.

7.4.4.4.1.5. Solar Time Calculation

Since many of the calculations made in transforming insolation on a horizontal surface depend on
the time of day, it is important that the correct solar time be used. Several correction factors are
used in computing solar time. Following the development in Chapter 2 of Duffie and Beckman,

solar time (hrs) = standard time + E + (Lst - Lloc)/15 Eq. 7.4-40

Here E accounts for the eccentricity of the earth's orbit and varies between about -.24 hours and
+.26 hours each year. Lst is the standard meridian for the local time zone and Lloc is the longitude
of the location in question. Both standard and local meridians are measured in degrees 0 to
180. West of longitude 0 (Greenwich, England) is positive, east is negative. Standard meridians
for continental U.S. time zones are Eastern 75 W, Central 90 W, Mountain l05 W, and Pacific

795
TRNSYS 17 Programmer's Guide

l20. Standard meridians for Europe are Western (Greenwich time) 0 and Central (MEZ time) -
15.

For processing the total radiation over a time step, the mean hour angle

= 0.5 ( 1 + 2 ) Eq. 7.4-41

is used. This is to ensure that the calculated position of the sun will be the average position for
the time step.

The solar time that is used is

solar time = t + E + SHFT/15 Eq. 7.4-42

where t is the time in hours corresponding to . Comparing the two equations for solar time, one
can see that SHFT should be set to Lst - Lloc. Also, simulation time should be set so that the first
data line read in corresponds to the period (typically hour) ending at the simulation starting time.
If data is supplied at even solar time intervals, then the factors E and SHFT should be omitted.
This is accomplished by including a negative last parameter.

References
1. Liu, B. Y. H. and Jordan, R. C. The Interrelationships and Characteristic Distribution of
Direct, Diffuse and Total Solar Radiation, Solar Energy, Vol. IV, July, (1960), pp. 1-19.
2. Boes, E. C. et al., Distribution of Direct and Total Solar Radiation Availabilities for the
U.S.A., Sandia Report SAND76-0411, August, (1976).
3. Erbs, D. G., Methods for Estimating the Diffuse Fraction of Hourly, Daily and Monthly
Average Global Solar Radiation, Masters Thesis in Mechanical Engineering, University
of Wisconsin-Madison, (1980).
4. SOLMET, Volume 2 Final Report, Hourly Solar Radiation Surface Metereological
Observations, TD-9724, (1979).
5. Randall, C.M. and Whitson, M. E., Final Report, Hourly Insolation and Metereological
Data Bases Including Improved Direct Insolation Estimates, Aerospace Report No. ATR-
78(7592)-1, (1977).
6. Duffie, J. A. and Beckman, W. A., Solar Energy Thermal Processes, Wiley, New York,
(1974).
7. ASHRAE Handbook of Fundamentals, American Society of Heating, Refrigeration and
Air-Conditioning Engineers, (1972).
8. Braun, J. E. and Mitchell, J.C., Solar Geometry for Fixed and Tracking Surfaces, Solar
Energy, Vol. 31, No. 5, October, (1983).
9. (a) Reindl, D.T., Beckman, W.A. and Duffie, J.A., Diffuse Fraction Correlations, Solar
Energy, Vol. 45, No. 1, (1990), pp.1-7.
(b) Reindl, D.T., Beckman, W.A. and Duffie, J.A., Evaluation of Hourly Tilted Surface
Radiation Models, Solar Energy, Vol. 45, No. 1, (1990), pp. 9-17.
10. Hay, J.E., Davies, J.A., Calculation of the Solar Radiation Incident on an Inclined
Surface, Proceedings First Canadian Solar Radiation Workshop, (1980), pp. 59-72.
11. Perez, R., Stewart, R., Seals, R., and Guertin, T., The Development and Verification of
the Perez Diffuse Radiation Model, Sandia Report SAND88-7030, (1988).

796
TRNSYS 17 Programmer's Guide

12. Perez, R. (1999)

797
TRNSYS 17 Programmer's Guide

7.4.4.5. InterpolateData (formerly DynamicData, DYNDATA and


DATA)

GENERAL DESCRIPTION

The InterpolateData 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
InterpolateData routine is able to interpolate the data found in the file in up to six dimensions
during the course of the simulation. For each data set, up to ten dependent (Y) functions may be
specified in terms of up to six independent (X) variables. At each call to the InterpolateData
routine, the calling Type sends the values of each independent variable. InterpolateData 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.
InterpolateData 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, InterpolateData will return the values of the dependent variables that
correspond to the maximum or minimum of the range. With the release of TRNSYS 17,
InterpolateData keeps track of what percentage of the simulation time a given data file and a
given independent variable were called with values above or below the range given in the data
file. A notice is printed to the *.lst and *.log files at the end of the simulation.

InterpolateData 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, InterpolateData was known as either DynamicData (which
was a double precision routine) or as DATA or DYNDATA, both of which were single precision
routines. DynamicData, DATA and DYNDATA were retained for backwards compatibility but
every effort should be made to use the double precision InterpolateData routine.

Examples of standard components that use InterpolateData are the Type1 Solar Collector and
the Type44 Conditioning Equipment model. The form of a call to InterpolateData is:
Integer :: LU,nIND,nX(:),nY(:),INFO(15)
Double Precision :: X(:),Y(:)
...
Call InterpolateData (LU, nIND, nX, nY, X, Y)
where

LU (integer) is the FORTRAN logical unit number through which the


performance data is accessed.
nIND (integer) is the number of independent variables (1 nIND 6)
nX is an integer array dimensioned to nIND containing the number
of values of each independent variable to be read from LU.
NX(1), NX(2), NX(3), NX(4), NX(5), and NX(6) are the number of
values of X1, X2, X3, X4, X5, and X6, respectively.
nY (integer) is the number of dependent (Y) values associated with
each set of independent (X) values (1 nY 10)
X is a double precision array dimensioned to nIND containing the
values of the independent variables for which interpolated Y
values are desired

798
TRNSYS 17 Programmer's Guide

Y is a double precision array of dimension nY containing


interpolated values of the dependent variables

DynamicData, DYNDATA, and DATA all required two additional arguments as follows:

INFO is the calling TYPE's INFO array.


N (integer) is the corresponding line number to jump to if the
subprogram is present.

The data is read from logical unit LU at the start of the simulation. Thereafter, InterpolateData
linearly interpolates for Y values given X values. If InterpolateData is called with an X out of
range of the supplied data, then the closest specified value is used. InterpolateData does not
extrapolate beyond the user supplied data.

Data is supplied in an external text file that is read by the InterpolateData routine. The values of
all the independent variables are specified at the top of the file, followed by the values of the
dependent variables. The independent variables may be thought of as the inputs; the dependent
variables are read from the file and may be thought of as the outputs. There may be up to six
independent variables. Each independent variables value range is specified in a single row
starting with the 6th dimension and proceeding to the 1st dimension. If the data being read and
interpolated is influenced by less than 6 dimensions, the data file begins with the greatest
dimension. Thus the row of independent variable values corresponding to X1 is always adjacent
to the section of the file containing the dependent values. An exclamation point following the
variable values indicates the beginning of a comment and can be used to clarify the contents of
each row in the file.

If NIND (the number of independent variables expected in the file) equals 6 then nX(6) values of
the sixth independent variable (X6) are expected to appear on the first line of the data file. In this
case, the second row of the data file would contain nX(5) values of the fifth independent variable
(X5), the third row of the data file would contain nX(4) values of the fourth independent variable,
the fourth row of the data file would contain nX(3) values of the third independent variable, the
fifth row would contain nX(2) values of the second independent variable and the sixth row would
contain nX(1) values of the first independent variable.

If nIND is equal to 2, then nX(2) values of the second independent variable appear on the first
row of the file and nX(1) values of the first independent variable appear on the second row of the
file. In each line, the values of independent variables must be in ascending order but need not be
at regular intervals.

The remainder of the data file contains rows of dependent variable values. Each row contains nY
(the number of dependent variable) values. And each row corresponds to a specific combination
of independent variable values. The total number of rows of dependent variable values will be
equal to the product of the number of values in each of the rows of independent variable values.
For example, if the file has two independent variables (nIND = 2) and there are 3 values of X2 (on
the first line) and 4 values of X1 on the second line of the file then the file will contain 12 rows of
dependent variable values.

The first set of dependent variable value rows correspond to the values of the X1 independent
variable. In the previous example, there were 4 values of X1; the first set of dependent variable
values would be made up of four rows corresponding to X1(1), X1(2), X1(3), and X1(4). Each
subsequent set of dependent variable value rows correspond to the values of the next highest

799
TRNSYS 17 Programmer's Guide

dimension of independent variable. Again taking the example from above, the same first four
rows would correspond to X1(1), X1(2), X1(3), and X1(4) for the first value of X2. A second set of
four rows would follow corresponding to X1(1), X1(2), X1(3), and X1(4) for the second value of X2.
A third set of four rows would correspond to X1(1), X1(2), X1(3), and X1(4) for the third value of X2.

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). InterpolateData is to be used to evaluate both the capacity and COP. The experimental
data is shown in Table 7.4.4.5-1.

Table 7.4.4.5-1

Tcond = 20 [C] Tcond = 50 [C]

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 Tevap and two values of Tcond will be
supplied. The call to InterpolateData within the calling Type routine might appear as

USE TrnsysFunctions
...
Integer :: nX(2)
Double Precision :: X(2),Y(2),CAP,COP,T_Evap,T_Cond
...
nX(1) = 3 !There are 3 values of the second variable in the file.
nX(2) = 2 !There are 2 values of the first variable 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
Call InterpolateData (10,2,nX,2,X,Y)
CAP = Y(1) !sets the call result y(1) to local variable CAP.
COP = Y(2) ! sets the call result y(1) to local variable COP.
...
The syntax of the data file accessed through logical unit 10 would be as follows:
20.0 50.0 !Tcond values

10.0 20.0 30.0 !Tevap values

35000. 2.47 !Capacity and COP for Tcond=20C, and Tevap=10C


41000. 2.80 !Capacity and COP for Tcond =20C, and Tevap=20C
49500. 2.99 !Capacity and COP for Tcond =20C, and Tevap=30C

21000. 1.73 !Capacity and COP for Tcond =50C, and Tevap=10C
25000. 1.96 !Capacity and COP for Tcond =50C, and Tevap=20C
29000. 2.09 !Capacity and COP for Tcond =50C, and Tevap=30C

7100
TRNSYS 17 Programmer's Guide

7.4.4.6. LinearRegression (formerly DFIT and FIT)

General Description

Subroutine LinearRegression uses linear least-squares regression to determine coefficients of a


user defined correlation. A call to LinearRegression is of the form:
Integer :: nRow,nCol,nCoef,nData,iFlag
Double Precision :: X,Y,PHI
...
Call LinearRegression(nRow,nCol,nCoef,nData,X,Y,PHI,iFlag)
where,

nROW (integer) Row dimension of X in routine calling LinearRegression.


nCOL (integer) Column dimension of X in routine calling
LinearRegression.
nCOEF (integer) Number of coefficients in model.
nDATA (integer) Number of data points for the regression.
X Double precision two dimensional array containing the values of
the independent variables to the model. X(I,J) is the value of the
independent variable associated with the ith coefficient of the
model and the jth data point.
Y (double precision) vector containing values of the dependent
variable corresponding to independent variable data points.
PHI (double precision) vector containing the coefficients determined
from the regression.
iFLAG (integer) flag returned indicating the error condition (0 - no error,
1 - dimension error, 2 - coefficients cannot be determined).
With TRNSYS versions prior to 17, the LienarRegression subroutine was available in two forms:
FIT required single precision arguments, while DFIT used double precision arguments. The
routines required an additional integer argument N following the iFlag argument.
*N (integer) the corresponding line number to jump to if the
subprogram is present.

MATHEMATICAL DESCRIPTION

Least-squares regression is used to minimize a function J, where:

(Y Ymod el , j )
N data
J= j
Eq. 7.4.4-43
j =1

N coef

Ymod el , j = X
i =1
i i, j Eq. 7.4.4-44

where,

7101
TRNSYS 17 Programmer's Guide

Yj jth data point for dependent variable


Ymodel,j dependent variable of the user's model for the jth data point
i ith coefficient to be determined with LinearRegression
Xi,j user defined functions of the independent variable or variables.

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. 7.4.4-45

This is the same form as Eq. 7.4.4-44 with:


1-5 = a0-a5

X1,j = 1.0

X2,j = E

X3,j = E2

X4,j = F

X5,j = F2

X6,j = EF

If the following data existed for E, F, and G:

E F G
3.0 0.2 10.0
5.0 0.4 12.5
7.0 0.6 13.1

Then LinearRegression would be called with

NROW = 6 or more (minimum is the # of coefficients,i's)


NCOL = 3 or more (minimum is the # of data points,j's)
NCOEF = 6 (number of coefficients, i's)
NDATA = 3 (number of data points, j's)

7102
TRNSYS 17 Programmer's Guide

1.0 1.0 1.0


E1 E2 E3 1.0 1.0 1.0
3.0 5.0 7.0
E1 2 E2 2 E3 2 9.0 25.0 49.0
X= = Eq. 7.4.4-46
F1 F2 F3 0.2 0.4 0.6
.04 .16 .36
F1 2 F2 2 F3 2 0.6 2.0 4.2
EF1 EF2 EF3
10.0
Y = 12.5 Eq. 7.4.4-47
13.1

The LinearRegression 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.

7103
TRNSYS 17 Programmer's Guide

7.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. In TRNSYS
16, LINKCK remained as a safeguard against inadvertently unlinked routines but almost always,
unlinked routines will be caught during the compiling and linking processes. With the release of
TRNSYS 17, many of the direct calls that a user-written Type made to LINKCK were made
obsolete by the introduction of access functions. Essentially the call to LINKCK was handled by
the access function and the user no longer had to worry about it. A call to LINKCK is of the form:
Character (len=12) :: ENAME1,ENAME2
Integer :: ILINK,LNKTYP
...
Call LINKCK(ENAME1,ENAME2,ILINK,LNKTYP)
where

ENAME1 a 12-character variable identifying the subroutine from which the


call originated.
ENAME2 a 12-character variable identifying the subroutine that was called
ILINK an integer indicating the steps to be taken by the LINKCK
program
=1 an unlinked subroutine has been found, generate an
error message and stop the program
=2 an unlinked subroutine has been found, generate a
warning but keep running
=3 an unlinked TYPE subroutine has been found, generate
an error message and stop the program
=4 warn the user that a subroutine requires use of an
external function which cannot be link checked
LNKTYP integer variable corresponding to the TYPE subroutine which
was not found in the TRNSYS executable
With TRNSYS versions prior to 17the routines required an additional integer argument N
following the LNKTYP argument.
N (integer) the corresponding line number to jump to if the
subprogram is present.

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
...
Character (len=12) ENAME1,ENAME2
Double Precision :: SPAR(10),WPAR(10),FV

7104
TRNSYS 17 Programmer's Guide

Integer :: ILINK,LNKTYP,INFO(15)
...
! Attempt to call the TRNSYS 16 subroutine called ENCLOSURE. NOTE: a
! TRNSYS 16 subroutine is used in this example because it makes use of
! the alternate return technique.
Call ENCLOSURE(SPAR,WPAR,FV,INFO,*101)
! Stop TRNSYS if the ENCLOSURE subroutine is not present.
ILINK = 1
IDUM = 75
ENAME1 = TYPE75
ENAME2 = ENCLOSURE
Call LINKCK(ENAME1,ENAME2,ILINK,IDUM)

!ENCLOSURE is present Continue on.


101 Continue
...

7105
TRNSYS 17 Programmer's Guide

7.4.4.8. InvertMatrix (formerly MATRIX_INVERT, INVERT and


DINVRT)
Subroutine InvertMatrix is a double precision routine available to invert a matrix of up to 50 by 50
entries. In TRNSYS version 15.x and below, the subroutine had two forms; INVERT was a single
precision version and DINVRT was a double precision. With the release of TRNSYS 16.0, the
double precision routine was renamed and recommended for use by all standard and user written
Types. INVERT and DINVRT were maintained for backwards compatibility. The InvertMatrix
routine takes a slightly different list of arguments than did the Matrix_Invert routine. A call to
InvertMatrix is of the form
Integer :: NRC,iFLAG
Double Precision :: A
...
CALL InvertMatrix(NRC,N,A,iFlag)
where

NRC (integer) is the column and row dimensions of the two-


dimensional A() array as defined in the program that calls
InvertMatrix.
N (integer) the number of equations and unknowns associated with
the problem.
A a double precision two-dimensional array (A(NRC, NRC)). Upon
calling InvertMatrix A should contain the matrix to be inverted.
InvertMatrix also returns the inverted matrix in the A array.
iFLAG an integer flag that is set to 0 if the inversion proceeds correctly,
1 if the number equations and unknowns, N, exceeds 50, and 2 if
the matrix is singular.
The MATRIX_INVERT, INVERT, and DINVRT routines required the additional argument *N
following the iFlag argument.
*N the corresponding line number to jump to if the subprogram is
present.
The inverted matrix is returned in the A array. The method used to invert the matrix is the Gauss-
Jordan reduction with maximum pivoting.

7106
TRNSYS 17 Programmer's Guide

7.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

errorCode is a standard TRNSYS error message number. Please refer to the


initializeErrorMessages() subroutine in Messages.f90 for existing messages.

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

7107
TRNSYS 17 Programmer's Guide

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 the first parameter > 10 is not acceptable (values < 10.1 are just rounded to 10 and the
simulation goes on).
Subroutine Type200
...
Use TrnsysConstants
Use TrnsysFunctions
...
Character (len=maxMessageLength) :: myMessage
Integer crntUnit,crntType
Double Precision :: param1
...
crntUnit = getCurrentUnit()
crntType = getCurrentType()
param1 = getParameterValue(1)
If (param1 < 10.0 ) Then
Write(myMessage,'("parameter 1 = ",g," , which is OK")') param1
Call Messages(-1,trim(myMessage),'Notice', crntUnit,crntType)
ElseIf (getParameterValue(1) <= 10.1) Then
Call Messages(-1,'parameter 1 has been rounded to 10', &
'Warning',crntUnit,crntType)
Else
Call Messages(-1,''parameter 1 is outside the acceptable range.', &
'Fatal', crntUnit,crntType)
Return
EndIf

Please note the use of RETURN 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 statement.

7108
TRNSYS 17 Programmer's Guide

7.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.

7109
TRNSYS 17 Programmer's Guide

7.4.4.11. MoistAirProperties (formerly PSYCHROMETRICS and


PSYCH)
This utility routine is available to calculate various moist air properties based on ASHRAE
correlations and the Ideal Gas Law. A double precision version called MoistAirProperties and
legacy double and single precision versions called PSYCHROMETRICS, and PSYCH
respectively are available although PSYCHROMETRICS and PSYCH are only included for
backwards compatibility. It is recommended that all user written routines employ the double
precision version and that all non integer arguments to the MoistAirProperties routine be declared
as DOUBLE PRECISION variables in the calling Type. A call to MoistAirProperties is of the form
Double Precision :: psydat(7)
Integer :: crntUnit,crntTyp,iUnits,mode,wbmode,psydat,eMode,stat
...
Call MoistAirProperties(crntUnit,crntTyp,iUnits,mode,wbmode,psydat,eMode,stat)
where

CrntUnit the UNIT number of the TYPE calling the MoistAirProperties


routine. If a non-Type is calling the routine, this argument should
be set to -1
CrntTyp the TYPE number of the TYPE calling the MoistAirProperties
routine. If a non-Type is calling the routine, this argument should
be set to -1
iUnits an integer variable equal to 1 or 2 identifying the units desired for
the properties. IUNITS = 1 results in properties in SI units.
IUNITS = 2 results in properties in English units.
mode an integer variable from 1 through 6. Three properties are
needed to specify the moist air state. The MODE identifies
which two properties besides pressure are need to be input,
leaving the other properties to be calculated. The modes are as
follows:
1: input dry bulb and wet bulb temperatures (PSYDAT(2)
and PSYDAT(3))
2: input dry bulb temperature and relative humidity
(PSYDAT(2) and PSYDAT(4))
3: input dry bulb and dew point temperatures (PSYDAT(2)
and PSYDAT(5))
4: input dry bulb temperature and humidity ratio
(PSYDAT(2) and PYSDAT(6))
5: input dry bulb temperature and enthalpy (PSYDAT(2)
and PSYDAT(7))
6: input humidity ratio and enthalpy (PSYDAT(6) and
PSYDAT(7)) . If saturation conditions occur, enthalpy is
reset to saturation enthalpy at the given value of
humidity ratio.
7: input humidity ratio and enthalpy (PSYDAT(6) and
PSYDAT(7)) . If saturation conditions occur, humidity
ratio is reset to saturation humidity ratio at the given

7110
TRNSYS 17 Programmer's Guide

value of enthalpy. 8: input relative humidity and


enthalpy (PSYDAT(6) and PSYDAT(4)).
wbMode an integer variable equal to 0 or 1. If WBMODE = 0, the wet bulb
temperature will not be calculated in MODEs 2 through 6. If
WBMODE = 1, the wet bulb temperature is calculated. At PATM
= 1.0 and temperatures common to HVAC applications, a
correlation (1) is used to find the wet bulb temperature given
enthalpy. For other pressures and temperatures, a Newton's
iterative method is used with the equations given by ASHRAE (2)
to calculate the wet bulb temperature. If the wet bulb
temperature is not needed, WBMODE should be set to 0 to
decrease the computational effort. If WBMODE = 0, the wet bulb
temperature is set to the dry bulb temperature.
PSYDAT an array containing the properties of the moist air. This array
must be dimensioned to 9 in the routine that calls
MoistAirProperties. Each location in this array is described
below:
PSYDAT(1) (double precision) The total system pressure in atmospheres.
The subroutine prints a warning if PATM is over 5 atmospheres,
which is considered here to be an upper limit for using ideal gas
relations for air and water mixtures.
PSYDAT(2) (double precision) dry bulb temperature (C).
PSYDAT(3) (double precision) wet bulb temperature (C).
PSYDAT(4) (double precision) relative humidity (fraction).
PSYDAT(5) (double precision) dew point temperature (C).
PSYDAT(6) (double precision) humidity ratio (kg water/kg dry air).
PSYDAT(7) (double precision) enthalpy (kJ/kg dry air).
PSYDAT(8) (double precision) density of the air water mixture (kg/m3)
PSYDAT(9) (double precision) density of the air portion of the mixture (kg dry
air/m3)
eMode an integer variable equal to 0, 1, or 2 specifying how warnings
are handled. If EMODE=0, no warnings will be printed. If
EMODE=1, only one warning for each condition will be printed
throughout the simulation. If EMODE=2, warnings will be printed
every time step. (EMODE=2 is useful for program and simulation
development, but it can produce an excessive amount of output).
stat an integer variable equal to 0 through 13 identifying the warning
condition that occurred within subroutine PSYCH. 0 indicates no
warnings. For a complete listing of warnings 1 through 13 the
subroutine source code should be reviewed.
The previous versions of this routine (PSYCHROMETRICS, and PSYCH) did NOT require the
crntUnit and crntType arguments. They did, however, require that the first two arguments were
the variable TIME, and the INFO() array and that the last argument was *N
TIME (double precision) This is the standard TIME used in TRNSYS.
It is used in the MoistAirProperties subroutine only to identify the
time at which warnings or errors occur.

7111
TRNSYS 17 Programmer's Guide

INFO This is the standard integer INFO array used in TRNSYS (see
Section 7.4.2.49). It is used in the PSYCHROMETRICS
subroutine to identify the unit and type number of the component
which calls the subroutine, which will be printed during a
simulation if warnings or errors occur.
*N the corresponding line number to jump to if the subprogram is
present.

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.

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.

7112
TRNSYS 17 Programmer's Guide

7.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 the Simulation Studio. With the
release of TRNSYS v17, direct calls by a Type to the RCHECK routine became somewhat
obsolete as two access functions were written to replace them. A call to RCHECK is of the form:
Integer :: INFO(15)
Character (len=3) :: YCHECK(:),OCHECK(:)
...
Call RCHECK(INFO,YCHECK,OCHECK)
where

INFO This is the standard INFO array used in TRNSYS (see Section
7.4.2.49). It is used in the RCHECK subroutine to identify the
Unit and Type number of the component which calls the
subroutine, which will be printed during a simulation if warnings
or errors occur.
YCHECK A 3-character array containing the expected input types for the
component.
OCHECK A 3-character array containing the output types for the
component
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 kernels 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.

With the release of TRNSYS v17, it was recommended that calls to RCHECK be replaced by use
of the setInputUnits and setOutputUnits access functions. See section 7.2 for information
about converting Types to the TRNSYS 17 coding standard. Refer to sections 7.4.2.87 and
7.4.2.88 for additional information about these specific access functions.

In TRNSYS v16 and earlier, it was recommended that a user formulating a new component utilize
the RCHECK 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 with RCHECK is to characterize the inputs and outputs
using the codes from 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 (during the first call manipulations) (formerly INFO(7)=-1) see Section 7.4.2.49) and after
the call to the TYPECK subroutine (see Section 3.4.1).

7113
TRNSYS 17 Programmer's Guide

The following example should help clarify the use RCHECK by a TRNSYS 16 coding standard
component:
Subroutine TYPE75(TIME,XIN,OUT,T,DTDT,PAR,INFO,ICNTRL,*)
! There are 3 Inputs and 4 Outputs for this Type
! Inputs: Temperature in (F)
! Mass flow rate in (lb-m/hr)
! Control signal in (0 or 1)
! OUTPUTS: Temperature out (C)
! Mas flow rate out (kg/hr)
! Heat transfer rate (kJ/hr)
! Power (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)
...
Return 1
EndIf
As a point of reference, the same results are achieved in TRNSYS 17 coding standard as follows:
Subroutine Type75
! There are 3 Inputs and 4 Outputs for this Type
! Inputs: Temperature in (F)
! Mass flow rate in (lb-m/hr)
! Control signal in (0 or 1)
! OUTPUTS: Temperature out (C)
! Mas flow rate out (kg/hr)
! Heat transfer rate (kJ/hr)
! Power (W)
...
If (getIsFirstCallofSimulation()) Then
...
Call setInputUnits(1,TE2)
Call setInputUnits(1,MF3)
Call setInputUnits(1,CF1)

Call setOutputUnits(1,TE1)
Call setOutputUnits(1,MF1)
Call setOutputUnits(1,PW1)
Call setOutputUnits(1,PW2)
...
Return
EndIf
Table 7.4.4.12-1: TEMPERATURE

VAR. TYPE # VAR. UNITS VAR.TYPE MULT. FACTOR ADD. FACTOR


1 C TE1 1.0 0
2 F TE2 1.8 32
3 K TE3 1.0 273.15
4 R TE4 1.8 492
Table 7.4.4.12-2: LENGTH

VAR. TYPE # VAR. UNITS VAR. TYPE MULT. FACTOR ADD. FACTOR

7114
TRNSYS 17 Programmer's Guide

1 m LE1 1 0
2 cm LE2 100 0
3 km LE3 1000 0
4 in LE4 39.3701 0
5 ft LE5 3.28084 0
6 miles LE6 6.21371 E-04 0
Table 7.4.4.12-3: AREA

VAR. TYPE # VAR. UNITS VAR. TYPE MULT. FACTOR ADD. FACTOR
1 m2 AR1 1 0
2 cm2 AR2 1 E+04 0
3 km2 AR3 1 E-06 0
4 in2 AR4 1550 0
5 ft2 AR5 10.7639 0
6 mi2 AR6 3.86102 E-07 0
Table 7.4.4.12-4: VOLUME

VAR. TYPE # VAR. UNITS VAR. TYPE MULT. FACTOR ADD. FACTOR
1 m3 VL1 1 0
2 l VL2 1000 0
3 ml VL3 1 E+06 0
4 in3 VL4 6.10237 E+04 0
5 ft3 VL5 35.3147 0
6 gal VL6 264.172 0
Table 7.4.4.12-5: SPECIFIC VOLUME

VAR. TYPE # VAR. UNITS VAR. TYPE MULT. FACTOR ADD. FACTOR
1 m3/kg SV1 1 0
2 l/kg SV2 1000 0
3 ft3/lbm SV3 16.0185 0
4 in3/lbm SV4 2.76799 E+04 0
Table 7.4.4.12-6: VELOCITY

VAR. TYPE # VAR. UNITS VAR. TYPE MULT. FACTOR ADD. FACTOR
1 m/s VE1 1.0 0
2 km/hr VE2 3.6 0
3 ft/s VE3 3.28084 0
4 ft/min VE4 196.85 0
5 mph VE5 2.23694 0
Table 7.4.4.12-7: MASS

VAR. TYPE # VAR. UNITS VAR. TYPE MULT. FACTOR ADD. FACTOR
1 kg MA1 1 0
2 g MA2 1000 0
3 lbm MA3 2.20462 0
4 ounces MA4 35.274 0
5 ton MA5 1.10231 E-03 0
Table 7.4.4.12-8: DENSITY

VAR. TYPE # VAR. UNITS VAR. TYPE MULT. FACTOR ADD. FACTOR
1 kg/m3 DN1 1.0 0
2 kg/l DN2 0.001 0
3 lbm/ft3 DN3 6.2428 E-02 0
4 lbm/gal DN4 8.3454 E-03 0

7115
TRNSYS 17 Programmer's Guide

Table 7.4.4.12-9: FORCE

VAR. TYPE # VAR. UNITS VAR. TYPE MULT. FACTOR ADD. FACTOR
1 N FR1 1.0 0
2 lbf FR2 0.224809 0
3 ounce FR3 3.59694 0
Table 7.4.4.12-10: PRESSURE

VAR. TYPE # VAR. UNITS VAR. TYPE MULT. FACTOR ADD. FACTOR
1 BAR PR1 1 0
2 kPa PR2 100 0
3 Pa PR3 1 E+05 0
4 ATM PR4 0.986923 0
5 psi PR5 14.5038 0
6 lbf/ft2 PR6 2.08854 E+03 0
7 in. H2O PR7 401.463 0
8 in. Hg PR8 29.53 0
Table 7.4.4.12-11: ENERGY

VAR. TYPE # VAR. UNITS VAR. TYPE MULT. FACTOR ADD. FACTOR
1 kJ EN1 1 0
2 kWh EN2 2.77778 E-04 0
3 Cal EN3 238.846 0
4 ft-lbf EN4 737.562 0
5 hp-hr EN5 3.72506 E-04 0
6 BTU EN6 0.947817 0
Table 7.4.4.12-12: POWER

VAR. TYPE # VAR. UNITS VAR. TYPE MULT. FACTOR ADD. FACTOR
1 kJ/hr PW1 1 0
2 W PW2 0.277778 0
3 kW PW3 2.77778 E-04 0
4 hp PW4 3.72505 E-04 0
5 BTU/hr PW5 0.947817 0
6 BTU/min PW6 1.57969 E-02 0
7 Tons PW7 7.89847 E-05 0
Table 7.4.4.12-13: SPECIFIC ENERGY

VAR. TYPE # VAR. UNITS VAR. TYPE MULT. FACTOR ADD. FACTOR
1 kJ/kg SE1 1 0
2 BTU/lbm SE2 0.429923 0
3 ft-lbf/lbm SE3 334.553 0
Table 7.4.4.12-14: SPECIFIC HEAT

VAR. TYPE # VAR. UNITS VAR. TYPE MULT. FACTOR ADD. FACTOR
1 kJ/kg-K CP1 1 0
2 W-hr/kg-K CP2 0.277778 0
3 BTU/lbm-R CP3 0.238846 0
Table 7.4.4.12-15: FLOW RATE

VAR. TYPE # VAR. UNITS VAR. TYPE MULT. FACTOR ADD. FACTOR
1 kg/hr MF1 1 0
2 kg/s MF2 2.77778 E-04 0
3 lbm/hr MF3 2.20462 0

7116
TRNSYS 17 Programmer's Guide

4 lbm/s MF4 6.12395 E-04 0


Table 7.4.4.12-16: VOLUMETRIC FLOW RATE

VAR. TYPE # VAR. UNITS VAR. TYPE MULT. FACTOR ADD. FACTOR
1 m3/hr VF1 1 0
2 m3/s VF2 2.77778 E-04 0
3 l/hr VF3 1000 0
4 l/s VF4 0.277778 0
5 ft3/s VF5 9.80958 E-03 0
6 ft3/hr VF6 35.3144 0
7 gpm VF7 4.40286 0
Table 7.4.4.12-17: FLUX

VAR. TYPE # VAR. UNITS VAR. TYPE MULT. FACTOR ADD. FACTOR
1 kJ/hr-m2 IR1 1 0
2 W/m2 IR2 0.277778 0
3 BTU/hr-ft2 IR3 8.8055 E-02 0
Table 7.4.4.12-18: THERMAL CONDUCTIVITY

VAR. TYPE # VAR. UNITS VAR. TYPE MULT. FACTOR ADD. FACTOR
1 kJ/hr-m-K KT1 1 0
2 W/m-K KT2 0.277778 0
3 BTU/hr-ft-R KT3 0.160497 0
Table 7.4.4.12-19: HEAT TRANSFER COEFFICIENTS

VAR. TYPE # VAR. UNITS VAR. TYPE MULT. FACTOR ADD. FACTOR
1 kJ/hr-m2-K HT1 1 0
2 W/m2-K HT2 0.277778 0
3 BTU/hr-ft2-R HT3 4.89194 E-02 0
Table 7.4.4.12-20: DYNAMIC VISCOSITY

VAR. TYPE # VAR. UNITS VAR. TYPE MULT. FACTOR ADD. FACTOR
1 N-s/m2 VS1 1 0
2 kg/m-s VS2 1 0
3 poise VS3 10 0
4 lbf-s/ft2 VS4 2.08854 E-02 0
5 lbf-hr/ft2 VS5 5.80151 E-06 0
6 lbm/ft-hr VS6 2419.08 0
Table 7.4.4.12-21: KINEMATIC VISCOSITY

VAR. TYPE # VAR. UNITS VAR. TYPE MULT. FACTOR ADD. FACTOR
1 m2/s KV1 1 0
2 m2/hr KV2 3600 0
3 ft2/s KV3 10.7639 0
4 ft2/hr KV4 3.87501 E+04 0
Table 7.4.4.12-22: MISCELLANEOUS

VAR. TYPE
Dimensionless DM1
Degrees DG1
Percentage PC1

7117
TRNSYS 17 Programmer's Guide

Month MN1
Day DY1
Hour TD1
Control function CF1
Volts VO1
Ampere CU1
Ohm RE1
Ampere-hour AH1

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

IU the unit number of the user-written component routine calling the


EQUATER subroutine (integer variable)
INNO the input number with the undetermined input type (integer
variable)
INDES the desired input variable type - not used in this capacity, set to
NAV for not available (3-character variable)
TRUTYP a 3 character array returning the output variable type connected
to this input (this is the desired result for this application) (3
character variable)
OUTU the unit number of the output connected to the unknown input
(not used in this capacity) (integer variable)
OUTNO the output number of the OUTU unit connected to the unknown
input (not used in this capacity) (integer variable)
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 the multiplication factor for the OUTDES variable - not used in
this capacity (double precision value)
A2 the addition factor for the OUTDES variable - not used in this
capacity (double precision value)
ICK1 error flag for calculation (1 = error found) (integer variable)

7118
TRNSYS 17 Programmer's Guide

ICK2 error flag for calculation (1 = error found) (integer variable)


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.

7119
TRNSYS 17 Programmer's Guide

7.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 (integer) the Fortran logical unit number ASSIGNed to the data


file that is to be rewound.
SKIP (integer) the number of lines that should be skipped in the data
file once it is rewound.
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 (integer) an error code that is returned by the Rewind routine and
is set to zero if no errors were encountered while rewinding the
data file or skipping lines and which is set to a vale of 1 if errors
were encountered.

EXAMPLE

The following example shows the usage of the Rewind routine and a possible method for
checking whether errors occurred during the rewind process.
Use TrnsysFunctions
...
Integer :: LU,SKIP,iUnit,iType,iError
...
LU = jfix(getParameterValue(1)) ! the jfix() function turns a double precision
! value into an integer.
SKIP = 10
iUnit = getCurrentUnit
iType = getCurrentType
Call Rewind(LU,SKIP,iUnit,iType,iError)
If (iError == 1) Then
Return
EndIf
...

7120
TRNSYS 17 Programmer's Guide

7.4.4.14. SolarCellPerformance (formerly SOLCEL)


SolarCellPerformance models silicon cell I-V characteristics. Its argument list is slightly different
than it was in TRNSYS versions 16.x and earlier (at which time it was known as SOLCEL).

Contributor: Professor Don L. Evans, Arizona State University. Tempe, AZ 85281


(Provided as-is. Check the source code for additional information)

The SolarCellPerformance 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 6F10.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 A low temperature reference ( C); (43)
TH A high temperature reference ( C); (175)
CL A low reference concentration; (6)
CH A high reference concentration; (20)
VOCLL Open circuit voltage of a cell at temperature TL and concentration CL (volts);
(0.625)
ISCLL Short circuit current of the cell at temperature TL and concentration CL (amps);
(0.649)

THIRD RECORD:
ISCLH Short circuit current of the cell at temperature TL and concentration CH (amps);
(0.625)
ISCHL Short circuit current of the cell at temperature TH and concentration CL(amps);
(2.16)
ISCHH Short circuit current of the cell at temperature TH and concentration CH(amps);
(2.16)
ACELL Gross cell area (m2); (0.0004)
EG Cell band gap at 0 Kelvin; (14000)
AOMIN Value of Ao. at concentration of 0; (1)

FOURTH RECORD:

7121
TRNSYS 17 Programmer's Guide

DAODC Slope of the Ao. vs concentration curve; (0.018)

RSH Shunt resistance (ohms); (10000)

RSMIN Value of series resistance when it becomes essentially independent of


concentration (ohms); (0.01)
CONTR Minimum concentration for which the series resistance can be considered to be
equal to RSMIN; (10)
DRSDC Slope of the series resistance vs concentration curve below a concentration
CONTR; (-0.005)
NSER Number of cells to be wired in series in the array (10)

7122
TRNSYS 17 Programmer's Guide

7.4.4.15. SolveDiffEq (formerly DIFFERENTIAL_EQN, and


DIFFEQ)
The double precision utility routine SolveDiffEQ provides an analytical solution to first-order linear
differential equations that can be written as

dT
= aT + b Eq. 7.4.4-48
dt

The designation double precision means that the arguments and results of the utility routine
SolveDiffEq must be declared in the calling Type as DOUBLE PRECISION variables as opposed
to REAL or INTEGER variables.

Users intending to utilize the Powells method TRNSYS solver (SOLVER 1) should use the
SolveDiffEq subroutine discussed here instead of the numerical derivative solver (the DTDT
array) discussed in section 7.4.5. The form of the call to SolveDiffEq is:
Double Precision :: time,AA,BB,TI,TF,TBAR
...
Call SolveDiffEq(AA, BB, TI, TF, TBAR)
where

AA (double precision) is the a coefficient of the differential equation


BB (double precision) is the b coefficient of the differential equation
TI (double precision) is the value of the dependent variable (T) at
the beginning time step
TF (double precision) is the value of the dependent variable (T) at
the end of the time step
TBAR (double precision) is the average value of the dependent variable
over the time step.
The SolveDiffEq 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.)

SolveDiffEq 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) SolveDiffEq requires the arguments AA, BB, and TI, while returning TF and TBAR. For
calls to SolveDiffEq 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 7.4.4.17.

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,

7123
TRNSYS 17 Programmer's Guide

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
C = (UA) L (TR Ta ) Eq. 7.4.4-49
dt

This can be written in the form of Eq. 7.4.4-48 if

(UA) L (UA) L Ta
a= and b= Eq. 7.4.4-50
C C
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 :: ti,aa,bb,ual,ta,c,qLoss,tf,tBar
...
C PERFORM FIRST CALL MANIPULATIONS
If (getIsFirstCallOfSimulation() ) Then
...
!reserve space in the dynamic storage structure
Call setNumberStoredVariables(0,1) !0 static spots, 1 dynamic spot.
...
!set initial values of the variables in the dynamic storage structure
Call setDynamicArrayInitialValue(1,10.d0)
!return to the calling program
Return
EndIf
...
!The following section is executed at every iteration.
ti = getDynamicArrayValueLastTimestep(1)
aa = -ual/c
bb = ual*ta/c
Call SolveDiffEq(aa,bb,ti,tf,tbar)
Call setDynamicArrayValueThisIteration(1,tf)
qLoss = ual*(tbar - ta)
...
One subtlety in the above example is well worth noting. Note that the call to SolveDiffEq is made
with the temperature at the start of the time step (ti) and that SolveDiffEq returns both the
temperature at the end of the time step (tf) and the average temperature over the time step (tbar).
TRNSYS outputs are (almost) always the average value over a time step so the calculation of
qLoss is made using tbar. However, the differential equation solver will need to know the
temperature at the end of the time step in order to have a correct initial value at the next time
step. Thus it is the final temperature (tf) that is stored using the call to
setDynamicArrayValueThisIteration().

7124
TRNSYS 17 Programmer's Guide

It is worth noting that the code above makes use of the Dynamic Data Storage feature introduced
in Trnsys17 (i.e. the functions setNumberStoredVariables(), setDynamicArrayInitialValue(),
setDynamicArrayValueThisIteration(), and getDynamicArrayValueLastTimestep()). Components
written using the Trnsys16 coding standard would instead make use of calls to the
setStorageVars() and getStorageVars() subroutines. The same example is repeated using the
older coding standard. NOTE: components using the Trnsys17 coding standard cannot directly
use the following code because the contents of the info() array is not passed to them.
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 (isEndOfTimestep()) Then
Call getStorageVars(stored,nS,info)
stored(1) = stored(2)
Call setStorageVars(stored,nS,info)
EndIf
...
!The following section is executed at every iteration.
Call getStorageVars(stored,nS,info)
ti = stored(1)
aa = -ual/c
bb = ual*ta/c
Call SolveDiffEq(aa,bb,ti,tf,tbar)
stored(2) = tf
qLoss = ual*(tbar - ta)
Call setStorageVars(stored,nS,info)
...

For this particular example (and regardless of coding standard), 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.

In TRNSYS version 16.x, this subroutine was called Differential_Eqn but had all the same
arguments and return values. A single precision version of the routine (called DIFFEQ) is also
available.

7125
TRNSYS 17 Programmer's Guide

7.4.4.16. Steam_Properties (formerly STEAM_PROPS and


STEAM)
The double precision Steam_Properties routine and its legacy double and single precision
counterparts STEAM_PROPS and STEAM are used to calculate the thermodynamic properties of
steam based on correlations from the National Bureau of Standards. Given two state properties,
the Steam_Properties routine will return the complete state of the fluid. A call to
Steam_Properties is of the form
Character (len=2) :: UNITS
Double Precision :: PROP(7)
Integer :: iTYPE,iERR
...
Call Steam_Properties(UNITS,PROP,iTYPE,iERR)
where

UNITS two character variable denoting unit system to be employed by


the fluids routine; SI for metric units and EN for english units
PROP double precision array holding the two known thermodynamic
properties of steam upon entry and the complete state upon
return from the Steam_Properties routine. This array must be
dimensioned to 7 in the routine that calls Steam_Properties.
Each location in this array is described below:
PROP(1) (double precision) temperature of the steam (F, C)
PROP(2) (double precision) pressure of the steam (PSI, MPa)
PROP(3) (double precision) enthalpy of the steam (BTU/lbm, kJ/kg)
PROP(4) (double precision) entropy of the steam (BTU/lbm R, kJ/kg K)
PROP(5) (double precision) quality (0 < x < 1)
PROP(6) (double precision) specific volume (ft3/lbm, m3/kg)
PROP(7) (double precision) internal energy (BTU/lbm, kJ/kg)
ITYPE integer variable denoting which two properties are supplied as
known properties. ITYPE = 10* PROP indicator 1 + PROP
indicator 2 (12 to 76)
IERR an integer variable returning the error messages from the
Steam_Properties call:
= 0 - no error found, calculations completed
> 0 - error found, calculations could not be completed
The legacy subroutines STEAM_PROPS and STEAM required a 5th argument *N following the
iErr argument.
*N the corresponding line number to jump to if the subprogram is
present
An example illustrating the use of the Steam_Properties routine is shown with the following
considerations: SI units are desired, and Temperature (PROP(1)) and Quality (PROP(5)) are
known.

7126
TRNSYS 17 Programmer's Guide

Use TrnsysFunctions
...
Character (len=2) :: units
Double Precision :: prop(7),temperature,quality,pressure,enthalpy
...
units = SI !SI units are desired.
...
temperature = getInputValue(1)
quality = getInputValue(2)
...
prop(1) = temperature
prop(5) = quality
iType = 15
Call Steam_Properties(units,prop,iType,iErr)
If (iErr > 0) Return
...
pressure = prop (2)
enthalpy = prop (3)

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.

7127
TRNSYS 17 Programmer's Guide

7.4.4.17. Storage of Data between Time Steps


Since a single Type subroutine may be used for several UNITS in one simulation, care must be
taken when storing values that are to be used from one time step to the next. If a tank model, for
instance, requires the initial tank temperature throughout the simulation, simply setting a variable
TZERO to the tank temperature during the Initialization manipulations section will not work.
When two tanks are used, the local variable TZERO will be set twice. Throughout the simulation,
it will contain the initial temperature of the second tank. As a result, the first tank will not be
modeled correctly.

One solution to this problem is to use an output; Types can reserve a few additional outputs and
store the values that they need in those spots. However, for large storage requirements, it is
recommended that a series of calls to AccessFunctions be used instead. Prior to the release of
TRNSYS v.16, structures called the S array and the STORE common block were the
recommended solution. With the release of TRNSYS v.16, three AccessFunctions
(setStorageSize(), getStorageVars() and setStorageVars) were added and recommended. With
the release of TRNSYS v.17, the concept of data storage between time steps was further
simplified into two main usages: static and dynamic. If the user has a component that was
written using an earlier coding standard, both the s array and the set/getStorageVars() functions
are retained in the kernel so that the component does not need to be modified. However, if the
user is writing a component using the TRNSYS v.17 coding standard, the user should not make
use of these earlier features as they are incompatible with the more recent standard. The
TRNSYS v.16 AccessFunctions are discussed in section 7.4.4.17.1.3 for reference.

Two situations typically arise: Static and Dynamic storage.

7.4.4.17.1.1. Static Storage

In the static storage situation, the Type calculates a value that is not going to change throughout
the simulation or that is going to change only sporadically. A good example is the solar radiation
view factor of a particular faade element in the Type34 overhang and wingwall shading
component. The user enters the dimensions of the faade, overhang, and wingwalls as
parameters of the model. The model takes those values and calculates a sky view factor for the
faade. Since the view factor is based only on parameters it need never be calculated again
unless there is more than one instance of Type34 in the simulation. The view factor calculation is
time consuming so the user might decide to calculate the view factor once during the first call
manipulations and then store the value, retrieving it only if the reread parameters manipulation
section is required. The above is an example of a static storage variable. In this situation, three
AccessFunctions would be used: setNumberStoredVariables(), setStaticArrayValue() and
getStaticArrayValue()

SETNUMBERSTOREDVARIABLES(NSTATIC,NDYNAMIC)

INTERFACE
subroutine setNumberStoredVariables(nStatic,nDynamic)
integer :: nStatic,nDynamic

DESCRIPTION

The setNumberStoredVariables AccessFunction should be called during the First Call


manipulations. This will tell the storage data structure how many spots it needs to reserve for your
component. The subroutine has two arguments:

7128
TRNSYS 17 Programmer's Guide

nStatic: The integer number of static storage spots required by this component.
nDynamic: The integer number of dynamic storage spots required by this component.
NOTE: we will not be concerning ourselves with dynamic storage in this example. Please
refer to the example immediately following for information about dynamic storage.

GETSTATICARRAYVALUE(N)

INTERFACE
subroutine getStaticArrayValue(n)
integer :: n

DESCRIPTION

When the user wants to obtain a previously stored static value a call is made to the
getStaticArrayValue AccessFunction. The AccessFunction takes the following arguments:
m: The integer index of the variable to be retrieved. If more than one variable value is to be
stored, it is up to the Type programmer to keep track of which variable is at which index.

SETSTATICARRAYVALUE(M,VAL)

INTERFACE
subroutine setStaticArrayValue(m,val)
integer :: m
double precision :: val

DESCRIPTION

When the user wants to set storage, a call is made to the setStaticArrayValue() AccessFunction.
The setStaticArrayValue() function takes the following arguments:
m: The integer index of the variable to be retrieved. If more than one variable value is to be
stored, it is up to the Type programmer to keep track of which variable is at which index.
val: A double precision variable containing the value that is to be stored.

STATIC STORAGE EXAMPLE

A tank model which uses global static storage to store the initial tank temperature might contain
the following lines:

...
C PERFORM FIRST CALL MANIPULATIONS
If (getIsFirstCallOfSimulation() ) Then
...
!reserve space in the double precision storage structure
Call setNumberStoredVariables(1,0) !1 static spot, 0 dynamic spots.
...
!return to the calling program
Return
EndIf

C PERFORM INITIAL TIME STEP MANIPULATIONS


If (getIsStartTime() ) Then
...
!set initial values of variables in the double precision storage structure

7129
TRNSYS 17 Programmer's Guide

Call setStaticArrayValue(1,T)
...
!return to the calling program
Return
EndIf
...
Call getStaticArrayValue(1,T)
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. It is well worth noting that while we refer to this kind of storage as static it is
not actually static. The user can call the setStaticArrayValue() AccessFunction whenever they
like, thereby changing the stored value.

7.4.4.17.1.2. Dynamic Storage

In the dynamic storage 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 new
initial value for the next time step. Any component that solves a differential equation is almost
invariably going to use dynamic storage because it needs to predict a final value not based on the
final value from the previous iteration but the final value from the previous time step. The Type
therefore needs to store the final value from the previous time step somewhere safe. In TRNSYS
v.16, this would have been accomplished by reserving two spots in the global storage structure.
One spot would be updated at the end of each iteration with the proposed final value. Then,
during the end of time step manipulations section, the last calculated proposed final value
would have been saved into the other global storage spot as the real final value. At the next
time step, the Type would read and base its calculations on the real final value, repeatedly
calculating a new proposed final value. With the development of TRNSYS v17, it was felt that
the end of timestep manipulations were too cumbersome and the concept of dynamic global
storage was proposed. In this case, only one storage spot is required. The Type calls the
setDynamicArrayValue() AccessFunction at the end of each iteration and bases its calculations
on what it retrieves from a call to the getDynamicArrayValue() function. The TRNSYS kernel
takes care of swapping the two values automatically at the end of a time step.

In the case of dynamic storage, four AccessFunctions are used: setNumberStoredVariables(),


setDynamicArrayInitialValue(), setDynamicArrayValueThisIteration(), and
getDynamicArrayValueLastTimestep()

SETNUMBERSTOREDVARIABLES(NSTATIC,NDYNAMIC)

INTERFACE
subroutine setNumberStoredVariables(nStatic,nDynamic)
integer :: nStatic,nDynamic

DESCRIPTION

The setNumberStoredVariables AccessFunction should be called during the First Call


manipulations. This will tell the storage data structure how many spots it needs to reserve for your
component. The subroutine has two arguments:
nStatic: The integer number of static storage spots required by this component. NOTE: we
will not be concerning ourselves with static storage in this example. Please refer to the
example immediately above for information about static storage.

7130
TRNSYS 17 Programmer's Guide

nDynamic: The integer number of dynamic storage spots required by this component.

GETDYNAMICARRAYVALUELASTTIMESTEP(N)

INTERFACE
subroutine getDynamicArrayValueLastTimestep(n)
integer :: n

DESCRIPTION

When the user wants to obtain a previously stored dynamic value a call is made to the
getDynamicArrayValueLastTimestep() AccessFunction. The AccessFunction takes the following
arguments:
m: The integer index of the variable to be retrieved. If more than one variable value is to be
stored, it is up to the Type programmer to keep track of which variable is at which index.

SETDYNAMICARRAYINITIALVALUE (M,VAL)

INTERFACE
subroutine setDynamicArrayInitialValue(m,val)
integer :: m
double precision :: val

DESCRIPTION

When the user wants to set an initial storage value, a call is made to the
setStaticArrayInitialValue() AccessFunction. The setStaticArrayInitialValue() function takes the
following arguments:
m: The integer index of the variable to be retrieved. If more than one variable value is to be
stored, it is up to the Type programmer to keep track of which variable is at which index.
val: A double precision variable containing the value that is to be stored.

SETDYNAMICARRAYVALUETHISITERATION(M,VAL)

INTERFACE
subroutine setDynamicArrayValueThisIteration(m,val)
integer :: m
double precision :: val

DESCRIPTION

When the user wants to set storage, a call is made to the setStaticArrayValueThisIteration()
AccessFunction. The setStaticArrayValueThisIteration() function takes the following arguments:
m: The integer index of the variable to be retrieved. If more than one variable value is to be
stored, it is up to the Type programmer to keep track of which variable is at which index.
val: A double precision variable containing the value that is to be stored.

DYNAMIC STORAGE EXAMPLE

7131
TRNSYS 17 Programmer's Guide

A tank model which uses global dynamic storage to keep the tank temperature at the end of the
previous time step might contain the following lines:
...
C PERFORM FIRST CALL MANIPULATIONS
If (getIsFirstCallOfSimulation() ) Then
...
!reserve space in the dynamic storage structure
Call setNumberStoredVariables(0,1) !0 static spots, 1 dynamic spot.
...
!return to the calling program
Return
EndIf

C PERFORM INITIAL TIME STEP MANIPULATIONS


If (getIsStartTime() ) Then
...
!set initial value of variables in the dynamic storage structure
Call setDynamicArrayInitialValue(1,T)
...
!return to the calling program
Return
EndIf
...
!retrieve the stored value of the initial temperature for this time step.
TZERO = getDynamicArrayValueLastTimestep(1)
...
!calculate TFINAL based on the initial temperature.
TFINAL = TZERO + ...
...
!update the storage with the calculated value of TFINAL
Call setDynamicArrayValueThisIteration(1,TFINAL)
...

7.4.4.17.1.3. DataStorage using TRNSYS v16s setStorageSize(), getStorageVars() and


setStorageVars()

The first of the three utility routines reserves a requested number of spots in the global data
structure. The second routine retrieves the values from the global storage structure that
correspond to the current Type. The third sets new values in the global structure for the current
Type. The following section provides general information about the manner in which the three
storage related utility routines are called. An example of using storage in a Type follows.

SETSTORAGESIZE

INTERFACE
subroutine setStorageSize(n,INFO)
integer :: n, INFO(15)

DESCRIPTION

The setStorageSize subroutine should be called during the First Call manipulations. 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.

7132
TRNSYS 17 Programmer's Guide

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), a call is made to the getStorageVars subroutine. The 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 retrieved. This argument allows the user to
retrieve only a subset of the stored variables. For example, if only the 5th stored variable is
desired, setting m to 5 will retrieve stored variables 1 through 5 and place them into spots 1
through 5 of storageArray
INFO: the standard INFO array is sent so that the storage data structures know what unit
and type number are requesting storage

SETSTORAGEVARS

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 during the End of Time Step manipulations section. 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 (getIsFirstCallOfSimulation() ) Then
...
!reserve space in the double precision storage structure
StorageSize = 1

7133
TRNSYS 17 Programmer's Guide

Call setStorageSize(StorageSize,INFO)
...
!return to the calling program
Return
EndIf

C PERFORM INITIAL TIME STEP MANIPULATIONS


If (getIsStartTime() ) 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
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, the end of timestep 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 END OF TIMESTEP MANIPULATIONS
If (getIsEndOfTimestep() ) 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 (getIsFirstCallOfSimulation() ) Then
...
!reserve space in the double precision storage structure
StorageSize = 2
Call setStorageSize(StorageSize,INFO)
...
!return to the calling program
Return
EndIf

C PERFORM INITIAL TIME STEP MANIPULATIONS


If (getIsStartTime() ) 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

7134
TRNSYS 17 Programmer's Guide

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)
...

7135
TRNSYS 17 Programmer's Guide

7.4.4.18. ASHRAE_Coefs (formerly TABLE_COEFS and TABLE)


The double precision subroutine ASHRAE_Coefs (and its legacy counterparts double repcision
TABLE_COEFS single precision companion TABLE) return transfer function coefficients
corresponding to the standard walls, partitions, floors, and ceilings given in the ASHRAE
Handbook of Fundamentals. Double Precision indicates that the arguments to the
TABLE_COEFS routine must be declared in the calling Type as DOUBLE PRECISON instead
of as REAL variables. The single precision version (called TABLE) was the only version available
in TRNSYS version 15.x and below. It was retained for backwards compatibility but every effort
should be made to use the double precision version: ASHRAE_Coefs. ASHRAE_Coefs differs in
its argument list from the legacy routine TABLE_COEFS. The ASHRAE_Coefs routine is used by
the TYPE 19 Zone Model. A call to ASHRAE_Coefs is of the form:
Integer :: ITYPE,NTABLE, IU,NBS,NCS,NDS
Double Precision :: B,C,D
...
Call ASHRAE_Coefs(ITYPE,NTABLE,IU,NBS,NCS,NDS,B,C,D)
where

ITYPE an integer variable equal to 1, 2, or 3 denoting which type of


surface is desired. ITYPE = 1 corresponds to roof coefficients,
ITYPE = 2 is for exterior walls, and ITYPE = 3 denotes interior
partitions, floors and ceilings. The tables containing the surface
descriptions can be found in the documentation for TYPE 19;
both in this manual and in the Component Description manual.
NTABLE (integer) number of wall, roof, etc., from the table specified by
ITYPE.
NBS (integer) the number of b coefficients for the desired wall as
returned by the subroutine.
NCS (integer) the number of c coefficients for the desired wall as
returned by the subroutine.
NDS (integer) the number of d coefficients for the desired wall as
returned by the subroutine.
B a double precision array dimensioned to 10 that contains the b
coefficients. These are the coefficients for the current and
previous sol-air temperatures (i.e. bo to bNBS-1).
C a double precision array dimensioned to 10 that contains the c
coefficients. These are the coefficients for the current and
previous room temperatures (i.e. co to cNCS-1).
D a double precision array dimensioned to 10 that contains the d
coefficients. These are the coefficients for the previous heat
fluxes (d1 to dNDS).
The obsolete versions of this routine (TABLE_COEF and TABLE) also took an additional 10th
argument (*N) following the D() array argument:
*N the corresponding line number to jump to if the subprogram is
present.
Subroutine ASHRAE_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

7136
TRNSYS 17 Programmer's Guide

coefficients are stored internally within the subroutine for use on subsequent calls to
ASHRAE_Coefs.

Note: Transfer function coefficients in the file ASHRAE.COF are different from
those actually found in the ASHRAE handbooks. Because the TYPE 19 single-
zone 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.

7137
TRNSYS 17 Programmer's Guide

7.4.4.19. Tau_Alpha (formerly TALF)

GENERAL DESCRIPTION

The double precision function Tau_Alpha and its obsolete single precision counterpart TALF
calculate the transmittance-absorptance product () of a solar collector as a function of angle of
incidence of radiation and collector construction. The transmittance of one or more sheets of
glass or plastic can be obtained by specifying an absorptance of 1. Tau_Alpha is a double
precision routine, meaning that all but its first argument must be declared in the calling Type as
double precision variables (as opposed to REAL variables). The value returned by Tau_Alpha is
also double precision. In TRNSYS versions 15.x and below, Tau_Alpha was known simply as
TALF, which was a single precision routine. TALF was retained for backwards compatibility and
every effort should be made to use the double precision Tau_Alpha routine.

A call to function Tau_Alpha is of the form


Double Precision :: TAUALF,TAU_ALPHA,THETA,XKL,REFRIN,ALPHA,RHOD
Integer :: N
...
TAUALF = TALF(N,THETA,XKL,REFRIN,ALPHA,RHOD)
The function arguments are interpreted as follows:

N (integer) number of covers


THETA (double precision) angle of incidence (degrees)
XKL (double precision) product of cover thickness and extinction
coefficient
REFRIN (double precision) index of refraction
ALPHA (double precision) absorber surface absorptance
RHOD (double precision) reflectance of the N covers to diffuse radiation
If the value of RHOD is not known, then Tau_Alpha 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 Tau_Alpha is then set to this
value so that on subsequent calls to Tau_Alpha the value of RHOD may be supplied.

Due to FORTRAN considerations, functions cannot 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:

7138
TRNSYS 17 Programmer's Guide

perpendicular parallel

sin 2 (1 2 ) tan 2 (1 2 )
1 = Eq. 7.4.4-51 2 = Eq. 7.4.4-52
sin 2 (1 + 2 ) tan 2 (1 + 2 )

The angles 1 and 2 are related by Snell's Law with the index of refraction for air of unity.

sin 1
sin 2 = Eq. 7.4.4-53
ng
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]:

a (1 i ) 2
Ti ,1 = Eq. 7.4.4-54
1 a i
2 2

a 2 (1 i ) 2
Ri ,1 = i 1 + 2
Eq. 7.4.4-55
1 a i
2

The internal transmittance, a, is a function of the extinction length and the transmission angle.

kL
a = exp Eq. 7.4.4-56
cos 2
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 = Eq. 7.4.4-57
1 Ri ,1Ri , N 1
Ri ,1Ti , N
Ri , N = Ri , N 1 + Eq. 7.4.4-58
1 Ri ,1Ri , N 1
The transmittance-absorptance product of the collector plate and glazing assembly can then be
calculated as

( ) =
(T1, N + T2, N )
Eq. 7.4.4-59
2(1 (1 ) RD )

where RD is the reflectance of the N covers to diffuse radiation. RD is calculated as the


reflectance for specular radiation at 60 incident angle.

7139
TRNSYS 17 Programmer's Guide

7.4.4.20. 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. With TRNSYS versions 16.x and below,
almost all Types (whether standard or user-written) made various direct calls to the TYPECK
routine, setting the IOPT argument appropriately. With the release of TRNSYS 17, it was
recommended that users wishing to write their own components make use of various access
functions (see section 7.4.2) in place of direct calls to TYPECK. The form of a TYPECK call is:
Integer :: IOPT,INFO(15),NI,NP,ND
...
Call TYPECK(IOPT,INFO,NI,NP,ND)
where

IOPT- indicates to TYPECK what kind of check to perform:


<0 the compilation will be terminated immediately after
printing an explanatory error message.
>0 the simulation will be terminate after all UNITS have
been called once or 20 error messages have been
issued.
1 or -1 check the number of user furnished INPUTS,
PARAMETERS, and DERIVATIVES from the INFO
array against the values of NI, NP, and ND. An error
message will be printed only if TYPECK finds an
error.
2 or -2 TYPE routine has found unspecified error and wants
TYPECK to flag it.
3 or -3 TYPE routine has found a bad INPUT or number of
INPUTS and wants TYPECK to flag it.
4 or -4 TYPE routine has found a bad PARAMETER or
number of PARAMETERS and wants TYPECK to
flag it.
5 or -5 TYPE routine has found a bad DERIVATIVE or
number of DERIVATIVES and wants TYPECK to
flag it.
6 TYPE routine has determined that the maximum
number of UNITS of that TYPE has been exceeded
and wants TYPECK to flag it and stop the
simulation.
INFO- TYPE's INFO array containing pertinent bookkeeping data on the
UNIT (see Section 7.4.2.49).
NI- correct number of INPUTS
NP- correct number of PARAMETERS
ND- correct number of DERIVATIVES

7140
TRNSYS 17 Programmer's Guide

7.4.4.21. View_Factors (formerly VIEW)

GENERAL DESCRIPTION

The double precision function View_Factors (and its obsolete single precision companion VIEW)
calculate the view factor between two planer rectangles of any orientation. For common
orientations, analytical expressions are used. A call to View_Factors is of the form:
Integer :: iType,nA1,nA2
Double Precision :: A,B,C,D,E,F,G,H,X3,Y3,Z3
...
F21 = View_Factors(iType,A,B,C,D,E,F,G,H,X3,Y3,Z3,nA1,nA2)
The integer variable iType defines the type of orientation between the two surfaces. There are
five possibilities as described by the following Figures. 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
A
C
Figure 7.4.4.21-1:ITYPE=1; parallel identical rectangles.

1
B

C
Figure 7.4.4.21-2: ITYPE=2; perpendicular rectangles with a common edge.

E G
B D 1
F
2

A
C

7141
TRNSYS 17 Programmer's Guide

Figure 7.4.4.21-3: ITYPE=3; nonidentical parallel rectangles.

B F
1
D E

C
Figure 7.4.4.21-4: ITYPE=4; perpendicular rectangles without a common edge.

(X2, Y2, Z2)

(X1, Y1, Z1)


1
(X3, Y3, Z3)
Z

2 B
X
(0, 0, 0) A
Figure 7.4.4.21-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 7.4.4.21-1 is determined with the following
expression taken from Reference 1.

(1 + X 2 )(1 + Y 2 )
1/ 2
2 X
F21 = ln + 1 + Y 2 tan 1
XY 1+ X + Y
2 2
1+ Y 2
Eq. 7.4.4-60
Y
+ Y 1 + X 2 tan 1 X tan 1 X Y tan 1 Y
1+ X2

where,
X = A/C
and
Y = B/C

7142
TRNSYS 17 Programmer's Guide

ITYPE = 2

From Reference 1, the view factor from surface two to one of Figure 7.4.4.21-2 is

F21 =
1
{ 1 1
Y tan 1 + X tan 1 X 2 + Y 2 tan 1
1
Y Y X X2 +Y2

+ ln
( )(
1 1 + Y 2 1 + X 2 ) Y (1 + X
2 2
+Y 2 ) X (1 + X
Y2 2 2
+Y 2 ) X2

Eq. 7.4.4-61

4 1+ X 2 + Y 2 (1 + Y )(X
2 2
+Y 2 ) (1 + X )(X 2 2
+Y 2 )

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:

F d 1 2 dA1
Eq. 7.4.4-62
F21 =
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
1 Xi Yi Yi Xi

Fd 1 2 = tan 1 + tan 1 Eq. 7.4.4-63
i =1 2 1 + X 2 1 + Xi
2
1 + Yi
2
1 + Yi
2
i

where
Ai B
Xi = 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.

7143
TRNSYS 17 Programmer's Guide

ITYPE = 4
The view factor from surface 2 to 1 of Figure 7.4.4.21-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
1 1 1 Yi 1

Fd 1 2 = tan tan 1 Eq. 7.4.4-64
i =1 2 Yi X i + Yi
2 2 2 2
X i + Yi

where
A C'
Xi = 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 7.4.4.21-5, the view factor
from 2 to 1 is:
1 cos 1 cos 2
F21 =
A2
A1 A2 S 2
dA2 dA1 Eq. 7.4.4-65

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. 7.4.4-66

where (Xd1,Yd1,Zd1) and (Xd2,Yd2,Zd2) are the coordinates of the elemental areas on surfaces
1 and 2, respectively. For Surface 2,

Z d1 Z d 2
cos 2 = Eq. 7.4.4-67
S

7144
TRNSYS 17 Programmer's Guide

For Surface 1,
v v
SN
cos 1 = Eq. 7.4.4-68
N S
v
where 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
surface 1.

In general,
v v v v
S = sxi + s y j + sz k Eq. 7.4.4-69
v v v v
N = nx i + n y j + nz k Eq. 7.4.4-70
v v v
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
S x nx + S y n y + S z nz
cos = Eq. 7.4.4-71
Sx + S y + Sz nx + n y + nz
2 2 2 2 2 2

where,
Sx = Xd2 - Xd1 Eq. 7.4.4-72
Sy = Yd2 - Yd1 Eq. 7.4.4-73
Sz = Zd2 - Zd1 Eq. 7.4.4-74

If nz is arbitrarily chosen to be 1, then

K n yY 1 Z1
nx = Eq. 7.4.4-75
X1
X2 X2
K 1 + Z1 Z 2
ny = X1 X1
Eq. 7.4.4-76
X2
Y2 Y1
X1

where,

X3 X2 X2 X3
Z1 Z 3 Y 2 Y 1 Z1 Z 2 Y 3 Y 1
K=
X1 X1 X1 X1
Eq. 7.4.4-77
X 2 X 3 X 3 X2
1 Y 3 Y 1 1 Y 2 Y 1
X 1 X1 X 1 X1

7145
TRNSYS 17 Programmer's Guide

The coordinates X1, X2, X3, Y1, Y2, Y3, Z1, Z2, Z3 are as defined in Figure 7.4.4.21-5.

7146
TRNSYS 17 Programmer's Guide

7.4.5. Solving Differential Equations


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
SolveDiffEq (see Section 7.4.4.15), and a numerical solution using one of three numerical
methods (see Manual 06-TRNEdit). The analytical method is recommended whenever practical it
is possible to write the differential equation in the following general form:

dT
= aT + b Eq. 7.4.5-1
dt
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 SolveDiffEq subroutine whenever possible.

Numerical solutions to differential equations, when required can be obtained through use of the
getNumericalDerivative(). Prior to the release of TRNSYS 17, these values were accessed
through the DTDT and T arrays in the subroutine argument list). To use a very simple example, if
the equation

dT
Q& i = C 1 Eq. 7.4.5-2
dt
were part of the mathematical model and the DERIVATIVE of the temperature T1 with respect to
& and a constant value C, it would appear
time t were to be integrated for a known heat flow rate Q
in the Type subroutine in a manner similar to that shown below.

Double Precision :: qDot,C


...
Call setNumericalDerivative(1,qDot/C)
...
Call setOutputValue(2,getNumericalSolution(1))
...
As a point of reference, this same code would appear in TRNSYS coding standards prior to that
of version 17.x as the following:
Double Precision :: qDot,C
.
.
DTDT(1) = qDot / C
.
.
OUT(2) = T(1)
.
.

DTDT(1) is the differential dT1/dt and is registered in the kernel by the Type calling the
setNumericalDerivative function. T(1) is the result of numerically integrating DTDT(1); it is
retrieved by the Type through the call to getNumericalSolution. In this example T1 is also desired
to be the second OUTPUT. The Type stores this value through a call to the setOutputValue()
routine. T(n) will always be the result of integrating DTDT(n). The numerical differential equation

7147
TRNSYS 17 Programmer's Guide

solution returns the average value over the time step, not the final value at the end of the time
step.

A DERIVATIVES control statement followed by an initial values line must be included among the
component control statements for any model which uses the numerical integration feature. The
presence of a DERIVATIVES command signals TRNSYS to integrate derivatives placed in the
kernels global DTDT array by means of a call to setNumericalDerivative() and to make results
available in the global T array (which is accessed by a Type calling getNumericalSolution()),
repeating the procedure at each time step 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 getIsFirstCallOfSimulation() returns a true result (when INF0(7) = - 1) see Section
7.4.2.49 for additional information.

7148
TRNSYS 17 Programmer's Guide

7.4.6. Use of the Alternate Return (RETURN 1)


In the coding standards between TRNSYS 14.1 and 16.x (inclusive) TRNSYS checked to make
sure that all routines required by the TRNSYS input file were included in the TRNSYS executable
file by utilizing the FORTRAN alternate return. In previous TRNSYS versions (prior to 14.1) run
with compilers allowing unresolved externals, unlinked subroutines were not checked and were
often the source of strange errors. In TRNSYS versions 17 and later, the link check was made in
a manner that did not require the alternate return. Since the alternate return was a difficult
concept for users to grasp, its use was sunsetted. This section is included in the documentation in
case users encounter Types that use the RETURN 1 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 !
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 written with coding standards between 14.1 and 16.x (inclusive) 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 written with coding standards between 14.1 and 16.x (inclusive) 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
7.4.4.4).

4) 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.

7149
TRNSYS 17 Programmer's Guide

7.4.7. Use of the ICNTRL Array


The ICNTRL array, which was new to version 14, conveyed to the component subroutines
(TYPE1, TYPE2, etc.) and to the TRNSYS equation processor, the states of discrete controller
variables when the Powells Method solver was employed in a simulation. With the release of the
TRNSYS 17 component coding standard, the ICNTRL() array was no longer passed to Types
through an argument list but was made available through the access functions
setNumberofDiscreteControls() and setDesiredControlState(). Refer to sections 7.4.2.78 and
7.4.2.79 respectively for additional information.

With the release of TRNSYS 14, the Powells Method control strategy was designed to eliminate
the problems caused by the Successive Substitution TRNSYS controllers sticking in order to
solve the system of equations (see Manual 06-TRNEdit). With TRNSYS 14, the TRNSYS kernel,
rather than the component models, directly controlled discrete variables. When the Powells
Method solver is selected by the user, 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 Powells Method control strategy into user-written component routines, the
ICNTRL and INFO arrays must be set up correctly. The setNumberofDiscreteControls() access
function should be called to set INFO(11) to the number of discrete control variables in the
component routine. The setDesiredControlState() access function should be called so that
ICNTRL(2*i) contains the desired at the current iteration. The TRNSYS kernel takes care of
setting ICNTRL(2*(i-1)+1), which contains the previously converged solution for controller i in the
component model (controlled by the TRNSYS processor).

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 = getParameterValue(1) ! UPPER DEAD BAND TEMP. DIFFERENCE
LDB = getParameterValue(2) ! LOWER DEAD BAND TEMP. DIFFERENCE
.
If (getIsFirstCallofSimulation) Then
.
setNumberofDiscreteControls(1) ! 1 CONTROL VARIABLE
.
EndIf
.
.
TH = getInputValue(1) ! UPPER INPUT TEMPERATURE
TL = getInputValue(2) ! LOWER INPUT TEMPERATURE
.
.
oldState = ICNTRL(1) ! CONTROL STATE AT PREVIOUS SOLUTION

7150
TRNSYS 17 Programmer's Guide

newState = oldState

If (oldState == 1) Then
If((TH-TL) < LDB) newState = 0
Else
If(TH-TL) > UDB)) newState = 1
EndIf
ICNTRL(2) = newState
.
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
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.

7151
TRNSYS 17 Programmer's Guide

7.4.8. Converting Types from earlier TRNSYS Versions


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.

7.4.8.1. Converting components from version 13.x to version


14.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,*)
2) Replace all RETURN statements in the subroutine with RETURN 1
Failure to replace all returns will result in an unlinked subroutine error. (see Section
7.4.6)

3) Change control algorithms to accommodate the Powells Method control strategy


(Optional) (see Section 7.4.7)

4) Change the XIN and OUT arrays to DOUBLE PRECISION variables. (see Section
7.3.2)

5) Change the INFO array dimension from 10 places to 15. (see Section 7.4.2.49)

6) Define the input and output variable types in the YCHECK and OCHECK arrays and
call the RCHECK subroutine to perform input/output checking. (see Section 7.4.4.12)

7) All calls to the following routines should be modified to include the link checking
option: DATA,ENCL,TABLE,INVERT,DINVRT,FIT,DFIT and PSYCH. (see Section
7.4.4.4)

7.4.8.2. Converting components from version 14.1 to version


14.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) Change any statements that contain a STOP statement from:


STOP
to the following if the Stop occurred in the primary Type subroutine:

7152
TRNSYS 17 Programmer's Guide

CALL MYSTOP(1001)
RETURN 1
or to the following if the Stop occurred in a secondary subroutine:
CALL MYSTOP(1001)
RETURN
The number 1001 can be changed to another error number if so desired.

2) Windows does not allow any write-to-screen statements. Any WRITE or PRINT
statements that print to the screen such as:
WRITE (*,*) There is an error in this type.
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

7.4.8.3. Converting components from version 14.2 to version


15.x
There are no modifications necessary to a TRNSYS 14.2 Type in order for it to be used with
TRNSYS version 15.x.

7.4.8.4. Converting components from version 15.x to version


16.x
TRNSYS 15 components can be updated to TRNSYS 16 in two ways:
After 2 steps that do not require any programming knowledge, you can run TRNSYS
15 Types in a "legacy TRNSYS 15" mode, where all the information exchange with the
Kernel is identical to what was happening in TRNSYS 15. This implies that you will not
benefit from some of the new features:
General use of double precision
Added security and user-friendliness thanks to access functions, etc.
Drop-in DLL's: Types running in "legacy TRNSYS 15 mode" must be linked to the
main TRNSYS DLL (TRNDll.dll).
You will also have to be careful if you are interested in the system response just after
initialization: Because of the change in the definition of the initial time step, TRNSYS 15
Types might give an incorrect answer just after the simulation start.
Simple components can be put into external DLLs in legacy mode. However, if the Type
needs to call one of the TRNSYS utility routines, it needs to be fully updated so that it can
call the double precision versions of those routines instead of the outdated single precision
versions.
You can also fully convert an existing component to the TRNSYS 16 standard by
following a systematic procedure. The difficulty of that procedure and the time required to
perform the conversion will depend on the way the existing Type is coded: heavy access to
Kernel variables through common blocks, use of Fortran functions specific to single precision
variables, etc.

7153
TRNSYS 17 Programmer's Guide

Steps to use TRNSYS 15 components in "legacy mode"

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
7.4.8.4.1.3. Note that the steps listed in this section are also required to fully convert existing
TRNSYS 15 Types. NOTE: If you choose to use your component in legacy mode the
Type cannot be placed in an external DLL; it must be compiled and linked into TRNDll.dll
along with TRNSYSs standard components.

7.4.8.4.1.1. Export the name of the routine (Typennn)

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.

7.4.8.4.1.2. Version sign the Type

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.

7154
TRNSYS 17 Programmer's Guide

7.4.8.4.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
%TRNSYS17%\SourceCode\Include (%TRNSYS17% is your installation directory). Note that
Param.inc is obsolete and that TRNSYS 16 (and more recent) Types should use the global
constants declared in the TrnsysConstants module (see section 7.4.8.4.1.7 for details).

Instructions to convert TRNSYS 15 Types to the TRNSYS 16 standard

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 sections 7.4.8.1, 7.4.8.2, and 7.4.8.3, of this manual.

7.4.8.4.1.4. Export the name of the routine (TYPEnnn)

See section 7.4.8.4.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.

7.4.8.4.1.5. Special calls identified by INFO(7:8) and INFO (13)

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 7.4.2.49. The following sections just outline the
changes to existing TRNSYS 15 Types.

VERSION SIGN CALL (INFO(7) = -2)

See section 7.4.8.4.1.2, here above, for details. 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) = 16
return 1
endif
By adding the above, you have signaled to TRNSYS that your component was written using the
TRNSYS 16 standard.

INITIALIZATION (PRE-SIMULATION) CALL (INFO(7) = -1)

The INFO(7) = -1 call is still intended to allow components to perform initializations, as in


TRNSYS 15. However, due to the new specification of TIME in TRNSYS, the manipulations
required at INFO(7) = -1 have changed. The manipulations that your component should do at
INFO(7) = -1 are the following:

7155
TRNSYS 17 Programmer's Guide

Set INFO(6) to the number of output spots needed by the component.


Set INFO(9) so that your Type will be called in the proper manner (see section 7.4.2.49 for
details).
Handle data storage initialization:
Set INFO(10) to the number of storage spots required in the single precision storage
structure (in other words, use the S array).
Call SetStorageSize to reserve space in the double precision storage structure. See
section 7.4.8.4.1.9 for more information.
Call TYPECK to have TRNSYS check whether the correct number of Inputs, Outputs and
Parameters were specified in the deck.
Call RCHECK to have TRNSYS check the units of the Input Output connections in the deck.
RETURN 1: no other manipulations should be made during this call.

Note that reading parameters and process them can be realized either during this call or during
the initial time step (see "TIME = TIME0 call" here below). You should be careful to handle all
operations that must be done only once (e.g. file opening) in only one of those initial calls.

NEW SIGNIFICANCE OF THE FIRST TIME STEP (TIME = TIME0)

In TRNSYS 16, the time specified in the simulation cards ("Simulation Start Time" in the
Simulation Studio) became the exact moment at which the simulation starts. This is different from
TRNSYS 15, where the so-called simulation start was the time at the end of the first time step. In
TRNSYS 16, components are called at TIME = TIME0 and they should just output their initial
values at that call. There are no iterations for that time step.

The manipulations that a component should make at TIME = TIME0 are:


read parameter values and set them to local variable names
check parameters for validity. For example, you might want to check to see if the specified
specific heat is negative and generate an error if it is. Note that
set outputs to initial conditions or 0
return 1: no other manipulations should be made during this call.

"POST CONVERGENCE" CALL (INFO(13) = 1)

All components that are signed as having been written for version 16 are called once more at the
end of every time step after convergence has been reached. This modification was made in order
to simplify the use of storage (the TRNSYS 15 S array) and other operations that must be done
after convergence has been reached, such as printing or integration. If your component does not
use storage and is not a printer or an integrator, then you may simply add the lines:
! Perform post-convergence operations
if(INFO(13) > 0) then
return 1
endif
If your component does use storage, then you should add lines that set up your local storage
array, and then send the values to global storage using a call to the setStorageVars subroutine as
explained in section 7.4.8.4.1.9.

FINAL CALL AFTER THE SIMULATION IS DONE (INFO(8) = -1)

7156
TRNSYS 17 Programmer's Guide

This call has not changed between TRNSYS 15 and 16. At the very end of a TRNSYS simulation,
each Type is called one last time with INFO(8) = -1. If your Type does not contain any handling of
INFO(8) = -1, it will simply run through its calculations one last time and probably no harm will
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:
! Perform last call manipulations
if(INFO(8) == -1) then
return 1
endif
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.

7.4.8.4.1.6. Double precision variables

One of the other focuses of version 16 developments 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
The correct way of performing the above is the following:
RealVariable = sngl(DoublePrecisionVariable)

7157
TRNSYS 17 Programmer's Guide

To go the other way, you need the following:


DoublePrecisionVariable = dble(RealVariable)

7.4.8.4.1.7. Access to global constants: the "TrnsysConstants" module

TRNSYS 16 Types should access global constants through the "TrnsysConstants" data module.
The available constants are described in section 7.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 7.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:
character*10 myString
myString = 'Hello world'
write(*,1000) myString
1000 format(a20)
The recommended way is now:
use TrnsysConstants ! defines integer, parameter ::maxDescripLength
character (len=maxDescripLength) :: myString
myString = 'Hello world'
write(*,'(a)') trim(myString)
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.

7158
TRNSYS 17 Programmer's Guide

7.4.8.4.1.8. Access to Kernel variables: Access Functions and the "TrnsysFunctions"


module

WHY ACCESS FUNCTIONS?

TRNSYS 16 Types should access global (Kernel) variables through access functions only.
Access functions allow Types to use Kernel variables in a much safer way than the Common
Blocks that were used in TRNSYS 15. Common Blocks are inherently dangerous because they
do not ensure name nor even type consistency for Kernel variables among the Types. There is
also no way of preventing a Type from changing the simulation stop time, or even the current
simulation time, with Common Blocks.

The principle of Access Functions is to provide functions that allow access to Kernel variables in
the way they are intended to be used. For example, a function is provided to "Get" the simulation
time step, but no function is provided to change it.

All access functions are listed in section 7.4.2.

HOW TO USE ACCESS FUNCTIONS

First, the module with all the function declarations must be Used in the Type:
use TrnsysFunctions
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".

subroutine Type205(TIME,XIN,OUT,T,DTDT,PAR,INFO,ICNTRL,*)
common/SIM/TIME0,TFINAL,DELT,IWARN
real TIME0,TFINAL,DELT
integer IWARN
TRNSYS 15
real x,s

s = s+x*DELT

subroutine Type205(TIME,XIN,OUT,T,DTDT,PAR,INFO,ICNTRL,*)
use TrnsysFunctions

double precision :: delt, x, s


TRNSYS 16
delt = getSimulationTimeStep()

s = s+x*delt

NOTE ON EXTERNAL DLL'S

7159
TRNSYS 17 Programmer's Guide

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.

7.4.8.4.1.9. Data storage (the "S array")

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 7.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.

7.4.8.4.1.10. The "Messages" subroutine

One of the enhancements in TRNSYS 16 is the introduction of a Messages subroutine that


handles all notices and error messages that component print to the listing and log files. This
makes it easier to parse a listing or log file for errors and it ensures a consistent handling of
messages by the Simulation Studio's "Error Manager".

Where Type previously wrote error messages to the listing file (accessed throught the logical unit
LUW in the LUNITS Common Block), they should now call the Messages subroutine:
call Messages(errorCode,message,severity,unitNo,typeNo)
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.

7160
TRNSYS 17 Programmer's Guide

Please refer to section 7.4.4.9 for more information on the Messages subroutine.

7.4.8.4.1.11. Utility subroutine calls

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 7.4.8.4-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 7.4.8.4-1: TRNSYS 15 (single precision) and TRNSYS 16 (double precision) utility routines

Single precision Double precision Arguments that need to be changed


routine routine from single to double precision
PSYCH Psychrometrics TIME, PSYDAT
DATA DynamicData X, Y
TALF TauAlpha THETA,XKL, REFRIN, ALPHA, RHOD
DIFFEQ Differential_Eqn TIME, AA, BB, TI, TF, TBAR
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 A
DINVRT Matrix_Invert A
FLUIDS Fluid_Props PROP
STEAM Steam_Props PROP

Additional information on Utility Subroutines can be found in section 7.4.4.

7161
TRNSYS 17 Programmer's Guide

7.5. Instructions to rebuild TRNDll.dll and


other dynamic link libraries
The following sections give detailed information on the compiler settings used to rebuild
TRNDll.dll. The TRNSYS developers recompile the main dynamic link library (TRNDll.dll), with
the Intel Visual Fortran compiler, which plugs into MS Visual Studio. Previously, they used the
Compaq Visual Fortran v6.6 compiler. It may be possible to recompile and relink both the
TRNDLL.dll and other dynamic link libraries using other compilers but it is not a trivial process.

If you have the Compaq Visual Fortran (CVF) compiler, go to the directory
%TRNSYS17%\Compilers\Cvf66\. This folder contains the CVF project required to recompile and
relink the TRNDll. As a note of caution, Compaq ceased development on their Fortran compiler in
2005. CVF has become increasingly difficult to buy and increasingly difficult to install on more
recent Microsoft Windows operating systems.

If you have the Intel compiler and its interface (MS Visual Studio), go to the directory
%TRNSYS17%\Compilers\ and select the folder that corresponds to the version of the compiler
that you are using (..\Ivf111 for Intel Visual Fortran 11.1, ..\IvfCXE2011 for Intel Visual Fortran
Composer XE 2011, etc). These directories contain the solution files for various versions of the
Intel Visual Fortran (IVF) compiler and its interface with the appropriate settings. You do not have
to modify any setting to recompile and debug TRNSYS if you use the project included in the
distribution.

You can use the IVF solution file to make modifications to the standard components and kernel
subroutines, or to add you own components to the main library TRNDll.dll.

You may also use the IVF solution file to build your own components into an individual dll. In this
case, use the project MyDll and add the source code for your own components.

7.5.1. Instructions to rebuild TRNDll.dll with Compaq


Visual Fortran 6.6
To use the default workspace, launch CVF 6.6, go to "File/Open workspace" and select
%TRNSYS17%\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.

Supported Compiler version: 6.6b (Note: there was 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)

7.5.1.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:

7162
TRNSYS 17 Programmer's Guide

Go to File/New, select the "Workspace" Tab


Select "Blank Workspace"
Place in %TRNSYS17%\Compilers
Workspace name: Cvf66

7.5.1.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 %TRNSYS17%\Compilers\Cvf66\TRNDll
Click OK
Select "Empty DLL"
Click Finish, then OK

7.5.1.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.

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 7.5.1.3-1: TRNDll Settings CVF 6.6, All Configurations

Tab Drop-down Parameter Value


Predefined
General TRNSYS_MULTI_DLL, TRNSYS_WIN32
Preprocessor Symbols
Powerstation 4.0
Compatibility Check "Libraries" and "Other Run-time Behavior"
compatibility options
Arguments Passing
C, by Reference
External Convention
Fortran Procedures String Length Argument
After All Args
Passing
Floating point exception
0
handling
Floating
Extend precision of
Point
Single precision Checked
constants
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.

7163
TRNSYS 17 Programmer's Guide

Table 7.5.1.3-2: TRNDll Settings CVF 6.6, Win32 Debug

Tab Drop-down Parameter Value


Executable for debug
..\..\..\Exe\TRNExe.exe
session
Debug General You can optionally enter the name of the deck file
Program arguments that you wish to debug here, to bypass the file/open
dialog in TRNExe.exe
Predefined
Add: TRNSYS_DEBUG
Preprocessor Symbols
General
Generate Source
Fortran Browse Information
Generate traceback
Checked
Runtime information
Runtime Error checking Check all boxes
Link Input Ignore Libraries libcd.lib, msvcrtd.lib
Post-build: Copying Debug TRNDll.dll and
Post- Post-build description
TRNDll.lib to the Exe folder
build
copy "Debug\TRNDll.dll" "..\..\..\Exe\TRNDll.dll"
step Post-build command(s)
copy "Debug\TRNDll.lib" "..\..\..\Exe\TRNDll.lib"

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 7.5.1.3-3: TRNDll Settings CVF 6.6, Win32 Release

Tab Drop-down Parameter Value


Link Input Ignore Libraries libcd.lib, msvcrtd.lib
Post-build: Copying Release TRNDll.dll and
Post- Post-build description
TRNDll.lib to the Exe folder
build
copy "Release\TRNDll.dll" "..\..\..\Exe\TRNDll.dll"
step Post-build command(s)
copy "Release\TRNDll.lib" "..\..\..\Exe\TRNDll.lib"

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

7.5.1.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".

7164
TRNSYS 17 Programmer's Guide

Browse to %TRNSYS17%\SourceCode\Kernel and select all *.f90 files (and *.for files if any)..
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
%TRNSYS17%\SourceCode\Types and select all *.f90 files (and *.for files if any). Click OK to
add the files to the project.

Type 56 Multizone Building


Go to the "TRNDll Files" root folder and create the "Precompiled" folder.
Select this new folder, right-click and choose "Add files to folder".
Browse to %TRNSYS17%\SourceCode\Type56\ and choose a subdirectory according to
your compiler (i.e. Cvf66 here). Select all .obj and .lib files (if any) and add them to the
project.

7.5.1.5. Building the TRNSYS DLL (TRNDll.dll)


Make sure the right project (TRNDll) is active in Project/Set active project, in case you have
several projects.
Select the appropriate configuration (Debug or Release) in Build/Set Active Configuration
Go to Build/Rebuild all

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 a
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.

7.5.1.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.

7165
TRNSYS 17 Programmer's Guide

7.5.1.7. Known issues with CVF 6.6

CVF IS UNSTABLE ON MICROSOFT VISTA AND WINDOWS7 OPERATING SYSTEMS.

Development and support of the Compaq Visual Fortran product ceased in 2005. CVF has
become increasingly difficult to install and (if it can be installed at all) unstable to run under more
recent Microsoft operating systems (Vista and Windows 7). If you are encountering such
difficulties, there is unfortunately no known solution except to migrate to a different Fortran
compiler. The TRNSYS developers use (and because of this) recommend the Intel Visual Fortran
compiler.

ERRORS ABOUT IFPORT.MOD, IFWIN.MOD, ETC. (FILE NOT FOUND)

This is a bug in CVF but it does not have any effect on TRNSYS. The "if*.mod" files are only used
when compiling and linking with the Intel Visual Fortran, but CVF checks for their existence (in the
wrong location) before even checking that it is going to use them. So you can safely ignore those
messages.

CVF UNNECESSARILY RECOMPILING SOME ROUTINES WHEN REBUILDING TRNDLL.DLL

CVF has a known issue that causes it to recompile some files even though they have not been
changed. This usually does not happen immediately but after using the project for some time you
may notice that some files are recompiled without a valid reason. To fix that issue, you can try the
following:
In CVF, with the right project and configuration selected, do a Build/Clean
In Windows explorer, browse to %TRNSYS17%\Compilers\Cvf66\TRNDll\Debug and delete
all files that may have been left over. Do the same for the
%TRNSYS17%\Compilers\Cvf66\TRNDll\Debug folder
Then do a Build/Update all dependencies
Then do a Rebuild all

This should solve the problem for a while. Moving the project from one location to another one or
from one computer to another one is known to cause the problem to reappear.

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 %TRNSYS17%\Compilers\Cvf66 directory except for Cvf66.dsw and
the subdirectories (only delete FILES, e.g. Cvf66.opt)
Delete ALL files in the %TRNSYS17%\Compilers\Cvf66\TRNDll directory except for
TRNDll.dsp and the subdirectories (only delete FILES, e.g. TRNDll.plg)
Delete EVERYTHING in %TRNSYS17%\Compilers\Cvf66\TRNDll\Debug and
%TRNSYS17%\Compilers\Cvf66\TRNDll\Release
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.

7166
TRNSYS 17 Programmer's Guide

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 %TRNSYS17%\Compilers\Cvf66.

7167
TRNSYS 17 Programmer's Guide

7.5.2. Instructions to add a new project to the CVF66


workspace
This section explains how to add a new project to the CVF66 workspace provided with
TRNSYS 17 in order to create a library of user components.

Note: You can use the "Export as Fortran" command in the TRNSYS Studio to
generate a code template and a CVF project template with the settings that are
listed in this section. The instructions here below are given for reference only and
for users who want to control more advanced options. Please refer to the
"Getting Started" TRNSYS Manual and to the TRNSYS Studio manual for more
information on the "Export as Fortran" command.

7.5.2.1. Cvf66 workspace


The workspace file is %TRNSYS17%\Compilers\Cvf66\Cvf66.dsw. In Compaq Visual Fortran, a
workspace is essentially a collection of Projects, each project being a set of files that allow you to
build an executable program or a DLL when linked together. When you open the workspace, you
will see a list of included projects on the left (by default only the TRNDll project is present).

7.5.2.2. New Project


Go to File/New, select the "Project" Tab
Project type: select "Win32 Dynamic Link Library"
Select "Add to current workspace"
Choose a Project name, e.g. MyDll.dll
The folder name should read %TRNSYS17%\Compilers\Cvf66\MyDll
Click OK
Select "Empty DLL"
Click Finish, then OK

This should add the MyDll project to the Workspace explorer (docked window on the left side of
the screen by default).

7.5.2.3. Project settings


Go to Projects/Settings and in the left-hand window, select the "MyDll" project (or right-click
on the MyDll Project in the workspace explorer and select "Settings")
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.

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.

7168
TRNSYS 17 Programmer's Guide

Table 7.5.2.3-1: New DLL Settings CVF 6.6, All Configurations

Tab Drop-down Parameter Value


Powerstation 4.0
Compatibility Check "Libraries" and "Other Run-time Behavior"
compatibility options
Arguments Passing
C, by Reference
External Convention
Procedures String Length Argument
After All Args
Fortran Passing
Floating point exception
0
handling
Floating
Extend precision of
Point
Single precision Checked
constants
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 7.5.2.3-2: New DLL Settings CVF 6.6, Win32 Debug

Tab Drop-down Parameter Value


General Output files ..\..\..\Userlib\DebugDLLs
Executable for debug
..\..\..\Exe\TRNExe.exe
session
Debug General You can optionally enter the name of the deck file
Program arguments that you wish to debug here, to bypass the file/open
dialog in TRNExe.exe
Generate Source
General Checked
Browse Information
Include and Use
Preprocessor ..\TrnDll\Debug
Paths
Fortran
Generate traceback
Checked
information
Runtime
Runtime Error
Check all boxes
checking
Link Input Ignore Libraries See note hereunder
Post-build: Copying Debug .dll to the
Post- Post-build description
UserLib\DebugDLLs folder
build
step Post-build copy "Debug\MyDll.dll"
command(s) "..\..\..\UserLib\DebugDLLs\MyDll.dll"

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.

7169
TRNSYS 17 Programmer's Guide

Table 7.5.2.3-3: New DLL Settings CVF 6.6, Win32 Release

Tab Drop-down Parameter Value


General Output files ..\..\..\Userlib\ReleaseDLLs
Include and Use
Preprocessor ..\TrnDll\Release
Paths
- Array and string bounds
Fortran
Run time error - Floating point underflow
Run time
checking - Integer overflow
- Power operations
Link Input Ignore Libraries See note hereunder

Post- Post-build description Post-build: Copying Release .dll to the Exe folder
build
step Post-build copy "Release\MyDll.dll"
command(s) "..\..\..\UserLib\ReleaseDLLs\MyDll.dll"

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.

7.5.2.4. Project files


On the left-hand window, go to "MyDll 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 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 %TRNSYS17%\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.

7.5.2.5. Building the new DLL


Make sure the right project (MyDll) is active in Project/Set active project, in case you have
several projects.
Select the appropriate configuration (Debug or Release) in Build/Set Active Configuration
Go to Build/Rebuild all

MyDll.dll should be created in %TRNSYS17%\UserLib. You can debug components in this DLL
by making the project active in Project/Set active project and launching the Exe used for
Debugging (TRNExe.exe) by pressing F5.

7170
TRNSYS 17 Programmer's Guide

7.5.2.6. Troubleshooting multiple DLL's

SHARING LOGICAL UNITS (FILES) BETWEEN DLL'S

Typical symptoms:

You assign a file in the TRNSYS input file and that file seems to be inaccessible to user-Types
compiled in an external DLL.
An "Inquire" statement tells you that the Logical Unit is not associated to a file
Attempts to write to / read from the file create "fort.nnn" (where nnn is the logical unit)

Solution:

If a TRNSYS Type uses a file that is opened and closed by the kernel (i.e. a file managed through
an "ASSIGN" statement in the deck, or an "External File" in a Studio proforma), the logical unit is
associated to the actual file in TRNDll. If a Type that accesses the file is compiled into a separate
DLL in UserLib:
Both DLL's must be linked to the DLL form of the Fortran run-time libraries. Use
"/libs:dll" in the command line, or set "Project Settings\Fortran\Libraries" to "Single-threaded
DLL" in the Visual Studio ("Debug Single-threaded DLL" for debug configuration).
Furthermore, all DLL's must be compiled in the same mode (Debug or Release). Note
that by default TRNSYS is shipped with a Release TRNDll.dll, but a Debug DLL is available
in "\Compilers\Cvf66\TRNDll\Debug".

7171
TRNSYS 17 Programmer's Guide

7.5.3. Rebuilding the TRNDll.dll with Intel Visual


Fortran 11.x and MS Visual Studio 200x
The following sections give detailed information on the compiler settings used to rebuild
TRNDll.dll. They are for reference only. To use the "solution," launch Microsoft Visual Studio, go
to "File/Open Solution" and select the following file: %TRNSYS17%\Compilers\Ivf111\Ivf111.sln.
You do not have to modify any settings 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 solution was created and give all modifications to default settings.

Supported Compiler version: 8.1.029 or above. The latest tested version is identified by the
following Package ID: w_fc_p_8.1.029. You can find out the Package ID you are using by typing
"ifort" at the command prompt (you may have to add the path to ifort.exe to your PATH
environmental variable or to type the full path at the command prompt, by default: " C:\Program
Files\Intel\Fortran\compiler80\IA32\BIN\ifort.exe".

Note: The solution distributed with TRNSYS 17 is created using Microsoft Visual
Studio 2008. Unfortunately, Microsoft changed the solution file format between
Visual Studio .Net 2002 and 2003, so the solution is not usable using MVS .Net
2002. However, the distributed projects for Intel Visual Fortran can easily be
imported in a newly created solution if you use MVS .Net 2002. All the important
settings are in those projects, not in the solution.

7.5.3.1. Ivf11x Solution


In Intel Visual Fortran, a project is set of files and settings that are used to build an application
(.exe or .dll). A solution is a container for multiple projects. The solution itself can be built, which
builds all of the contained projects in a specified order (which can be adjusted by the user).
Go to File/New, select the "Blank Solution" option
In "name", type in "Ivf11x" (without the quotes)
For "Location", browse to %TRNSYS17%\Compilers
Click OK. This will create the file %TRNSYS17%\Compilers\Ivf11x\Ivf11x.sln

7.5.3.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 / Project
Under "Project Types", select "Intel Fortran Project"
Under "Templates", select "Dynamic-link Library"
Type in "TRNDll" for the name
Select the radio button Add to Solution.
Click OK.
This will open the "Fortran Dynamic Link Library Wizard" window.

7172
TRNSYS 17 Programmer's Guide

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 default settings:
%TRNSYS17%\Compilers\Ivf11x\TRNDll\TRNDll.vfproj

7.5.3.3. Project settings


In the Solution Explorer (right-hand window by default), right-click on the TRNDll project and
select "Properties".

Figure 7.5.3.3-1: Solution Explorer, with TRNDll project.

In the window TRNDll Property Pages, go to the pull down menu Configuration; select "All
Configurations". We will now choose the settings that are common to the Debug and Release
configurations.

Figure 7.5.3.3-2: TRNDll properties window. Select All configurations.

There are numerous settings here controlled by a tree structure on the left. Below are the
important settings for each of these tabs. Each tree branch can have several "Categories", so
there are many settings involved. Only the settings that must be changed from their default
values are mentioned.

7173
TRNSYS 17 Programmer's Guide

Table 7.5.3.3-1: TRNDll Settings IVF 11.x, All Configurations

Branch Category Parameter Value


Suppress Startup Banner Yes

Optimization Disable
General
TRNSYS_MULTI_DLL;
Preprocessor Definitions TRNSYS_WIN32;
__INTEL_COMPILER
Data Local Variable Storage All Variables SAVE
Fortran Initialize Local Saved Scalars to
Yes
Zero
Floating Point Extend precision of Single-
Yes
Precision Constants
External
Calling convention C,REFERENCE
procedures
Name case interpretation Upper Case
Libraries Runtime Library Multithreaded
Command
Linker /ignore:4049,4217
line
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 7.5.3.3-2: TRNDll Settings IVF 11.x, Win32 Debug

Branch Category Parameter Value


Command ..\..\..\Exe\TRNExe.exe
You can optionally enter the name of the deck
Debugging
Command arguments file that you wish to debug here, to bypass the
file/open dialog in TRNExe.exe
General Preprocessor Definitions Add TRNSYS_DEBUG
Fortran Libraries Runtime library Debug Single-threaded DLL
Run-time Runtime Error Checking All
copy "Debug\TRNDll.dll" "..\..\..\Exe\TRNDll.dll"
Command Line
Build Post-build copy "Debug\TRNDll.lib" "..\..\..\Exe\TRNDll.lib"
events Event Post-build: Copying TRNDll.dll and TRNDll.lib to
Description
the Exe folder
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.

Table 7.5.3.3-3: TRNDll Settings IVF 11.x, Win32 Release

Branch Category Parameter Value


Fortran Libraries Runtime library Single-threaded DLL

copy "Release\TRNDll.dll" "..\..\..\Exe\TRNDll.dll"


Build Post-build Command Line
copy "Release\TRNDll.lib" "..\..\..\Exe\TRNDll.lib"
events Event
Description Copying TRNDll.dll and TRNDll.lib to the Exe folder
Linker Optimization References Keep unreferenced data

Notes:

7174
TRNSYS 17 Programmer's Guide

The post-build step makes sure that 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

7.5.3.4. Project files


In the Solution Explorer, you can optionally remove the "Header Files" and "Resource Files"
folders under "TRNDll", since they are not used (right-click on the folder and select
"Remove").
Add Kernel routines:
Right-Click on "Source Files" under the "TRNDll" project.
Select "Add", then "New Folder".
Create a folder and rename it to "Kernel".
Right-click on that newly-created folder and select "Add", then "Add Existing Item".
Browse to %TRNSYS17%\SourceCode\Kernel and select all *.for and *.f90 files.
Click OK to add the files to the project.
Add Standard Types:
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", then "Add Existing Item".
Browse to %TRNSYS17%\SourceCode\Types and select all .for and .f90 files (if any).
Click OK to add the files to the project.

7.5.3.5. Building TRNDll.dll


Make sure the right project (TRNDll) is active (its name should be in bold characters in the
Solution Explorer). If not, make it active (Select, right-click, choose "Set as StartUp Project").
Select the appropriate configuration (Debug or Release) in Build/Configuration Manager
Go to Build/Rebuild Solution

Note: You need to do a Rebuild 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.

7175
TRNSYS 17 Programmer's Guide

7.5.4. Instructions to add a new project to the Ivf11.x


Solution
This section explains how to add a new project to the IVF111 Solution provided with TRNSYS 17
in order to create a library of user components.

Note: You can use the "Export as Fortran" command in the TRNSYS Studio to
generate a code template and a CVF project template with the settings that are
listed in this section. The project can then be opened in MS Visual Studio .Net
and automatically updated to IVF 11.x

The instructions here below are given for reference only and for users who want
to control more advanced options. Please refer to the "Getting Started" TRNSYS
Manual and to the TRNSYS Studio manual for more information on the "Export
as Fortran" command.

7.5.4.1. Ivf11.x Solution


The solution is %TRNSYS17%\Compilers\Ivf11x\Ivf11x.sln

In Intel Visual Fortran, a project is set of files and settings that are used to build an application
(.exe or .dll). A Solution is a container for multiple projects. The solution itself can be built, which
builds all of the contained projects in a specified order (which can be adjusted by the user).

7.5.4.2. New Project


Go to File / New / Project
Under "Project Types", select "Intel Fortran Project"
Under "Templates", select "Dynamic-link Library"
Type in "MyDll" for the name. You may select a different name for your application, or
rename it at the end of these instructions.
Check the "Add to solution" radio button. The Location will be adapted automatically and
should say: %TRNSYS17%\Compilers\Ivf11x
Click OK.
This will open the "Fortran Dynamic Link Library Wizard" window.
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 default settings:
%TRNSYS17%\Compilers\Ivf11x\MyDll\MyDll.vfproj

7176
TRNSYS 17 Programmer's Guide

Figure 7.5.4.2-1: Solution Explorer, with projects TRNDll and MyDll.

7.5.4.3. Project settings


In the Solution Explorer (right-hand window by default), right-click on the project MyDll and
select "Properties".

In the "configuration" drop-down list box showing "Active (Debug)", select "All configurations". We
will now choose the settings that are common to the Debug and Release configurations. There
are numerous settings here controlled by a tree structure on the left. Below are the important
settings for each of these tabs. Each tree branch can have several "Categories", so there are
many settings involved. Only the settings that must be changed from their default values are
mentioned.

Table 7.5.4.3-1: New Dll Settings IVF 11.x, All Configurations

Branch Category Parameter Value


Local Variable Storage All variables SAVE
Data Initialize Local Saved Scalars to
Yes
Zero
Fortran Floating Extend precision of Single
Yes
Point precision constants
External Calling convention C, REFERENCE
procedures Name case interpretation Upper Case
Compatabil Use Other PowerStation Run-time
Yes (/fpscomp:general)
ity library
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 7.5.4.3-2: New Dll Settings IVF 11.x, Win32 Debug

Branch Category Parameter Value


Command ..\..\..\Exe\TRNExe.exe
You can optionally enter the name of the deck
Debugging
Command arguments file that you wish to debug here, to bypass the
file/open dialog in TRNExe.exe
Additional Include
Preprocessor ..\TRNDll\Debug
Directories
Fortran Libraries Runtime library Debug Single-threaded DLL
Run-time Runtime Error Checking All

7177
TRNSYS 17 Programmer's Guide

copy "Debug\MyDll.dll"
Build Post-build Command Line
"..\..\..\UserLib\DebugDLLs\MyDll.dll"
events Event
Description Post-build: Copying .dll to the UserLib folder
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.

Table 7.5.4.3-3: TRNDll Settings IVF 11.x, Win32 Release

Branch Category Parameter Value


Additional Include
Preprocessor ..\TRNDll\Release
Fortran Directories
Libraries Runtime library Single-threaded DLL
copy "Release\MyDll.dll"
Build Post-build Command Line
"..\..\..\UserLib\ReleaseDLLs\MyDll.dll"
events Event
Description Copying .dll to the UserLib folder
Notes:
The post-build step makes sure the required files are copied to the UserLib folder without
adding unnecessary compiler files to that folder and making sure a copy of those files stays
in the Debug or Release directory

7.5.4.4. Project files


In the Solution Explorer, you can optionally remove the "Header Files" and "Resource Files"
folders under "MyDll", since they are not used (right-click on the folder and select
"Remove").
Add the source file(s) for your Type(s) and possibly the routines, modules, etc. that they
require
Create a folder called "Libraries" under MyDll and add the TRNDll.lib file that is found
under the folder %TRNSYS17%\Compilers\Ivf11x\TRDll\Debug. This will allow your DLL
to use all the symbols exported by TRNSYS.

7.5.4.5. Building MyDLL


Make sure the right project (MyDll) is active (its name should be in bold characters in the
Solution Explorer). If not, make it active (Select, right-click, choose "Set as StartUp Project").
Select the appropriate configuration (Debug or Release) in Build/Configuration Manager
Go to Build/Rebuild Solution

These instructions will create a DLL of your files, and will place a copy of the MyDll.dll into the
directory %TRNSYS16%\UserLib\ReleaseDLLs or %TRNSYS17%\UserLib\DebugDLLs. You
may want to rename the file MyDll.dll for another meaningful name, such as Typexxx.dll but
bear in mind that there is no reason why you cannot add many Types into the same DLL.

7178
TRNSYS 17 Programmer's Guide

7.5.5. Rebuilding the TRNDll.dll with Intel Visual


Fortran Composer XE 2011
The following sections give detailed information on the compiler settings used to rebuild
TRNDll.dll. They are for reference only. To use the "solution," launch Intel Visual Fortran
Composer XE 2011, go to "File/Open Solution" and select the following file:
%TRNSYS17%\Compilers\IvfCXE2008\IvfCXE2011.sln. You do not have to modify any settings
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 solution was created and
give all modifications to default settings.

7.5.5.1. IvfCXE2011 Solution


In Intel Visual Fortran, a project is set of files and settings that are used to build an application
(.exe or .dll). A solution is a container for multiple projects. The solution itself can be built, which
builds all of the contained projects in a specified order (which can be adjusted by the user).
Go to File/New, select the "Blank Solution" option
In "name", type in "Ivf11CXE2011" (without the quotes)
For "Location", browse to %TRNSYS17%\Compilers
Click OK. This will create the file %TRNSYS17%\Compilers\IvfCXE2011\IvfCXE2011.sln

7.5.5.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 / Project
Under "Project Types", select "Intel Fortran Project"
Under "Templates", select "Dynamic-link Library"
Type in "TRNDll" for the name
Select the radio button Add to Solution.
Click OK.
This will open the "Fortran Dynamic Link Library Wizard" window.
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 default settings:
%TRNSYS17%\Compilers\IvfCXE2011\TRNDll\TRNDll.vfproj

7.5.5.3. Project settings


In the Solution Explorer (right-hand window by default), right-click on the TRNDll project and
select "Properties".

7179
TRNSYS 17 Programmer's Guide

Figure 7.5.5.3-1: Solution explorer, with TRNDll project.

In the window TRNDll Property Pages, go to the pull down menu Configuration; select "All
Configurations". We will now choose the settings that are common to the Debug and Release
configurations.

Figure 7.5.5.3-2: TRNDll properties window. Select All configurations.

There are numerous settings here controlled by a tree structure on the left. Below are the
important settings for each of these tabs. Each tree branch can have several "Categories", so
there are many settings involved. Only the settings that must be changed from their default
values are mentioned.

7180
TRNSYS 17 Programmer's Guide

Table 7.5.5.3-1: TRNDll Settings IVF Composer XE 2011, All Configurations

Branch Category Parameter Value


Suppress Startup Banner Yes

Optimization Disable
General
TRNSYS_MULTI_DLL;
Preprocessor Definitions TRNSYS_WIN32;
__INTEL_COMPILER
Data Local Variable Storage All Variables SAVE
Fortran Initialize Local Saved Scalars to
Yes
Zero
Floating Point Extend precision of Single-
Yes
Precision Constants
External
Calling convention C,REFERENCE
procedures
Name case interpretation Upper Case
Libraries Runtime Library Multithreaded
Command
Linker /ignore:4049,4217
line
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 7.5.5.3-2: TRNDll Settings IVF Composer XE 2011, Win32 Debug

Branch Category Parameter Value


Command ..\..\..\Exe\TRNExe.exe
You can optionally enter the name of the deck
Debugging
Command arguments file that you wish to debug here, to bypass the
file/open dialog in TRNExe.exe
General Preprocessor Definitions Add TRNSYS_DEBUG
Fortran Libraries Runtime library Debug Single-threaded DLL
Run-time Runtime Error Checking All
copy "Debug\TRNDll.dll" "..\..\..\Exe\TRNDll.dll"
Command Line
Build Post-build copy "Debug\TRNDll.lib" "..\..\..\Exe\TRNDll.lib"
events Event Post-build: Copying TRNDll.dll and TRNDll.lib to
Description
the Exe folder
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.

Table 7.5.5.3-3: TRNDll Settings IVF Composer XE 2011, Win32 Release

Branch Category Parameter Value


Libraries Runtime library Single-threaded DLL
Fortran Use Other Yes (/fpscomp:general)
Compatibility PowerStation Run-
time Behavior
copy "Release\TRNDll.dll" "..\..\..\Exe\TRNDll.dll"
Build Post-build Command Line
copy "Release\TRNDll.lib" "..\..\..\Exe\TRNDll.lib"
events Event
Description Copying TRNDll.dll and TRNDll.lib to the Exe folder
Linker Optimization References Keep unreferenced data

Notes:

7181
TRNSYS 17 Programmer's Guide

The post-build step makes sure that 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

7.5.5.4. Project files


In the Solution Explorer, you can optionally remove the "Header Files" and "Resource Files"
folders under "TRNDll", since they are not used (right-click on the folder and select
"Remove").
Add Kernel routines:
Right-Click on "Source Files" under the "TRNDll" project.
Select "Add", then "New Folder".
Create a folder and rename it to "Kernel".
Right-click on that newly-created folder and select "Add", then "Add Existing Item".
Browse to %TRNSYS17%\SourceCode\Kernel and select all *.for and *.f90 files.
Click OK to add the files to the project.
Add Standard Types:
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", then "Add Existing Item".
Browse to %TRNSYS17%\SourceCode\Types and select all *.f90 (and *.for files if any).
Click OK to add the files to the project.

7.5.5.5. Building TRNDll.dll


Make sure the right project (TRNDll) is active (its name should be in bold characters in the
Solution Explorer). If not, make it active (Select, right-click, choose "Set as StartUp Project").
Select the appropriate configuration (Debug or Release) in Build/Configuration Manager
Go to Build/Rebuild Solution

Note: You need to do a Rebuild 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.

7182
TRNSYS 17 Programmer's Guide

7.5.6. Instructions to add a new project to the


IvfCXE2011 Solution
This section explains how to add a new project to the IVFCXE2011 Solution provided with
TRNSYS 17 in order to create a library of user components.

Note: You can use the "Export as Fortran" command in the TRNSYS Studio to
generate a code template and a CVF project template with the settings that are
listed in this section. The project can then be opened in MS Visual Studio .Net
and automatically updated to IVF Composer XE 2011

The instructions here below are given for reference only and for users who want
to control more advanced options. Please refer to the "Getting Started" TRNSYS
Manual and to the TRNSYS Studio manual for more information on the "Export
as Fortran" command.

7.5.6.1. Ivf11.x Solution


The solution is %TRNSYS17%\Compilers\IvfCXE2011\IvfCXE2011.sln

In Intel Visual Fortran, a project is set of files and settings that are used to build an application
(.exe or .dll). A Solution is a container for multiple projects. The solution itself can be built, which
builds all of the contained projects in a specified order (which can be adjusted by the user).

7.5.6.2. New Project


Go to File / New / Project
Under "Project Types", select "Intel Fortran Project"
Under "Templates", select "Dynamic-link Library"
Type in "MyDll" for the name. You may select a different name for your application, or
rename it at the end of these instructions.
Check the "Add to solution" radio button. The Location will be adapted automatically and
should say: %TRNSYS17%\Compilers\IvfCXE2011
Click OK.
This will open the "Fortran Dynamic Link Library Wizard" window.
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 default settings:
%TRNSYS17%\Compilers\IvfCXE2011\MyDll\MyDll.vfproj

7183
TRNSYS 17 Programmer's Guide

Figure 7.5.6.2-1: Solution explorer, with projects TRNDll and MyDll.

7.5.6.3. Project settings


In the Solution Explorer (right-hand window by default), right-click on the project MyDll and
select "Properties".

In the "configuration" drop-down list box showing "Active (Debug)", select "All configurations". We
will now choose the settings that are common to the Debug and Release configurations. There
are numerous settings here controlled by a tree structure on the left. Below are the important
settings for each of these tabs. Each tree branch can have several "Categories", so there are
many settings involved. Only the settings that must be changed from their default values are
mentioned.

Table 7.5.6.3-1: New Dll Settings IVF Composer XE 2011, All Configurations

Branch Category Parameter Value


Local Variable Storage All variables SAVE
Data Initialize Local Saved Scalars to
Yes
Zero
Fortran Floating Extend precision of Single
Yes
Point precision constants
External Calling convention C, REFERENCE
procedures Name case interpretation Upper Case
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 7.5.6.3-2: New Dll Settings IVF Composer XE 2011, Win32 Debug

Branch Category Parameter Value


Command ..\..\..\Exe\TRNExe.exe
You can optionally enter the name of the deck
Debugging
Command arguments file that you wish to debug here, to bypass the
file/open dialog in TRNExe.exe
Additional Include
Preprocessor ..\TRNDll\Debug
Directories
Fortran Libraries Runtime library Debug Single-threaded DLL
Run-time Runtime Error Checking All
copy "Debug\MyDll.dll"
Build Post-build Command Line
"..\..\..\UserLib\DebugDLLs\MyDll.dll"
events Event
Description Post-build: Copying .dll to the UserLib folder

7184
TRNSYS 17 Programmer's Guide

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.

Table 7.5.6.3-3: TRNDll Settings IVF Composer XE 2011, Win32 Release

Branch Category Parameter Value


Additional Include
Preprocessor ..\TRNDll\Release
Fortran Directories
Libraries Runtime library Single-threaded DLL
copy "Release\MyDll.dll"
Build Post-build Command Line
"..\..\..\UserLib\ReleaseDLLs\MyDll.dll"
events Event
Description Copying .dll to the UserLib folder
Notes:
The post-build step makes sure the required files are copied to the UserLib folder without
adding unnecessary compiler files to that folder and making sure a copy of those files stays
in the Debug or Release directory

7.5.6.4. Project files


In the Solution Explorer, you can optionally remove the "Header Files" and "Resource Files"
folders under "MyDll", since they are not used (right-click on the folder and select
"Remove").
Add the source file(s) for your Type(s) and possibly the routines, modules, etc. that they
require
Create a folder called "Libraries" under MyDll and add the TRNDll.lib file that is found
under the folder %TRNSYS17%\Compilers\IvfCXE2011\TRDll\Debug. This will allow your
DLL to use all the symbols exported by TRNSYS.

7.5.6.5. Building MyDLL


Make sure the right project (MyDll) is active (its name should be in bold characters in the
Solution Explorer). If not, make it active (Select, right-click, choose "Set as StartUp Project").
Select the appropriate configuration (Debug or Release) in Build/Configuration Manager
Go to Build/Rebuild Solution

These instructions will create a DLL of your files, and will place a copy of the MyDll.dll into the
directory %TRNSYS17%\UserLib\ReleaseDLLs or %TRNSYS17%\UserLib\DebugDLLs. You
may want to rename the file MyDll.dll for another meaningful name, such as Typexxx.dll but
bear in mind that there is no reason why you cannot add many Types into the same DLL.

7185
TRNSYS 17 Programmer's Guide

7186
TRNSYS 17 Programmer's Guide

7.6. 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.

7187

Das könnte Ihnen auch gefallen