Welcome to the TRNSYS Users Forum.

The forum is a place where people can interact and have discussions about different topics involving the use of the TRNSYS software package. Here you can post topics for discussion or questions on using TRNSYS and get advice from other users or TRNSYS experts. This forum is not intended for detailed technical support. Users should contact their distributor’s hotline for such assistance.

Some tips for success on using the forum:

  • Follow the Forum Rules posted in Forum Administration.
  • There are categories for different types of topics and questions. Post your topic or question into the proper category.
  • Before posting a topic or question search the existing topics  (and the TRNSYS Users listserv archive or Post archive) to see if a similar topic or question has already been answered.
  • Use a descriptive topic name. Don’t use attention getting subjects, they don’t get attention and only annoy people.
  • State the version of TRNSYS and which add-ons your are using.
  • Include enough specific details for your topic of question to be answered. Just posting “Why am I getting an error?” without describing the specific error and what you are trying to do when you get the error will not receive a response that fixes your issue.
  • Remember when people help you, they are doing you a favor. Be patient, help people out by posting good descriptions of what you need help with, and be polite even if a response does not solve your issue.
  • Moderators may edit your post for clarity or move your topic to a more appropriate category.

Notifications
Clear all

How to store and array

11 Posts
3 Users
1 Reactions
362 Views
0
Topic starter

Dear TRNSYS users,

I am trying to write a new Type which models a latent heat storage unit. The model is relatively detailed in that it models a rectangular PCM slab in two dimensions and has to solve numerically the corresponding differential equations on the 2-D grid. I am writing the Type in Fortran following the TRNSYS 18 programmer's guide and I have reached a potential problem. The program calculates the size of the 2-D grid from user-defined parameters, so allocatable arrays are needed. Then, these arrays representing the state of the grid (temperatures, enthalpy) in all individual nodes at a given time, need to be stored and updated from one timestep to the next. I see in the programmer's guide info on storing and retrieving variables with functions such as setStaticArrayValue and getStaticArrayValue, but from what I can see only a single value can be stored, but not arrays. The following is what appears in the programmer's guide:

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

I don't see any reference in the guide to how to store arrays. Is there a way to do this? I assume there is, or that there is some workaround. I would appreciate any help on this.

Franz

 

1 Answer
1

Hello @franzdra,

What we usually do in our Types is define the array as a static array within the Type, with a maximum allocation for each dimension. Once the dimensions are known at runtime, we use those dimensions to loop through the array and store/retrieve each value in series.

For example, if you don't expect your 2D array to exceed 100 x 200, the storage-relevant sections of your code might look something like this:

!Variable declarations
 Implicit None 
 Integer NX_Max,NY_Max,NX_Tot,NY_Tot
 Integer N_Items_Static,N_Items_Dynamic
 Integer CurrentUnit,CurrentType
 Integer x,y
 Parameter (NX_Max=100,NY_Max=200)
 Double Precision MyArray(NX_Max,NY_Max)

!Get global TRNSYS simulation variables - used in Messages calls if there's an error
 CurrentUnit = getCurrentUnit()
 CurrentType = getCurrentType()

!In the first call of the simulation, size the array, and set the number of storage spots needed
 If getisFirstCallofSimulation() Then

     !(insert code to size the array at runtime - assume the array is NX_Tot x NY_Tot)

     !Error out if the actual size of the array exceeds the maximum size
      If ((NX_Tot>NX_Max).or.(NY_Tot>NY_Max)) Then
         Call Messages(-1, 'At least one of the maximum dimensions of MyArray has been exceeded','Fatal',CurrentUnit,CurrentType)
         Return
      EndIf

     !Set the number of storage spots needed by this unit
      N_Items_Static = NX_Tot*NY_Tot
      N_Items_Dynamic = 0
      Call SetNumberStoredVariables(N_Items_Static,N_Items_Dynamic)

 EndIf

!On an iterative call, retrieve and/or save static array variables

!saving static array variables
 do x = 1,NX_Tot
     do y = 1,NY_Tot
         call SetStaticArrayValue(NX_Tot*(x-1)+y,MyArray(x,y))
     enddo
 enddo

!retrieving static array variables
 do x = 1,NX_Tot
     do y = 1,NY_Tot
         MyArray(x,y) = getStaticArrayValue(NX_Tot*(x-1)+y)
     enddo
 enddo


You can see an example of array storage for the nodal temperatures in standard Type 158, the vertical cylindrical storage tank; that Type only uses dynamic storage, but the basics of the array sizing and the loops to set/retrieve values in storage are the same. 

 

A_Weiss A_Weiss 05/04/2024 3:42 am

On re-read, I realize I probably should've used dynamic storage in the example above. Dynamic storage was written specifically to make saving and updating temperatures between timesteps easier. Type 158 is a good template to follow for using dynamic storage for temperatures. You can also use static storage to save and update temperatures between timesteps, but it requires some extra steps during the post-convergence call and isn't quite as intuitive overall as using dynamic storage.

DavidBradley 05/04/2024 1:04 pm

@franzdra to add on to @a_weiss's excellent and (as ever) thorough answer, the idea of the static array storage in v18 is that it provides a place to store values from timestep to timestep. If you want to change a value, you do so whenever you want to; it makes no assumptions about what you are trying to do. For instance if you have a component that has a complicated computation of a view factor that depends only on parameter values, you could have the Type do the computation once, store the result in the static storage array and then just retrieve it whenever you want.

The dynamic storage array is for a special but common case in which you want to base a calculation on the value that a variable had at the end of the previous timestep rather than basing the calculation on the value that variable had at the end of the last iteration. Solving differential equations is the most common use. You're calculation of a new final temperature should be based on the temperature at the end of the last timestep, not on the final temperature you calculated at the end of the previous iteration. At each iteration you call a function that retrieves a value from the end of the last timestep, you make you calculation and you place your calculated value into dynamic storage. At the end of the timestep, the TRNSYS kernel will automatically move the value that you stores into a different place so that when you next retrieve the value from the previous timestep, you'll get the one you want.

franzdra Topic starter 05/04/2024 1:55 pm

Thank you very much A_Weiss for the clear answer and the example code and also thanks DavidBradley. I will attempt the storage of my arrays using this method. I have not yet looked in detail into dynamic storage. I wrote the original code for my latent heat storage model as a stand alone program in python and to calculate the values of the arrays at the next time step I used two arrays per variable, for example array T and T_new for temperature at previous timestep and the new one respectively. Array T remained constant until convergence was reached and T_new changed with every new iteration. After convergence the values of T_new are replaced into T and the simulation time is advanced. I guess this is analogue to static storage and feel comfortable with it.
If I may, I have another doubt related to writing this new Type. In my original code, and in the code adapted from it to make the new Type, each time the Type is called for calculations and the input values are read, the code will iterate until my convergence criteria are met (those criteria are used defined parameters) based on those input values. As I understand from the documentation, some TRNSYS Types do one iteration per call and the output of those Types would change from one iteration to the next. So if the outputs of such a Type are the inputs to my Type, my Type would be iterating "internally" x times until convergence for every iteration of the upstream Type. Although this seems inefficient, is this a normal or standard situation to have or should I modify my code so that only 1 iteration is done per call in my Type? Thanks

Share: