Compilación del ATP al alcance del usuario.
Orlando P. Hevia
Gorostiaga 1483
CAUE-Comité Argentino de Usuarios del EMTP
3000 Santa Fe
GISEP-Facultad Regional Santa Fe- UTN
Argentina
[email protected]
1. Introducción.
Una de las posibilidades que tienen los usuarios del ATP es generar una versión de acuerdo
con sus necesidades. Hasta la aparición de compiladores FORTRAN y C sin costo, esto estaba
reservado sólo a los usuarios que podían adquirir estas herramientas, y mantenerlas
actualizadas.
Al principio solamente se podía generar un ejecutable con las tablas de dimensiones acorde a
los requerimientos. Pero primero la subrutina ANALYT para definir fuentes por el usuario,
luego agregar subrutinas y funciones que pueder ser llamadas desde MODELS, el elemento no
lineal definido por el usuario USRNL, fueron completando la gama de posibilidades. Más tarde
apareció la posibilidad de generar una rutina FORTRAN a partir de sentencias de TACS, las
cuales se compilan e integran parte del ATP para un uso específico. Finalmente se agregó una
fuente sencilla a definir por el usuario, en la rutina USRFUN.
A los efectos de facilitar la tarea del usuario que quiera usar alguna de estas opciones, se
elaboró el presente trabajo. Todas las operaciones se explican suponiendo se esté utilizando la
versión Windows del ATP y el compilador MINGW32. Con pocos cambios se procede en
DOS y en LINUX.
El ATP en versión GNU (Mingw32 para Windows 32, DOS/DJGPP y Linux) se distribuyen
tanto en binarios (ATP*.ZIP), como en librería (LIB*.ZIP).
2. Dimensionamiento del ATP.
Esta fue la primera opción a la que accedieron los usuarios: modificar la tabla de
dimensionamientos del ATP para obtener un programa adecuado para sus necesidades.
Esta tarea se ve facilitada por una característica del FORTRAN que fue muy bien aprovechada:
el dimensionamiento de una variable toma el valor máximo que encuentre en múltiples
asignaciones. Esto permite dimensionar todo el ATP mediante una sola subrutina. Esta
subrutina se genera mediante un programa, lo que libera al programador/usuario de una tarea
penosa.
El programa vardim.exe lee el contenido del listsize.dat y genera algunos archivos FORTRAN
donde se definen los dimensionamientos del ATP. Estos archivos se llaman dimdef.f y
newmods.f.
Compilados estos archivos (tarea que insume muy corto tiempo, ya que los archivos son
pequeños), se encadenan con una librería precompilada por los encargados del mantenimiento
del programa, más las librerías gráficas DISLIN, y se obtiene una versión personalizada en lo
que respecta al dimensionamiento.
Para facilitar la tarea, se emplea un utilitario (el cual es parte del paquete que conforma el
compilador) llamado make.
Este programa lee instrucciones de un archivo ASCII y procede a ejecutar las tareas de
compilación y encadenamiento.
El archivo ASCII se denomina makefile, lo que facilita algo el uso del make: sólo hace falta
invocarlo y automáticamente leerá el archivo makefile y procederá según lo que encuentre en
él.
Como resultado, se obtiene el ATP de acuerdo con el dimensionamiento requerido por el
usuario.
3. Subrutinas y Funciones foreign del MODELS.
El MODELS permite definir subrutinas y funciones llamadas foreign (externas) al ATP. Esto
requiere generar la rutina o función que el usuario necesita, y modificar un archivo FORTRAN
existente, que sirve de conexión entre el ATP y el programa definido por el usuario.
El programa fgnmod.f es la clave para acceder a las rutinas generadas por el usuario desde
MODELS. Las rutinas del usuario pueden estar tanto en C (como se puede ver en los ejemplos
que forman parte del suministro), o en FORTRAN, o en cualquier lenguaje cuyo compilador
genere modulos objeto compatibles.
En versiones anteriores del compilador DOS/DJGPP se podía incluso agregar funciones
externas en PASCAL, pero en las versiones más nuevas de perdió esta compatibilidad.
En este caso el usuario interesado debe generar su subrutina, y agregarla a la lista en el archivo
fgnmod.f siguiendo una de las ya instaladas como guía.
Aquí también, una vez agregada la función del usuario, se debe usar el programa make. Sólo es
necesario agregar el nombre del módulo objeto en el archivo makefile. Cuando se ejecute el
programa make, este compilará el modulo definido por el usuario y lo encadenará al nuevo
ATP.
Más instrucciones pueden verse directamente en el archivo fgnmod.f.
4. TACS compilado.
Esta opción permite generar una rutina FORTRAN que puede compilarse y encadenarse al
ATP, a partir de la porción de datos de un caso de TACS.
La ventaja de esta posibilidad es una mayor velocidad, ya que el ATP deja de interpretar el
TACS como un lenguaje. Debe notarse que, a diferencia de las funciones foreign de MODELS,
no se estaría agregando nuevas funciones al TACS, sólo se compila una rutina FORTRAN
equivalente a un caso de TACS.
Si bien todo lo que esté en la región de TACS será convertido a una rutina FORTRAN, debe
tenerse en cuenta algunas limitaciones:
Algunos nombres de variables no deben usarse: I, IA, T...
No deben usarse números enteros como denominador:
1/2 debe ser definido como 1.D0/2.D0
Las expresiones lógicas deben ser modificadas a mano como sigue:
Por ejemplo:
SIGAP = .NOT. SIGA
Este código debe modificarse como sigue:
AASIGAP = .NOT.SIGA
BB IF ( SIGA .GT. 0.0 ) then
BB SIGAP = 0.0
BB ELSE
BB SIGAP = 1.0
BB ENDIF
Otro ejemplo:
SIGNLC = SIGN( ERRORC ) * ( ABS( ERRORC ) .GT. DELTAI )
Este código debe modificarse como sigue:
AASIGNLC = SIGN( ERRORC ) * ( ABS( ERRORC ) .GT. DELTAI )
BB IF ( DABS( ERRORC ) .GT. DELTAI ) THEN
BB SIGNLC = SIGNZ( ERRORC ) * 1.0D0
BB ELSE
BB SIGNLC = 0.D0
BB ENDIF
http://www.jaug.gr.jp/~atp/develop-e.htm#tacs
Las líneas con AA se interpretarán por el ATP al ejecutar el caso, mientras que las que tienen
BB se emplearán para generar el módulo FORTRAN requerido.
Para obtener una versión COMPILED TACS del ATP, debe ajustarse primero la variable de
entorno COMTACS como MAKE:
C:> set comptacs=make
También es conveniente borrar el archivo objeto de alguna versión anterior:
C:> delete comtac.o
y correr el ATP con el archivo que contiene el caso cuya sección TACS se quiere compilar.
Entonces se generan los tres archivos siguientes:
codetacs.inc
decktac1.inc
dectack2.inc
Estos archivos deben copiarse como comta1.ins, comta2.ins y comta3.ins, respectivamente,
como requiere el programa comtac.f.
Es conveniente incluir una línea con “SINGLE STEP IF MAKE” en el archivo de datos. Eso
hará que al ejecutar el ATP con el archivo de datos, se generen los archivos mencionados, y la
ejecución se detenga en el primer paso de tiempo. Sin este comando, el caso correrá hasta que
la simulación llegue a tmax.
El archivo comtac1.bat incluido en la distribución hace todo este trabajo, con el archivo de
datos como argumento:
C:> comtac1 archivo
Los tres archivos mencionados se incluirán por el comtac.f al momento de compilar. El nuevo
tpbig se genera compilando comtac.f y encadenando con los otros módulos.
Esto se hace automáticamente corriendo el programa make sin argumentos.
Para correr el nuevo tpbig.exe, debe ajustarse la variable de entorno COMPTACS como USE.
C:> set comptacs=use
El archivo de comandos comtac2.bat hace este trabajo con el archivo de datos como
argumento:
C:> comtac2 archivo
El archivo DCMAKE.DAT es un caso en el cual se solicita la generación del TACS
COMPILED. El archivo DCUSE.DAT está preparado para usar la versión compilada de
TACS con el mismo ejemplo del caso anterior. El archivo DCATP.DAT tiene el mismo caso
para poder comparar los tiempos de ejecución. Estos son:
Con TACS:
Seconds for overlays 1-5 : 0.060 0.000 0.060 -- (CP: Wait; Real) Seconds for overlays 6-11 : 0.030 0.000 0.030
Seconds for overlays 12-15 : 0.010 0.000 0.010 Seconds for time-step loop : 0.741 0.000 0.741 Seconds after DELTAT-loop : 0.010 0.000 0.010 Totals : 0.851 0.000 0.851
Con TACS COMPILADO:
Seconds for overlays 1-5 : 0.060 0.000 0.060 -- (CP: Wait; Real) Seconds for overlays 6-11 : 0.030 0.000 0.030
Seconds for overlays 12-15 : 0.000 0.000 0.000 Seconds for time-step loop : 0.441 0.000 0.441 Seconds after DELTAT-loop : 0.010 0.000 0.010 Totals : 0.541 0.000 0.541
5. Obtención del compilador MINGW32 y rutinas gráficas DISLIN.
5.1 Lo que debe obtenerse:
El compilador MINGW32 (MINimal Gnu Windows 32 bits) se puede obtener de la siguiente
dirección:
http://www.xraylith.wisc.edu/~khan/software/gnu-win32/
Los archivos que deben o es conveniente obtener son:
a. gcc-2.95-mingw32.zip: obligatorio: contiene los compiladores C/C++/F77/ObjC
b. gcc-2.95-html-docs.zip: opcional: contiene la documentación en formato HTML.
5.2 Instalación del compilador
Una vez obtenido el archivo gcc-2.95-mingw32.zip, se debe instalar el paquete.
a. Se crea un directorio en el disco de trabajo, por ejemplo C:\GCC-2.95, pero puede ser
cualquier disco y cualquier directorio, incluyendo unidades ZIP o JAZZ, pero el directorio no
debe contener espacios en el nombre (no usar “Archivos de Programas”, por ejemplo).
b. Se descomprime el archivo gcc-2.95-mingw32.zip en este directorio. Es preferible usar un
programa que reconozca nombre largos y mantenga la estructura de directorios, como el
“unzip”. PKUNZIP, WINZIP, RAR también puede usarse. Debe usarse la opción -d para que
se manytenga la misma estructura de directorios al descomprimir.
Primero se crea el directorio de instalación:
C:\> mkdir C:\GCC-2.95
C:\> cd C:\GCC-2.95
Suponiendo que el archivo gcc-2.95-mingw32.zip se copió al directorio c:\tmp, se
descomprime el paquete con:
C:\> unzip -d C:\tmp\gcc-2.95-mingw32.zip
Debe agregarse el directorio en el cual se encuentran los ejecutables del compilador (el
compilador, el linker, el ensamblador, make, etc.) al PATH del sistema operativo.
Este es el C:\GCC-2.95\BIN
Esto se puede hacer manualmente:
C:\> PATH=C:\GCC-2.95\BIN;%PATH%
pero es conveniente definirlo en el sistema (Windows NT o 2000), o en el autoexec.bat.
Lo precedente es nada más que una traducción libre de las instrucciones que se pueden ver en
el sitio mencionado.
5.3 Rutinas Gráficas DISLIN.
Las rutinas gráficas DISLIN (sin costo para los compiladores MINGW32, Linux y
DOS/DJGPP) pueden obtenerse de las siguientes direcciones de ftp anónimo:
También puede accederse al sitio de DISLIN, www.linmpi.mpe.de/dislin/ y bajar la (o las)
versiones requeridas con el protocolo http.
Este paquete gráfico trae sus propias instrucciones de instalación, muy sencillas. En el
directorio en el cual se instale el paquete, por ejemplo C:\DISLIN, se encontrará el archivo
dismg7.a (el nompre de la libreria DISLIN). El archivo makefile que se mencionó más arriba
debe modificarse de acuerdo con la ubicación de dismg7.a.
En este caso, nuestro agradecimiento debe ser para Helmut Michels, autor de las rutinas
gráficas DISLIN.
APÉNDICES
1. Funciones foreign de MODELS
A continuación se muestra el archivo fgnmod.f. Este archivo es el que se usa para generar la
versión ejecutable del ATP tal como se distribuye actualmente. El archivo es parte de la
distribución en la versión como librería.
SUBROUTINE FGNMOD ( name, namlen, xdata, xin, xout, xvar, 1 iniflg, ierflg)
IMPLICIT REAL*8 (A-H, O-Z), INTEGER*4 (I-N) DIMENSION xdata(*), xin(*), xout(*), xvar(*) CHARACTER*1 name(*)
PARAMETER ( namcnt = 8 ) CHARACTER*32 refnam(namcnt)
CONTINUE ! CONTINUE ! You may increase namcnt above to allow more names: CONTINUE ! CONTINUE ! In the following lines, register your foreign model CONTINUE ! names as they are declared in your models:
CONTINUE ! - use only uppercase characters for the name here CONTINUE ! - you can use any case for the name in the models CONTINUE ! - make a copy of the modifications you make to this CONTINUE ! file so that you don't lose them when installing CONTINUE ! a newer version of ATP later
DATA refnam(1) / 'SAMPLE_MODEL' / ! Do not modify this line DATA refnam(2) / 'SAMPLE_C_MODEL' /
DATA refnam(3) / ' ' / DATA refnam(4) / ' ' / DATA refnam(5) / ' ' / DATA refnam(6) / ' ' / DATA refnam(7) / ' ' / DATA refnam(8) / ' ' /
CONTINUE ! CONTINUE ! Name identification loop
CONTINUE ! -- no need to change anything here iname = 1
lpflg = 1
DO WHILE (iname.LE.namcnt .AND. lpflg.GT.0) ICHAR = 1
DO WHILE (ichar.LE.namlen
1 .AND. name(ichar).EQ.refnam(iname)(ichar:ichar)) ichar = ichar + 1
ENDDO
IF (ichar.GT.namlen) THEN lpflg = 0
ELSE
iname = iname + 1 ENDIF
IF (iname.GT.namcnt) THEN ierflg = 1
RETURN ENDIF
CONTINUE ! CONTINUE ! In the following lines, this is where you call the CONTINUE ! actual foreign subroutines/procedures:
CONTINUE ! - actual names may be different from the foreign CONTINUE ! names used in the models
CONTINUE ! - notice how each one uses both an
CONTINUE ! initialization routine and an execution routine IF ( iname.EQ.1 ) THEN
IF (iniflg.EQ.1) THEN
CALL sampli(xdata, xin, xout, xvar) ELSE
CALL samplm(xdata, xin, xout, xvar) ENDIF
CONTINUE ! ELSE IF ( iname.EQ.2 ) THEN
IF (iniflg.EQ.1) THEN
CALL c_sample_i(xdata, xin, xout, xvar) ELSE
CALL c_sample_m(xdata, xin, xout, xvar) ENDIF
CONTINUE ! ELSE IF ( iname.EQ.3 ) THEN
IF (iniflg.EQ.1) THEN ELSE
ENDIF
CONTINUE ! ELSE IF ( iname.EQ.4 ) THEN
IF (iniflg.EQ.1) THEN ELSE
ENDIF
CONTINUE ! ELSE IF ( iname.EQ.5 ) THEN
IF (iniflg.EQ.1) THEN ELSE
ENDIF
CONTINUE ! ELSE IF ( iname.EQ.6 ) THEN
IF (iniflg.EQ.1) THEN ELSE
ENDIF
CONTINUE ! ELSE IF ( iname.EQ.7 ) THEN
IF (iniflg.EQ.1) THEN ELSE
ENDIF
CONTINUE ! ELSE IF ( iname.EQ.8 ) THEN
IF (iniflg.EQ.1) THEN ELSE
ENDIF ENDIF
CONTINUE ! RETURN
END
SUBROUTINE fgnfun ( name, namlen, xarg, nval, ierflg) IMPLICIT REAL*8 (A-H, O-Z), INTEGER*4 (I-N)
DIMENSION xarg(*) CHARACTER*1 name(*) PARAMETER ( namcnt = 8 ) CHARACTER*32 refnam(namcnt)
CONTINUE ! CONTINUE ! You may increase namcnt above to allow more names: CONTINUE ! CONTINUE ! In the following lines, register your foreign function CONTINUE ! names as they are declared in your models:
CONTINUE ! file so that you don't lose them when installing CONTINUE ! a newer version of ATP later
DATA refnam(1) / 'SAMPLE_FUNCTION' / ! Do not modify this line DATA refnam(2) / 'SAMPLE_C_FUNCTION' /
DATA refnam(3) / 'C_SEED' / DATA refnam(4) / 'C_RANDOM' / DATA refnam(5) / ' ' /
DATA refnam(6) / ' ' / DATA refnam(7) / ' ' / DATA refnam(8) / ' ' /
CONTINUE ! CONTINUE ! Name identification loop
CONTINUE ! -- no need to change anything here iname = 1
lpflg = 1
DO WHILE (iname.LE.namcnt .AND. lpflg.GT.0) ichar = 1
DO WHILE (ichar.LE.namlen
1 .AND. name(ichar).EQ.refnam(iname)(ichar:ichar)) ichar = ichar + 1
ENDDO
IF (ichar.GT.namlen) THEN lpflg = 0
ELSE
iname = iname + 1 ENDIF
ENDDO
IF (iname.GT.namcnt) THEN ierflg = 1
RETURN ENDIF
CONTINUE ! CONTINUE ! In the following lines, this is where you call the CONTINUE ! actual foreign functions:
CONTINUE ! - actual names may be different from the foreign CONTINUE ! names used in the models
IF ( iname.EQ.1 ) THEN
nval = samplf(xarg) ELSE IF ( iname.EQ.2 ) THEN
nval = cfun(xarg) ELSE IF ( iname.EQ.3 ) THEN
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC CCCC xarg(1) = C_seed() xarg(1) = cseed() CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC nval = 1
ELSE IF ( iname.EQ.4 ) THEN
CCCC xarg(1) = C_random() xarg(1) = Crandom() nval = 1
ELSE IF ( iname.EQ.5 ) THEN
nval = 0 ELSE IF ( iname.EQ.6 ) THEN
nval = 0 ELSE IF ( iname.EQ.7 ) THEN
nval = 0 ELSE IF ( iname.EQ.8 ) THEN
nval = 0 ENDIF
CONTINUE ! RETURN
END
SUBROUTINE samplm(xdata, xin, xout, xvar) IMPLICIT REAL*8 (A-H, O-Z), INTEGER*4 (I-N) DIMENSION xdata(*), xin(*), xout(*), xvar(*)
CONTINUE ! - the dimension of xin,xout,xvar is given in xdata(1)! CONTINUE ! - xvar is to be initialized with HISTDEF ! CONTINUE ! in the USE statement ! CONTINUE !---! CONTINUE ! For any foreign model: ! CONTINUE ! - the user can assign history to xin and xvar ! CONTINUE ! using HISTDEF in the USE statement ! CONTINUE ! - MODELS always saves the values that are in xvar ! CONTINUE ! between uses, so that the memory of multiple ! CONTINUE ! instances of using the code can be managed ! CONTINUE ! automatically by MODELS ! CONTINUE !---! CONTINUE ! To introduce a foreign model in a simulation: ! CONTINUE ! - create an initialization and an execution routine ! CONTINUE ! for that model ! CONTINUE ! - provide access to your routines by modifying ! CONTINUE ! the routine fgnmod at the beginning of this file ! CONTINUE ! - declare and use the foreign model in a model ! CONTINUE ! of the simulation ! CONTINUE !---! CONTINUE ! This sample foreign model could be used in a model ! CONTINUE ! as follows: ! CONTINUE ! ! CONTINUE ! MODEL anyname ! CONTINUE ! INPUT ... ! CONTINUE ! VAR a[1..3], ... ! CONTINUE ! ... ! CONTINUE ! MODEL mymodel FOREIGN sample_model ! CONTINUE ! followed by values for ixdata, ixin, ixout, ! CONTINUE ! and ixvar a pair of inside brackets ! CONTINUE ! -- the preceding line declares foreign model "sub" ! CONTINUE ! -- "mymodel" is the local name of the foreign model ! CONTINUE ! -- "sample_model" is the identifier used for that ! CONTINUE ! -- foreign model in the user-modifiable ! CONTINUE ! -- MODELS interface routine "fgnmod" ! CONTINUE ! ... ! CONTINUE ! EXEC ! CONTINUE ! ... ! CONTINUE ! USE mymodel AS mymodel ! CONTINUE ! DATA xdata[1]:=3 ! CONTINUE ! INPUT xin[1..3]:=[ list of 3 expressions... ] ! CONTINUE ! OUTPUT a[1..3]:=xout[1..3] ! CONTINUE ! HISTORY histdef(xvar[1..3]):=0 ! CONTINUE ! -- can be any expression ! CONTINUE ! -- note the fixed names xdata, xin, xout, xvar ! CONTINUE ! ENDUSE ! CONTINUE ! ... ! CONTINUE ! ENDEXEC ! CONTINUE ! ENDMODEL ! CONTINUE !---! text80 = 'Executing model "sample_model".' ! Assemble output mes CALL OUTSIX( text80, 80 ) ! Send text80 (arg 1) to ATP listing DO 1000 i=1,xdata(1)
xvar(i)=(2*xvar(i)+xin(i))/2 xout(i)=xvar(i)+100.0
1000 CONTINUE RETURN
ENTRY sampli(xdata, xin, xout, xvar)
text80 = 'Initializing model "sample_model".' CALL OUTSIX( text80, 80 )
RETURN END
FUNCTION samplf(arg)
IMPLICIT REAL*8 (A-H, O-Z), INTEGER*4 (I-N) DIMENSION arg(2)
CONTINUE ! - the function loads its output values in ! CONTINUE ! the same array ! CONTINUE ! - the function returns the number of output values ! CONTINUE ! as its value ! CONTINUE !---! CONTINUE ! To introduce a foreign function in a simulation: ! CONTINUE ! - create a function procedure ! CONTINUE ! - provide access to your functions by modifying ! CONTINUE ! the routine fgnfun at the beginning of this file ! CONTINUE ! - declare and use the foreign function in a model ! CONTINUE ! of the simulation ! CONTINUE !---! CONTINUE ! This function could be declared in a model as follows:! CONTINUE ! FUNCTION myfunc FOREIGN sample_function ! CONTINUE ! followed by ixarg:2 inside a pair of brackets ! CONTINUE ! which defines the function "myfunc" to be a foreign ! CONTINUE ! function where: ! CONTINUE ! - "myfunc" is the local name of the foreign function ! CONTINUE ! - "sample_function" is the identifier used for that ! CONTINUE ! foreign funcion in the user-modifiable ! CONTINUE ! MODELS interface routine "fgnfun" ! CONTINUE ! - "ixarg" is a fixed keyword indicating ! CONTINUE ! the argument count ! CONTINUE !---! CONTINUE ! This function could be used in a model as follows: ! CONTINUE ! a[1..2] := 3*myfunc( 36.3, sqrt(c) ) ! CONTINUE !---! arg(1)=arg(1) +arg(2)
arg(2)=10*arg(1) samplf=2
RETURN END
Los siguientes son los módulos C que definen las funciones externas (foreign) actualmente
incluidas en el ATP.
Esta función devuelve la suma de los dos argumentos pasados, multiplicada por 10.
double cfun_(double arg[]) { arg[0] = arg[0] + arg[1]; arg[1] = 10 * arg[0]; return 2;
}
Esta función opera con los argumentos que se le pasen, independientemente de la cantidad, que
es pasada en el primer argumento, xdata_ar. Los argumentos de entrada son los xin_ar, los de
salida, que pasan al MODELS al retorno, son los xout_ar. En xvar_ar se pasan parámetros.
extern void outsix_( char *, int *); void c_sample_m__(double xdata_ar[], double xin_ar[], double xout_ar[], double xvar_ar[]) { short i;
char* text = "Executing model 'sample_c_model'."; int len = strlen(text);
outsix_(text, &len);
for (i=0; i<xdata_ar[0]; i++)
{ xvar_ar[i] = (2*xvar_ar[i] + xin_ar[i])/2; xout_ar[i] = xvar_ar[i] + 100.0;
} return; }
void c_sample_i__(double xdata_ar[], double xin_ar[], double xout_ar[], double xvar_ar[])
{ char* text = "Initializing model 'sample_c_model'."; int len = strlen(text);
outsix_(text, &len); return;
}
/* Remarks:
| xin_ar holds input values received from the calling model. | xout_ar holds output values sent back to the calling model.
| xvar_ar holds state values stored in memory by MODELS between calls. |
| Note how xvar_ar is referenced before a new value is assigned to it, | requiring a reference to the pre-simulation history of xvar_ar | at the first execution of the procedure.
|
| Note that you need to modify ATP file fgnmod.for in order to connect | additional user-defined foreign subroutines and procedures.
| */
El siguiente módulo es un generador de números aleatorios. cseed es la inicialización del
módulo. Si se lo invoca al principio, el generador producirá diferentes números cada vez.
#include <stdlib.h> /* #include <lib.h> */
/*---*/ /* These functions would be declared in a model as follows: */ /* FUNCTION seed FOREIGN C_SEED {ixarg: 1} */ /* FUNCTION rand FOREIGN C_RANDOM {ixarg: 1} */ /* and the function names would need to be registered */ /* in subroutine fgnfun of ATP's file mod001.for */ /*---*/ double cseed_(void) /* randomly seeds the C library function rand() */ {
/* { date_time_seed(); */ srand(time(0));
return 0; }
double crandom_(void) /* returns a random number between 0 and 1 */ { return (double)rand()/(double)RAND_MAX;
}
2. Elementos no lineales a definir por el usuario
El archivo usernl.f es para incluir ramas no lineales definidas por el usuario. En este ejemplo, se
define el elemento 51-52-53 Z0Z1Z2. Este archivo es parte de la distribución como librería y
no se reproduce aquí por ser demasiado extenso.
Nota: en la versión distribuida del tpbig, este elemento se define en otra parte del programa y
no es igual al presentado en el archivo, que sólo sirve de ejemplo.
El archivo usrfun.f permite definir fuentes del usuario. Cuando el ATP encuentra una línea
pidiendo este tipo de fuentes, llama a esta subrutina con AMPLITUDE como una llave para
seleccionar que función se debe usar en la subrutina para calcular la amplitud de la fuente. Esta
variable es pasada a la subrutina como K. Sólo está disponible el tiempo de simulación TS,
aunque la fuente respetará tanto tstart como tstop. El ejemplo mostrado corresponde a una
fuente tipo CIGRE.
FUNCTION USRFUN(TS,K) IMPLICIT REAL*8 (A-H) IMPLICIT REAL*8 (O-Z) TT=TS*1.0D6
IF(K.EQ.1)THEN C
C APPROXIMATE VALUES (CIGRE) C
A = 0.6266666667E+06 B = 0.3315508781E+01 C = 0.8200000000E+01 D = 0.1041666642E+01 E = 0.1032926456E+00 TX1 = 0.6094142845E-05 TX2 = 0.2000000000E-07 T90 = 0.7758620690E-06 ENDIF
IF(K.EQ.2)THEN C
C EXACT VALES (FITTER) C
A = 0.6124318289E+06 B = 0.3242060189E+01 C = 0.8017192737E+01 D = 0.1015865843E+01 E = 0.1158658425E+00 TX1 = 0.6418499034E-05 TX2 = 0.2246214478E-07 T90 = 0.7760616259E-06 ENDIF
IF(TS.LE.T90)THEN USRFUN=A*TS+B*TT**C ELSE
USRFUN=D*DEXP(-(TS-T90)/TX1)-E*DEXP(-(TS-T90)/TX2) ENDIF
RETURN END
4. Archivos suministrados
A continuación, la lista (no completa) de los archivos que componen la distribución del ATP
como librería:
ATG.BAT Archivo de comandos para correr el ATP+gtpplot
COMTAC.F Módulo FORTRAN para COMPILED TACS
COMTAC1.BAT Archivo de comandos para generar el COMPILED TACS
COMTAC2.BAT Archivo de comandos para correr el COMPILED TACS
COMTA1.INS Módulos generados por comtac1.bat
COMTA2.INS
COMTA3.INS
DCUSE.DAT Archivo para correr el COMPILED TACS
DCMAKE.DAT Archivo para generar el COMPILED TACS
DCATP.DAT Archivo para correr TACS no compilado
DEKSPY.INS Archivos auxiliares
DIMDEF.F
EIGHTH.AUX Opción de salida en pantalla
FGNMOD.F Módulo de enlace entre MODELS y las funciones del usuario
USRFUN.F Módulo fuente función del usuario
GRAPHICS Opción de salida gráfica
GRAPHICS.AUX Opción de salida en pantalla
GRAPHICS.STD Opción de salida en pantalla
HALFHIGH.AUX Opción de salida en pantalla
HALFWIDE.AUX Opción de salida en pantalla
HIGHER80.AUX Opción de salida en pantalla
HIGHER93.AUX Opción de salida en pantalla
LISTSIZE.BPA Dimensionamiento de la BPA
LISTSIZE.JAU Dimensionamiento de JAUG
MAKEFILE Archivo de instrucciones para make
NEWMODS.F Archivo auxiliar
QUARTER.AUX Opción de salida en pantalla
SIXTEEN.AUX Opción de salida en pantalla
STARTUP Archivo de ajustes de variables
TACSAR.INS Archivo auxiliar
THIRTY2.AUX Opción de salida en pantalla
TPBIG.A Librería que incluye la sección no pública del ATP
USERNL.F Módulo elemento no lineal definido por el usuario
VARDIM.EXE Programa para variar el dimensionamiento del ATP
VARDIM20.BAT Archivos de comandos para correr VARDIM.EXE
VARDIMN.BAT
5. MAKEFILE
A continuación está el archivo makefile tal como se distribuye con la version MINGW32 de
librería del ATP, pero con los comentarios traducidos al castellano.
Los caracteres # definen un comentario.
# Archivo: makefile
# Proposito: compilar y encadenar el ATP #
# Para compilar sin la libreria DISLIN, cambie la libreria DISLIN # a la libreria muda dislin.a
# # #
# Cambie esta linea (y directorios si es necesario) #
CC=gcc FOR=g77 #
# OBJECTS es una lista personalizada de modulos objetos sobre los # que se esta trabajando y estan presentes en el directorio corriente # El caracter \ indica continuacion
# Una linea que es continuacion debe comenzar con <TAB> OBJECTS =dimdef.o \
newmods.o \ comtac.o \ fgnmod.o \ usernl.o \ usrfun.o #
#---# windows NT
# modifique la linea siguiente si la libreria DISLIN esta en otro directorio #
# la porcion “-luser32 -lgdi32 -lcomdlg32” no debe modificarse LIBRARY = tpbig.a h:\\dislin76\\dismg7.a -luser32 -lgdi32 -lcomdlg32 #
# Para encadenar sin librerias graficas DISLIN, anule con un comentario # la linea anterior y habilite la siguiente
#
#LIBRARY = tpbig.a dislin.a -luser32 -lgdi32 -lcomdlg32 #
# En las lineas que siguen se define que debe hacer make cuando se lo invoque: # 1- verifica que existan todos los archivos modulos objetos .o
# 2- Si existe el modulo .o, pero es anterior a su homologo .f o .c (el # fuente del cual proviene), invoca al compilador correspondiente con # parametros adecuados y con el nombre del archivo fuente como argumento, # esto indicado por $<
# # .f.o:
$(FOR) -c $(FFLAGS) $< .c.o:
$(CC) -c $(CFLAGS) $(INCFLAGS) $< #
# 3- Una vez cumplida la regla de objetos mas nuevos que fuentes, se genera # el ejecutable encadenando los objetos con las librerias.
#
$(IMAGE) : $(OBJECTS)