@ -13,16 +13,18 @@ AUTHORS
20 May 2011 Thomas Sailer
03 Sep 2012 Holger Vogt
27 Feb 2017 Marcel Hendrix
23 JUL 2018 Holger Vogt
MODIFICATIONS
MODIFICATIONS
SUMMARY
This file contains the model - specific routines used to
functionally describe the file source code model used
to read an array of analog values per time step from a file .
to read an array from a file containing lines with
time and analog values , and returning them per time step .
INTERFACES
@ -76,6 +78,14 @@ struct filesource_state {
} ;
struct infiledata {
double * datavec ;
int vecallocated ;
int maxoccupied ;
int actpointer ;
int size ;
} ;
typedef struct {
double * amplinterval ; / * the storage array for the
@ -87,6 +97,9 @@ typedef struct {
struct filesource_state * state ; / * the storage array for the
filesource status . * /
struct infiledata * indata ; / * the storage vector for the input data
sourced from file . * /
} Local_Data_t ;
@ -108,6 +121,7 @@ MODIFICATIONS
07 Sept 2012 Holger Vogt
27 Feb 2017 Marcel Hendrix
23 JUL 2018 Holger Vogt
SUMMARY
@ -142,15 +156,18 @@ static void
cm_filesource_callback ( ARGS , Mif_Callback_Reason_t reason )
{
switch ( reason ) {
case MIF_CB_DESTROY : {
Local_Data_t * loc = STATIC_VAR ( locdata ) ;
fclose ( loc -> state -> fp ) ;
free ( loc -> state ) ;
free ( loc -> amplinterval ) ;
free ( loc -> timeinterval ) ;
free ( loc ) ;
break ;
}
case MIF_CB_DESTROY : {
Local_Data_t * loc = STATIC_VAR ( locdata ) ;
if ( loc -> state -> fp )
fclose ( loc -> state -> fp ) ;
free ( loc -> state ) ;
free ( loc -> amplinterval ) ;
free ( loc -> timeinterval ) ;
free ( loc -> indata -> datavec ) ;
free ( loc -> indata ) ;
free ( loc ) ;
break ;
}
}
}
@ -158,8 +175,10 @@ cm_filesource_callback(ARGS, Mif_Callback_Reason_t reason)
void cm_filesource ( ARGS ) /* structure holding parms, inputs, outputs, etc. */
{
int size = PORT_SIZE ( out ) ;
int stepsize = size + 1 ;
int amplscalesize ;
int amploffssize ;
int j ;
Local_Data_t * loc ; / * Pointer to local static data , not to be included
in the state vector * /
@ -169,7 +188,7 @@ void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc.
}
if ( INIT == 1 ) {
int i ;
int i , count ;
CALLBACK = cm_filesource_callback ;
@ -180,11 +199,18 @@ void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc.
/* Allocate storage for internal state */
loc -> timeinterval = ( double * ) calloc ( 2 , sizeof ( double ) ) ;
loc -> amplinterval = ( double * ) calloc ( 2 * ( size_t ) size , sizeof ( double ) ) ;
loc -> state = ( struct filesource_state * ) malloc ( sizeof ( struct filesource_state ) ) ;
loc -> state = ( struct filesource_state * ) malloc ( sizeof ( struct filesource_state ) ) ;
loc -> indata = ( struct infiledata * ) malloc ( sizeof ( struct infiledata ) ) ;
loc -> indata -> datavec = ( double * ) malloc ( sizeof ( double ) * stepsize * 1000 ) ;
loc -> indata -> vecallocated = stepsize * 1000 ;
loc -> indata -> maxoccupied = 0 ;
loc -> indata -> actpointer = 0 ;
loc -> indata -> size = stepsize ;
loc -> timeinterval [ 0 ] = loc -> timeinterval [ 1 ] = PARAM_NULL ( timeoffset ) ? 0.0 : PARAM ( timeoffset ) ;
for ( i = 0 ; i < size ; ++ i )
loc -> amplinterval [ 2 * i ] = loc -> amplinterval [ 2 * i + 1 ] = PARAM_NULL ( amploffset ) ? 0.0 : PARAM ( amploffset [ i ] ) ;
/* open the file */
loc -> state -> fp = fopen_with_path ( PARAM ( file ) , "r" ) ;
loc -> state -> atend = 0 ;
if ( ! loc -> state -> fp ) {
@ -195,82 +221,118 @@ void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc.
sprintf ( p , "%s%s%s" , lbuffer , DIR_PATHSEP , PARAM ( file ) ) ;
loc -> state -> fp = fopen ( p , "r" ) ;
free ( p ) ;
}
}
if ( ! loc -> state -> fp ) {
cm_message_printf ( "cannot open file %s" , PARAM ( file ) ) ;
loc -> state -> atend = 1 ;
}
}
/* read, preprocess and store the data */
amplscalesize = PARAM_NULL ( amplscale ) ? 0 : PARAM_SIZE ( amplscale ) ;
amploffssize = PARAM_NULL ( amploffset ) ? 0 : PARAM_SIZE ( amploffset ) ;
count = 0 ;
while ( ! loc -> state -> atend ) {
char line [ 512 ] ;
char * cp , * cpdel ;
char * cp2 ;
double t , tprev = 0 ;
int i ;
if ( ! fgets ( line , sizeof ( line ) , loc -> state -> fp ) ) {
loc -> state -> atend = 1 ;
break ;
}
cpdel = cp = strdup ( line ) ;
/* read the time channel; update the time difference */
while ( * cp & & isspace_c ( * cp ) )
++ cp ;
if ( * cp == '#' | | * cp == ';' ) {
free ( cpdel ) ;
continue ;
}
t = strtod ( cp , & cp2 ) ;
if ( cp2 == cp ) {
free ( cpdel ) ;
continue ;
}
cp = cp2 ;
if ( ! PARAM_NULL ( timescale ) )
t * = PARAM ( timescale ) ;
if ( ! PARAM_NULL ( timerelative ) & & PARAM ( timerelative ) == MIF_TRUE )
t + = tprev ;
else if ( ! PARAM_NULL ( timeoffset ) )
t + = PARAM ( timeoffset ) ;
tprev = t ;
/ * before storing , check if vector size is large enough .
If not , add another 1000 * size doubles * /
if ( count > loc -> indata -> vecallocated - size ) {
loc -> indata -> vecallocated + = size * 1000 ;
loc -> indata -> datavec = ( double * ) realloc ( loc -> indata -> datavec , sizeof ( double ) * loc -> indata -> vecallocated ) ;
}
if ( loc -> indata -> datavec == NULL ) {
cm_message_printf ( "cannot allocate enough memory" ) ;
break ; / / loc -> state -> atend = 1 ;
}
loc -> indata -> datavec [ count ++ ] = t ;
/* read the data channels; update the amplitude difference of each channel */
for ( i = 0 ; i < size ; ++ i ) {
while ( * cp & & ( isspace_c ( * cp ) | | * cp == ',' ) )
++ cp ;
t = strtod ( cp , & cp2 ) ;
if ( cp2 == cp )
break ;
cp = cp2 ;
if ( i < amplscalesize )
t * = PARAM ( amplscale [ i ] ) ;
if ( i < amploffssize )
t + = PARAM ( amploffset [ i ] ) ;
loc -> indata -> datavec [ count ++ ] = t ;
}
free ( cpdel ) ;
}
loc -> indata -> maxoccupied = count ;
if ( loc -> state -> fp ) {
fclose ( loc -> state -> fp ) ;
loc -> state -> fp = NULL ;
}
/* point to the next time */
loc -> indata -> actpointer = stepsize ;
}
amplscalesize = PARAM_NULL ( amplscale ) ? 0 : PARAM_SIZE ( amplscale ) ;
amploffssize = PARAM_NULL ( amploffset ) ? 0 : PARAM_SIZE ( amploffset ) ;
loc = STATIC_VAR ( locdata ) ;
/ * The file pointer is at the same position it was for the last simulator TIME .. .
* If TIME steps backward , for example due to a second invocation of a 'tran' analysis
* then we need to rewind the file to start from the beginning .
* step back in datavec [ loc -> indata -> actpointer ] .
* /
if ( TIME < loc -> timeinterval [ 0 ] ) {
rewind ( loc -> state -> fp ) ;
loc -> timeinterval [ 0 ] = loc -> timeinterval [ 1 ] = PARAM_NULL ( timeoffset ) ? 0.0 : PARAM ( timeoffset ) ;
while ( TIME < loc -> indata -> datavec [ loc -> indata -> actpointer ] & & loc -> indata -> actpointer >= 0 )
loc -> indata -> actpointer - = stepsize ;
loc -> timeinterval [ 0 ] = loc -> indata -> datavec [ loc -> indata -> actpointer ] ;
}
loc -> timeinterval [ 1 ] = loc -> indata -> datavec [ loc -> indata -> actpointer + stepsize ] ;
while ( TIME >= loc -> timeinterval [ 1 ] & & ! loc -> state -> atend ) {
char line [ 512 ] ;
char * cp , * cpdel ;
char * cp2 ;
double t ;
int i ;
if ( ! fgets ( line , sizeof ( line ) , loc -> state -> fp ) ) {
loc -> state -> atend = 1 ;
break ;
while ( TIME > loc -> timeinterval [ 1 ] ) {
loc -> indata -> actpointer + = stepsize ;
if ( loc -> indata -> actpointer > loc -> indata -> maxoccupied ) {
/* we are done */
return ;
}
cpdel = cp = strdup ( line ) ;
loc -> timeinterval [ 1 ] = loc -> indata -> datavec [ loc -> indata -> actpointer ] ;
}
loc -> timeinterval [ 0 ] = loc -> indata -> datavec [ loc -> indata -> actpointer - stepsize ] ;
/* read the time channel; update the time difference */
while ( * cp & & isspace_c ( * cp ) )
++ cp ;
if ( * cp == '#' | | * cp == ';' ) {
free ( cpdel ) ;
continue ;
}
t = strtod ( cp , & cp2 ) ;
if ( cp2 == cp ) {
free ( cpdel ) ;
continue ;
}
cp = cp2 ;
if ( ! PARAM_NULL ( timescale ) )
t * = PARAM ( timescale ) ;
if ( ! PARAM_NULL ( timerelative ) & & PARAM ( timerelative ) == MIF_TRUE )
t + = loc -> timeinterval [ 1 ] ;
else if ( ! PARAM_NULL ( timeoffset ) )
t + = PARAM ( timeoffset ) ;
loc -> timeinterval [ 0 ] = loc -> timeinterval [ 1 ] ;
loc -> timeinterval [ 1 ] = t ;
/* read the channels; update the amplitude difference of each channel */
for ( i = 0 ; i < size ; ++ i )
loc -> amplinterval [ 2 * i ] = loc -> amplinterval [ 2 * i + 1 ] ;
for ( i = 0 ; i < size ; ++ i ) {
while ( * cp & & ( isspace_c ( * cp ) | | * cp == ',' ) )
++ cp ;
t = strtod ( cp , & cp2 ) ;
if ( cp2 == cp )
break ;
cp = cp2 ;
if ( i < amplscalesize )
t * = PARAM ( amplscale [ i ] ) ;
if ( i < amploffssize )
t + = PARAM ( amploffset [ i ] ) ;
loc -> amplinterval [ 2 * i + 1 ] = t ;
}
free ( cpdel ) ;
for ( j = 0 ; j < size ; j ++ ) {
loc -> amplinterval [ 2 * j ] = loc -> indata -> datavec [ loc -> indata -> actpointer - stepsize + j + 1 ] ;
loc -> amplinterval [ 2 * j + 1 ] = loc -> indata -> datavec [ loc -> indata -> actpointer + j + 1 ] ;
}
if ( ! loc -> state -> atend & & loc -> timeinterval [ 0 ] <= TIME & & TIME <= loc -> timeinterval [ 1 ] ) {
if ( loc -> timeinterval [ 0 ] <= TIME & & TIME <= loc -> timeinterval [ 1 ] ) {
if ( ! PARAM_NULL ( amplstep ) & & PARAM ( amplstep ) == MIF_TRUE ) {
int i ;
for ( i = 0 ; i < size ; ++ i )