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

Using Python to call directly the TRNDll64.dll

1 Posts
1 Users
0 Reactions
251 Views
0
Topic starter

Greetings,

We are currently using TRNSYS "Original Release of 18.00.0000". We are trying to test a direct call to the dll (TRNDll64.dll) instead of calling a subprocess with the exe and the dck file as it is done in some programming sites out there. In other words, our Python code works as a substitute of the exe file.

As you see, we are using the 64bytes version of everything, so there won't be compatibility problems (32/64 bits). We are working with Windows OS btw.

We are making a small example to generate a csv with results from another csv. For that matter, we use Type25 and Type9.

After using the info of usage contained in the file Trnsys.90 that specifies the name of the subroutine in Fortran, and the types of the parameters to include, we manage to connect and make things work... or at least the header and the first row from the csv.

The issue is that in the instructions indicated in Trnsys.90, we assume that multiple calls are necessary to make this work:

-An initial call with icall=0 to read the deck and set initializations. It is indicated that the first value is also inserted (for our case, first row of the csv)

-Another call (or calls?) with icall=1 to keep things going on with the rest of the rows, until finish.

-We have to send an icall=-1 to indicate that we have finished with everything.

As I've commented, I just manage to create the first row of the output csv. If I execute the code again, i get some error in the lst file:

From type25c:

*** Warning at time : 0.000000
Generated by Unit : Not applicable or not available
Generated by Type : Not applicable or not available
TRNSYS Message 72 : You have assigned the same Logical Unit Number to the same file name twice. Two components may be reading from or writing to the same file. Please check your File Assignments
Reported information : Logical Unit 30, File name: "OutputTest.csv"

*|? Output file for printed results |1000

From type9e:

*** Warning at time : 0.000000
Generated by Unit : Not applicable or not available
Generated by Type : Not applicable or not available
TRNSYS Message 72 : You have assigned the same Logical Unit Number to the same file name twice. Two components may be reading from or writing to the same file. Please check your File Assignments
Reported information : Logical Unit 31, File name: "InputsTest.csv"

*|? Input file name |1000

 

Any indication will be very welcome, for sure.

This topic was modified 7 months ago by framig
Topic Tags
1 Answer
0
Topic starter

Sorry for the spam, but must I aggregate the text of the file, as long as I am not allowed to attach *py not *.txt files for some reason:

# -*- coding: utf-8 -*-
import ctypes as C
import numpy as np
from ctypes import wintypes

NAME = "TRNDll64"
NAME_FULL = NAME + ".dll"
BASE = '********************'
SUB= "
*****************"
DIR_EXE ="
******************************"

MAX_PATH_LENGTH = 300

#función para rellenar un string con nulls para "reservar" toda esa memoria
def mallocLocal(arrayCorto, tamTotal):
arrayLargo = arrayCorto
tamActual = len(arrayCorto)
for valorTam in range(tamActual,tamTotal):
arrayLargo = arrayLargo + '\0'
return arrayLargo

print("inicio de la operacion")
dll = C.windll.LoadLibrary(BASE + SUB + NAME_FULL)
trnsys = getattr(dll, "TRNSYS")
trnsys.restype = None

trnsys.argtypes = [C.POINTER(C.c_int),
C.POINTER(C.c_double),
C.POINTER(C.c_double),
np.ctypeslib.ndpointer(C.c_char, flags='F_CONTIGUOUS'),
np.ctypeslib.ndpointer(C.c_char, flags='F_CONTIGUOUS'),
np.ctypeslib.ndpointer(C.c_char, flags='F_CONTIGUOUS')
]
print("carga de parámetros")
icall = C.c_int(0)
parout_sinorden = [(0.0)]*1000
parout_transpuesto = np.transpose(parout_sinorden)
parout = parout_transpuesto.ctypes.data_as(C.POINTER(C.c_double))
#este es un valor que han de rellenar desde otro lado
plotout_sinorden = [(0.0)]*1000
plotout_transpuesto = np.transpose(plotout_sinorden)
plotout = plotout_transpuesto.ctypes.data_as(C.POINTER(C.c_double))

direccion = BASE
#valores a rellenar desde otro lado, no importa
labels_origen = '\0'
labels_origen = mallocLocal(labels_origen, 4000)
labels = np.array(list(labels_origen), dtype='S1')

#estos valores tienen también aspecto de venir de otras ejecuciones
titles_origen = '\0'
titles_origen = mallocLocal(titles_origen, 1500)
titles = np.array(list(titles_origen), dtype='S1')

#el fichero de log se crea en el mismo lugar donde está el dck!!
deck_name = BASE + 'ejemplo\\PruebaPythonTRNSYS.dck'
deck_name = mallocLocal(deck_name, MAX_PATH_LENGTH)
deck_2 = list(deck_name)
deckn = np.array(deck_2, dtype='S1')

print("primera llamada")
trnsys(C.byref(icall), parout, plotout, labels, titles, deckn)
#llamada tras el cero inicial

print("llamada a iteraciones")
#se hace una, pero habría que hacer todas las necesarias, y cerrar al final
#usamos los valores recibidos de iteración
paso_inicio = parout[0]
paso_fin = parout[1]
step_paso = parout[2]

paso = paso_inicio
icall = C.c_int(1)

trnsys(C.byref(icall), parout, plotout, labels, titles, deckn)
#icall = 1
#trnsys(icall, parout, plotout, labels, titles, deckn)
print("cierre")
#cierre
icall = C.c_int(-1)
trnsys(C.byref(icall), parout, plotout, labels, titles, deckn)

# Esto es para liberar la DLL, ya que si no, al rearrancar daba error
C.windll.kernel32.FreeLibrary.argtypes = [wintypes.HMODULE]
C.windll.kernel32.FreeLibrary(dll._handle)

print("fin de la operacion")

Share: