home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************
- * STEVE SPICE steve punte 10-24-87
- *
- * This program is frequency domain only version of spice. It
- * was developed for the ece-149 class for the simulation of
- * passive and active filters on standard IBM-ATs that normally
- * have insufficient memory for even the reduced version of
- * pspice. This program is written very flexibbly to request
- * memory from the operating system as it is needed. Unfortionately
- * the micro-soft C compiler requires that the maximum amount of
- * memory ever needed be stated before hand. Never the less
- * this is a portable program to any system that compiles C.
- *
- *****************************************************************************
- *
- * This is the header file. All global variables are defined here.
- * If this file is used in file "main", then the phrase "extern"
- * is stripped of from all declarations. Otherwise it remains for
- * use in other files.
- *
- ****************************************************************************/
-
- #include <stdio.h>
- #include <math.h>
- #define TRUE 1
- #define FALSE 0
- #define PIE 3.141592653
- #define STR_LNGTH 20
-
- #define MAIN
- #ifdef MAIN /* Removes extern if used in main.c */
- #define extern
- #endif
- #define ALLCODE /* If all code is present, allows proper compliation*/
- /* Convenient pointers to dynamically allocated arrays */
- #define addm(I, J) (addm_mtrx_ptr + I + N * J)
- #define curr(I ) (curr_vect_ptr + I )
-
- extern struct component
- {
- char name[ STR_LNGTH ]; /* Name of component */
- int node_i; /* One connection of the component */
- char name_i[ STR_LNGTH ]; /* Name of first node */
- int node_j; /* The second connection of the component */
- char name_j[ STR_LNGTH ]; /* Name of second node */
- int node_k; /* A third connection, if existing */
- char name_k[ STR_LNGTH ]; /* Name of third node */
- int node_l; /* A Fourth connection, if existing */
- char name_l[ STR_LNGTH ]; /* Name of fourth node */
- double value; /* The value of the component */
- struct component *link; /* Link foward to next structure or NULL */
- };
-
- extern struct component *begin_caps ; /* Start of capacitor link list */
- extern struct component *begin_inds ; /* Start of inductor link list */
- extern struct component *begin_res ; /* Start of resistor link list */
- extern struct component *begin_vcv ; /* Start of VCV link list */
- extern struct component *begin_vci ; /* Start of VCI link list */
- extern struct component *end_caps ; /* Last entry of capacitor link list */
- extern struct component *end_inds ; /* Last entry of inductor link list */
- extern struct component *end_res ; /* Last entry of resistor link list */
- extern struct component *end_vcv ; /* Last entry of VCV link list */
- extern struct component *end_vci ; /* Last entry of VCI link list */
-
- extern struct component VS_source; /* Special entry for source */
- extern struct component OUT_node; /* Special entry for output node marker */
-
- extern int flag_FS ;
- extern int flag_FE ;
- extern int flag_FP ;
- extern int flag_LOG ;
- extern int flag_PHASE ;
- extern int flag_RADS ;
- extern int flag_PRTCMP ;
- extern int flag_VS ;
- extern int flag_OUT ;
- extern int flag_MTRX ;
-
- extern double freq_start; /* Starting Frequency */
- extern double freq_end; /* Ending Frequency */
- extern int freq_part; /* Number of partitions */
-
- extern int N; /* Number of distinct nodes */
- extern struct cmplx_num *addm_mtrx_ptr; /* Addmittance Matrix Pointer */
- extern struct cmplx_num *curr_vect_ptr; /* Impedance Matrix Pointer */
- /* -------------------------------------------------------------------*/
- /*************************************************************************
- *
- * ENHANCED MATH PACKAGE
- * An extra set of math functions, and in particular
- * macros that perform complex number operations. Note:
- * all arguenments pass to the complex number macros MUST
- * be pointers to a complex structure, and not an
- * actual structure. Also the use of variable names "den"
- * and "cmplx_tmp" will create problems. These are macros,
- * and not subroutines!
- *
- **************************************************************************/
-
- struct cmplx_num { /* The Complex number structure */
- double real;
- double imag;
- };
-
- #define abs(X) ( X > 0 ? X : -X )
- #define sqr(X) ( X )*( X )
-
- #define cset(X, Y, Z) X->real = Y; X->imag = Z
- #define cmpl(X) X->imag = - X->imag
- #define cadd(X, Y, Z) Z->real = X->real + Y->real;\
- Z->imag = X->imag + Y->imag
- #define csub(X, Y, Z) Z->real = X->real - Y->real;\
- Z->imag = X->imag - Y->imag
- #define cmul(X, Y, Z) { \
- struct cmplx_num cmplx_tmp; \
- cmplx_tmp.real = X->real * Y->real - X->imag * Y->imag ; \
- cmplx_tmp.imag = X->real * Y->imag + X->imag * Y->real ; \
- Z->real = cmplx_tmp.real; \
- Z->imag = cmplx_tmp.imag; \
- }
- #define cdiv(X, Y, Z) { \
- struct cmplx_num cmplx_tmp; \
- double den; \
- den = sqr( Y->real ) + sqr( Y->imag ); \
- cmplx_tmp.real = X->real * Y->real + X->imag * Y->imag ; \
- cmplx_tmp.imag = X->imag * Y->real - X->real * Y->imag ; \
- Z->imag = cmplx_tmp.imag / den; \
- Z->real = cmplx_tmp.real / den; \
- }
- #define cmag(X) sqrt( sqr( X->real) + sqr( X->imag))
- /* ----------------------------------------------------------------------------*/
- /************************************************************************
- *
- * Main.c contains the primary loop of the spice simulation, namely
- * the loop that increments frequency. Main also first calls
- * subroutines to read in all the net list, to check for critical
- * information, and to possibly print the input data. For each
- * frequency, the addmitance matrix is recalculated, then
- * inverted. The proper element is picked off, and printed.
- *
- *************************************************************************/
- #ifndef ALLCODE
- #include "header.h"
- #endif
-
- main()
- {
- double freq_delta; /* Frequency increment */
- double freq; /* Current frequency of calculations */
- int i;
-
- initialize();
- read_input();
- if( flag_PRTCMP == TRUE ) print_components(); /* Print all component values */
- check_input();
-
-
- /* Allocate Space for addmitance matrix */
- addm_mtrx_ptr = (struct cmplx_num *)malloc( N * N * sizeof( struct cmplx_num) );
- if( addm_mtrx_ptr <= NULL ) {
- fprintf( stderr, "Insufficient Malloc memory allocations. Fatal error \n");
- exit(1);
- }
- curr_vect_ptr = (struct cmplx_num *)malloc( N * sizeof( struct cmplx_num) );
- if( curr_vect_ptr <= NULL ) {
- fprintf( stderr, "Insufficient Malloc memory allocations. Fatal error \n");
- exit(1);
- }
-
- #ifdef IBM
- printf( "1 \n %d , SSPICE \n", freq_part );
- #endif
-
- freq_delta = (freq_end - freq_start ) /freq_part;
- freq = freq_start ;
- for( i = 0; i <= freq_part ; i++ ) {
- double omega;
- fprintf( stderr, "*");
-
- if( flag_RADS == TRUE ) omega = freq ;
- else omega = 2 * PIE * freq ;
-
- /* Fill addmittance matrix */
- fill_matrix( omega);
- if( flag_MTRX == TRUE ) print_mtrx( addm_mtrx_ptr );
-
- /* Take inverse of addmittance matrix */
- inverse_matrix();
- if( flag_MTRX == TRUE ) print_mtrx( addm_mtrx_ptr );
-
- print_output( freq );
-
- freq += freq_delta ;
- }
-
- } /* End of main */
- /* ----------------------------------------------------------------------- */
- /************************************************************************
- *
- * This file contains two main subroutines: "fill_matrix" walks
- * through all the component link lists, and makes numeric entries
- * into the addmittance matrx. This is only done for one frequency
- * at a time. "inverse_matrx" actually solves for the voltages
- * of all nodes. The solution ends up in the vector "curr", which
- * originaly stands for the net current at each node. The net current
- * at each node is zero, with the exception of the source node. It
- * is assigned an external current of 1.0.
- *
- ***************************************************************************/
-
- #ifndef ALLCODE
- #include "header.h"
- #endif
-
- fill_matrix( omega)
- double omega;
- {
- struct component *x;
- struct cmplx_num addmitt;
- int i, j;
-
- if( omega == 0.0 ) omega = 0.000001 ; /* To prevent division by zero */
-
- /* Sets entire addmitance matrix to zero */
- for( i=0 ; i < N ; i++ ) {
- for( j=0 ; j < N ; j++ ) {
- addm( i, j)->real = 0.0;
- addm( i, j)->imag = 0.0;
- }
- }
-
- /* Enters all resistor addmittances to matrix */
- for( x = begin_res; x != NULL ; x = x->link ) { /* Walks throught all res. */
- cset( (&addmitt) , (1.0 / x->value), 0.0 );
- add_element( &addmitt, x );
- }
-
- /* Enters all capacitor addmittances to matrix */
- for( x = begin_caps; x != NULL ; x = x->link ) { /* Walks throught all cap. */
- cset( (&addmitt) , 0.0 , (omega * x->value) );
- add_element( &addmitt, x );
- }
-
- /* Enters all inductor addmittances to matrix */
- for( x = begin_inds; x != NULL ; x = x->link ) { /* Walks throught all ind. */
- cset( (&addmitt) , 0.0 , ( -1.0 / (omega * x->value)) );
- add_element( &addmitt, x );
- }
-
- /* Enters all Voltage Controlled Current Sources addmittances to matrix */
- for( x = begin_vci; x != NULL ; x = x->link ) {
- cset( (&addmitt) , x->value, 0.0 );
-
- if( x->node_k >= 0 ) { /* Not a ground node */
- if( x->node_i >= 0 ) {
- addm( x->node_k, x->node_i)->real -= addmitt.real;
- addm( x->node_k, x->node_i)->imag -= addmitt.imag;
- }
- if( x->node_j >= 0 ) {
- addm( x->node_k, x->node_j)->real += addmitt.real;
- addm( x->node_k, x->node_j)->imag += addmitt.imag;
- }
- }
-
- if( x->node_l >= 0 ) { /* Not a ground node */
- if( x->node_i >= 0 ) {
- addm( x->node_l, x->node_i)->real += addmitt.real;
- addm( x->node_l, x->node_i)->imag += addmitt.imag;
- }
- if( x->node_j >= 0 ) {
- addm( x->node_l, x->node_j)->real -= addmitt.real;
- addm( x->node_l, x->node_j)->imag -= addmitt.imag;
- }
- }
- }
-
- /* Enters all Voltage Controlled Voltage Sources addmittances to matrix */
- for( x = begin_vcv; x != NULL ; x = x->link ) {
- cset( (&addmitt) , x->value, 0.0 );
- for( i = 0 ; i < N ; i ++) {
- addm( x->node_k, i)->real = 0.0 ;
- addm( x->node_k, i)->imag = 0.0 ;
- }
- cset( addm( x->node_k, x->node_k), 1.0, 0.0 );
-
- if( x->node_j >= 0 ) { /* Not a ground node */
- addm( x->node_k, x->node_j)->real = x->value ;
- }
- if( x->node_i >= 0 ) { /* Not a ground node */
- addm( x->node_k, x->node_i)->real = -( x->value) ;
- }
- }
-
- /* Enters source addmittance to matrix */
- for( i = 0 ; i < N ; i ++) {
- addm( (&VS_source)->node_i, i)->real = 0.0 ;
- addm( (&VS_source)->node_i, i)->imag = 0.0 ;
- }
- cset( addm( (&VS_source)->node_i, (&VS_source)->node_i), 1.0, 0.0 );
-
-
- /* Initialize current vertor */
- for( i = 0; i < N; i++ ) { cset( curr( i ), 0.0 , 0.0 ); }
- cset( curr( (&VS_source)->node_i), 1.0, 0.0 );
- } /* End of enter_matrix */
-
- add_element( a, x)
- struct cmplx_num *a;
- struct component *x;
- {
-
- if( (x->node_i >= 0) && (x->node_j >=0) ) {
- addm( x->node_i, x->node_i)->real += a->real;
- addm( x->node_i, x->node_i)->imag += a->imag;
-
- addm( x->node_j, x->node_j)->real += a->real;
- addm( x->node_j, x->node_j)->imag += a->imag;
-
- addm( x->node_i, x->node_j)->real -= a->real;
- addm( x->node_i, x->node_j)->imag -= a->imag;
-
- addm( x->node_j, x->node_i)->real -= a->real;
- addm( x->node_j, x->node_i)->imag -= a->imag;
- }
-
- else if( (x->node_i >= 0) && (x->node_j < 0) ) {
- addm( x->node_i, x->node_i)->real += a->real;
- addm( x->node_i, x->node_i)->imag += a->imag;
- }
-
- else if( (x->node_i < 0) && (x->node_j >= 0) ) {
- addm( x->node_j, x->node_j)->real += a->real;
- addm( x->node_j, x->node_j)->imag += a->imag;
- }
-
- else {
- fprintf( stderr, "Component %s Seems to have no conections to any active nodes. It is ignored \n", x->name );
- }
-
-
- }
-
-
- #define csubeq(X, Y) { \
- X->real -= Y->real; \
- X->imag -= Y->imag; \
- }
-
- /********************************************************************
- * The following routing is an enhanced inversion gaussain elimination
- * inversion routing. Is seeks the largest value in any column, and
- * then performs pivoting and elimination using this entry. In order to
- * keep track of which columns have already been pivoted, the algorithm
- * checks the sum of the magnitude of the elements along the row to
- * just before the test pivot element. If this sum is zero, or very
- * close to it, it is assumed that this row has already been pivoited.
- **********************************************************************/
- inverse_matrix()
- {
- struct cmplx_num one_x, tmp_x, scale_x;
- struct cmplx_num *one, *tmp, *scale;
- int i, j, k, ii;
- double pre_max; /* Previous Maximum */
- double cur_max; /* Current Maximum */
- double par_row_sum ; /* Partial Row Sum. To detect if this row has already been cleared */
-
- /* Need Temporary space that are pointers */
- one = &one_x;
- tmp = &tmp_x;
- scale = &scale_x;
-
- cset( one, 1.0, 0.0);
-
-
- /* Scan across all columns */
- for( j = 0; j < N; j++) {
-
- /* Find Maximun entry in this row. The magnitude of all previous entries in
- this row is sumed in "par_row_sum". Only if this sum is zero is it
- valid to pivot on this row. */
- pre_max = 0.0 ;
- for( i = 0; i < N; i++ ) {
- par_row_sum = 0.0;
- for( k = 0; k < j ; k++ ) par_row_sum += cmag( addm( i, k) ) ;
- cur_max = cmag( addm( i, j) );
-
- /* test this pivot point */
- if( ( cur_max > pre_max ) && ( cur_max > (1000000000 * par_row_sum ) )) {
- ii = i; /* Mark this N as ii */
- pre_max = cur_max ;
- }
- }
-
- /* Normalize the row chosen above */
- if( cmag( addm( ii, j )) == 0.0 ) {
- fprintf( stderr,"##ERROR##\n, division by zero.\n");
- exit(0);
- }
- cdiv( one , addm( ii, j), scale );
- for( k = j; k < N; k++ ) {
- cmul( addm( ii, k), scale, addm( ii, k) );
- }
- cmul( curr( ii), scale, curr( ii) );
-
-
- /* Null out all other entries in this column, except
- choses entry to zero. */
- for( i = 0; i < N; i++ ) {
- /* Don't do if pivot row, or if semi-pivot element is zero */
- if( ( i != ii ) && ( cmag( addm( i , j ) ) != 0.0) ) {
- cmul( addm( i, j), curr( ii ), tmp );
- csubeq( curr( i ), tmp );
- for( k = N-1; k >= j ; k-- ) {
- cmul( addm( i, j), addm( ii, k), tmp );
- csubeq( addm( i, k), tmp );
- }
- }
- }
- } /* End of Column Scan */
- } /* End of matrix inversion */
- /*****************************************************************************
- *
- * This file contains subroutines for reading in the net list, processing
- * the node names into node numbers, setting true appropriate flags, and
- * recording misc. infomation, such as starting frequency, etc.
- *
- *****************************************************************************/
-
- #ifndef ALLCODE
- #include "header.h"
- #endif
- #define fscanf my_fscanf
-
- /* Primary input read loop. Exits when EOF is detected */
- read_input()
- {
- char str[ STR_LNGTH ] ; /* String buffer for input reading */
- FILE *fp_in = stdin;
-
- /* Loops over all input lines, and enters data into proper variables */
- while( fscanf( fp_in, "%s", str) != EOF ) {
- double scan_modifier();
- struct component *add_cmpt_link();
-
- if( !strcmp( str, "FS") ) {
- fscanf( fp_in, "%f", &freq_start);
- freq_start *= (int)scan_modifier( fp_in );
- flag_FS = TRUE;
- }
-
- else if( !strcmp( str, "FE") ) {
- fscanf( fp_in, "%f", &freq_end);
- freq_end *= (int)scan_modifier( fp_in );
- flag_FE = TRUE;
- }
-
- else if( !strcmp( str, "FP") ) {
- fscanf( fp_in, "%d", &freq_part);
- freq_part *= (int)scan_modifier( fp_in );
- flag_FP = TRUE;
- }
-
- else if( !strcmp( str, "PHASE") ) {
- flag_PHASE = TRUE;
- scan_modifier( fp_in );
- }
-
- else if( !strcmp( str, "LOG") ) {
- flag_LOG = TRUE;
- scan_modifier( fp_in );
- }
-
- else if( !strcmp( str, "MTRX") ) {
- flag_MTRX = TRUE;
- scan_modifier( fp_in );
- }
-
- else if( !strcmp( str, "RADS") ) {
- flag_RADS = TRUE;
- scan_modifier( fp_in );
- }
-
- else if( !strcmp( str, "PRTCMP") ) {
- flag_PRTCMP = TRUE;
- scan_modifier( fp_in );
- }
-
- else if( !strcmp( str, "OUT") ) {
- flag_OUT = TRUE;
- fscanf( fp_in, "%s", OUT_node.name_i );
- OUT_node.node_i = node_numb( OUT_node.name_i);
- scan_modifier( fp_in );
- }
-
- else if( *str == 'L' ) {
- add_cmpt_link( &begin_inds, &end_inds );
- strcpy( end_inds->name, str);
- fscanf( fp_in, "%s", end_inds->name_i );
- end_inds->node_i = node_numb( end_inds->name_i);
- fscanf( fp_in, "%s", end_inds->name_j );
- end_inds->node_j = node_numb( end_inds->name_j);
- fscanf( fp_in, "%f", &end_inds->value );
- end_inds->value *= scan_modifier( fp_in );
- }
-
- else if( *str == 'C' ) {
- add_cmpt_link( &begin_caps, &end_caps );
- strcpy( end_caps->name, str);
- fscanf( fp_in, "%s", end_caps->name_i );
- end_caps->node_i = node_numb( end_caps->name_i);
- fscanf( fp_in, "%s", end_caps->name_j );
- end_caps->node_j = node_numb( end_caps->name_j);
- fscanf( fp_in, "%f", &end_caps->value );
- end_caps->value *= scan_modifier( fp_in );
- }
-
- else if( *str == 'R' ) {
- add_cmpt_link( &begin_res, &end_res );
- strcpy( end_res->name, str);
- fscanf( fp_in, "%s", end_res->name_i );
- end_res->node_i = node_numb( end_res->name_i);
- fscanf( fp_in, "%s", end_res->name_j );
- end_res->node_j = node_numb( end_res->name_j);
- fscanf( fp_in, "%f", &end_res->value );
- end_res->value *= scan_modifier( fp_in );
- }
-
- else if( !strcmp( str, "VCI") ) {
- add_cmpt_link( &begin_vci, &end_vci );
- strcpy( end_vci->name, str);
- fscanf( fp_in, "%s", end_vci->name_i );
- end_vci->node_i = node_numb( end_vci->name_i);
- fscanf( fp_in, "%s", end_vci->name_j );
- end_vci->node_j = node_numb( end_vci->name_j);
- fscanf( fp_in, "%s", end_vci->name_k );
- end_vci->node_k = node_numb( end_vci->name_k);
- fscanf( fp_in, "%s", end_vci->name_l );
- end_vci->node_l = node_numb( end_vci->name_l);
- fscanf( fp_in, "%f", &end_vci->value );
- end_vci->value *= scan_modifier( fp_in );
- }
-
- else if( !strcmp( str, "VCV") ) {
- add_cmpt_link( &begin_vcv, &end_vcv );
- strcpy( end_vcv->name, str);
- fscanf( fp_in, "%s", end_vcv->name_i );
- end_vcv->node_i = node_numb( end_vcv->name_i);
- fscanf( fp_in, "%s", end_vcv->name_j );
- end_vcv->node_j = node_numb( end_vcv->name_j);
- fscanf( fp_in, "%s", end_vcv->name_k );
- end_vcv->node_k = node_numb( end_vcv->name_k);
- fscanf( fp_in, "%f", &end_vcv->value );
- end_vcv->value *= scan_modifier( fp_in );
- }
-
- else if( !strcmp( str, "VS") ) {
- flag_VS = TRUE;
- fscanf( fp_in, "%s", VS_source.name_i );
- VS_source.node_i = node_numb( VS_source.name_i);
- scan_modifier( fp_in );
- }
-
-
- else {
- fprintf( stderr, "Syntax Error: Unrecognized input string \"%s\". String ignored. \n", str );
- }
- } /* End of while */
- } /* End of read routine */
-
-
-
-
-
- /* Assigns a number to any ascii node name. Number are chosen in
- * sequential order beginning with zero. If the name passed to
- * this routing already exits, then the node number assigned
- * to this name previously is returned. Gnd and several variations
- * are special reserved names which always have the value -1
- * associated with them.
- */
- node_numb( str )
- char *str;
- {
- struct name_list { /* Link List structure to keep node names */
- char name[ STR_LNGTH ];
- int node_number;
- struct name_list *link;
- };
-
- static struct name_list *bgn_nm_lst = NULL;
- static struct name_list *end_nm_lst = NULL;
- struct name_list *new_link, *x;
-
- if( !strcmp( str, "GND") || !strcmp( str, "gnd") || !strcmp( str, "Gnd") ) return( -1 );
- for( x = bgn_nm_lst; x != NULL; x = x->link )
- {
- if( !strcmp( x->name, str)) return( x->node_number );
- }
-
- new_link = (struct name_list *)malloc( sizeof (struct name_list));
-
- new_link->link = NULL;
- if( bgn_nm_lst == NULL ) bgn_nm_lst = new_link; /* IF first link, start chain */
- else end_nm_lst->link = new_link; /* link head */
- end_nm_lst = new_link; /* Update end pointer */
-
- strcpy( new_link->name, str);
- new_link->node_number = N++;
- return( new_link->node_number );
- }
-
-
- #undef fscanf
- /* A lousy fucking patch for micro-soft C. It doesn't
- * seem to read floating point numbers properly.
- */
- my_fscanf( fp, str, reg)
- FILE *fp;
- char *str;
- union {
- int x;
- double y;
- char t;
- } *reg;
-
- {
- double atof();
- if( !strcmp( str, "%f") ) {
- char temp[40];
- fscanf( fp, "%s", temp);
- reg->y = atof( temp);
- }
- else fscanf( fp, str, reg);
- }
- #define fscanf my_fscanf
- /* ------------------------------------------------------------------------ */
- /********************************************************************
- *
- * This file contains all routines which print anything to
- * the user.
- *
- **********************************************************************/
-
- #ifndef ALLCODE
- #include "header.h"
- #endif
-
- #define FLG_STR(X) if( X == TRUE ) strcpy( str, "TRUE" ); \
- else strcpy( str, "FALSE")
-
- /* Prints components and all other important information */
- print_components()
- {
- FILE *fp_out = stdout;
- char str[ STR_LNGTH ] ; /* String buffer for input reading */
- struct component *x; /* a pointer to current component structure */
-
- FLG_STR(flag_FS);
- fprintf( fp_out,"+Starting frequency flag is set %s \n", str);
- FLG_STR(flag_FE);
- fprintf( fp_out,"+Ending frequency flag is set %s \n", str);
- FLG_STR(flag_FP);
- fprintf( fp_out,"+Number of Points flag is set %s \n", str);
- FLG_STR(flag_RADS);
- fprintf( fp_out,"+Radian flag is set %s \n", str);
- FLG_STR(flag_LOG);
- fprintf( fp_out,"+Logarithmitic flag is set %s \n", str);
- FLG_STR(flag_VS);
- fprintf( fp_out,"+Source designation flag is set %s \n", str);
- FLG_STR(flag_OUT);
- fprintf( fp_out,"+Output designation flag is set %s \n", str);
- fprintf( fp_out,"\n");
-
- if( flag_FS == TRUE ) fprintf( fp_out,"+Starting Frequency = %f \n", freq_start);
- if( flag_FE == TRUE ) fprintf( fp_out,"+Ending Frequency = %f \n", freq_end);
- if( flag_FP == TRUE ) fprintf( fp_out,"+Number of partitions is = %d \n", freq_part);
-
- fprintf( fp_out, "\n Component I Node J Node K Node L Node Value \n");
-
- for( x = begin_res; x != NULL ; x = x->link )
- fprintf( fp_out, "+ %10s %8s %8s %10e Ohms \n", x->name, x->name_i, x->name_j, x->value);
-
- for( x = begin_inds; x != NULL ; x = x->link )
- fprintf( fp_out, "+ %10s %8s %8s %10e Heneries \n", x->name, x->name_i, x->name_j, x->value);
-
- for( x = begin_caps; x != NULL ; x = x->link )
- fprintf( fp_out, "+ %10s %8s %8s %10e Farads \n", x->name, x->name_i, x->name_j, x->value);
-
- for( x = begin_vcv; x != NULL ; x = x->link )
- fprintf( fp_out, "+ %10s %8s %8s %8s %10e Av \n", x->name, x->name_i, x->name_j, x->name_k , x->value);
-
- for( x = begin_vci; x != NULL ; x = x->link )
- fprintf( fp_out, "+ %10s %8s %8s %8s %8s %10e Mohs \n", x->name, x->name_i, x->name_j, x->name_k , x->name_l , x->value);
-
- fprintf( fp_out, "+ VS %8s \n", VS_source.name_i);
- fprintf( fp_out, "+ OUT %8s \n", OUT_node.name_i);
-
- } /* End of print routine */
-
-
-
-
- /* Prints out all elements of a complex matrix
- * Primarily to be used for checking and debugging
- */
- print_mtrx( mtrx )
- struct cmplx_num *mtrx;
- {
- FILE *fp_out = stdout ;
- int i, j;
-
- fprintf( fp_out,"------------------------------------------------------------ \n");
- for( i=0; i<N ; i++ ) {
- for( j=0; j<N ; j++ ) fprintf( fp_out, "%6.2f ", (mtrx + i + N*j)->real);
- fprintf( fp_out, " %6.2f\n", curr( i )->real);
- for( j=0; j<N ; j++ ) fprintf( fp_out, "%6.2f ", (mtrx + i + N*j)->imag);
- fprintf( fp_out, " %6.2f\n", curr( i )->imag);
- fprintf( fp_out, "\n");
- }
- fprintf( fp_out,"------------------------------------------------------------ \n");
- }
-
-
-
- /* Prints the output transfer function */
- print_output( omega)
- double omega;
- {
- double magnitude, phase;
- int i, ii, out;
- double pre_max;
-
- out = OUT_node.node_i ;
- pre_max = 0.0 ;
- for( i =0 ; i < N ; i++ ) {
- if( cmag( addm( i, out )) > pre_max ) {
- ii = i;
- pre_max = cmag( addm( i, out ));
- }
- }
-
-
- phase = atan2( curr( ii )->imag, curr( ii )->real );
- magnitude = cmag( curr( ii ) );
- if( magnitude == 0.0 ) magnitude = 1000000000.0;
-
- #ifdef IBM
- if( flag_LOG == TRUE ) printf( "%f , %f \n", omega, ( -20 * log10( magnitude ) ) );
- else if( flag_PHASE == TRUE ) printf( "%f , %f \n", omega, ( 180 * phase / PIE) );
- else printf( "%f , %f \n", omega, magnitude );
-
- #else
- if( flag_LOG == TRUE ) printf( "%f %f \n", omega, ( -20 * log10( magnitude ) ) );
- else if( flag_PHASE == TRUE ) printf( "%f %f \n", omega, ( 180 * phase / PIE ) );
- else printf( "%f %f \n", omega, magnitude );
- #endif
- }
- /* ----------------------------------------------------------------------------- */
- /****************************************************************************
- *
- * General miscellaneous subroutines that I didn't want to
- * be cluttering up the more improtant files.
- *
- *****************************************************************************/
-
- #ifndef ALLCODE
- #include "header.h"
- #endif
-
-
- /* Looks for some type of value modifie, such as kilo (x1000)
- * or micro (x0.000001). Then will be expecting a colon as end
- * of line marker. Returns a double persion number for
- * scaling purposes.
- */
-
- double scan_modifier( input )
- FILE *input;
- {
- double scale = 1.0;
- char string[ STR_LNGTH ];
-
- while( (fscanf( input, "%s", string) != EOF) && (*string != ';' ) ) {
-
- switch( *string) {
-
- case 'K':
- scale = 1000;
- break;
-
- case 'M':
- scale = 1000000;
- break;
-
- case 'G':
- scale = 1000000000;
- break;
-
- case 'm':
- scale = 0.001;
- break;
-
- case 'u':
- scale = 0.000001;
- break;
-
- case 'n':
- scale = 0.000000001;
- break;
-
- case 'p':
- scale = 0.000000000001;
- break;
-
- case 'E':
- {
- int K;
- fscanf( input, "%d", &K);
- if( K > 30 ) K = 30;
- if( K < -30 ) K = -30;
- while( K-- > 0 ) scale *= 10;
- while( K++ < 0 ) scale *= 0.1;
- }
- break;
-
- default:
- fprintf( stderr, "Unrecognized string \"%s\" \n", string);
- fprintf( stderr, "Metric modifying unit expected. \n" );
- fprintf( stderr, "String Ignored. \n");
-
-
- }
- }
- return( scale );
- }
-
-
- /* Add a Component structor to the Link. A component structor is
- * added to the link list. The end_ptr_add arguement is the ADDRESS of a
- * pointer which points to the last structure in the list. In the
- * case of a zero list, "pointer_address" is the ADDRESS of the
- * variable "begin_list"
- */
-
- struct component *add_cmpt_link( bgn_ptr_add, end_ptr_add )
- struct component **end_ptr_add;
- struct component **bgn_ptr_add;
- {
- struct component *new_link;
-
- if( ( new_link = (struct component *)malloc( sizeof ( struct component ) ) ) == NULL ) {
- fprintf( stderr, "Operating system fault Insufficient memory resources. \n");
- fprintf( stderr, "Fatal Error. \n");
- exit(1);
- }
-
- new_link->link = NULL; /* Link tail */
- if( *bgn_ptr_add == NULL ) *bgn_ptr_add = new_link; /* IF first, Start Chain */
- else (*end_ptr_add)->link = new_link; /* link head */
- *end_ptr_add = new_link; /* Update end pointer */
- return( new_link );
- }
-
-
-
- /*
- * Initializes global variables only.
- * This cannot be nicely done in header.h due to
- * its dual nature use with a makefile
- */
-
- initialize()
- {
- begin_caps = NULL; /* Start of capacitor link list */
- begin_inds = NULL; /* Start of inductor link list */
- begin_res = NULL; /* Start of resistor link list */
- begin_vcv = NULL; /* Start of VCV link list */
- begin_vci = NULL; /* Start of VCI link list */
- end_caps = NULL; /* Last entry of capacitor link list */
- end_inds = NULL; /* Last entry of inductor link list */
- end_res = NULL; /* Last entry of resistor link list */
- end_vcv = NULL; /* Last entry of VCV link list */
- end_vci = NULL; /* Last entry of VCI link list */
-
- flag_FS = FALSE;
- flag_FE = FALSE;
- flag_FP = FALSE;
- flag_LOG = FALSE;
- flag_PHASE = FALSE;
- flag_RADS = FALSE;
- flag_PRTCMP = FALSE;
- flag_VS = FALSE;
- flag_OUT = FALSE;
- flag_MTRX = FALSE;
-
- N = 0;
- }
-
-
- /* Checks if essential input informaiton is present */
- check_input()
- {
-
- if( flag_VS == FALSE ) {
- fprintf( stderr, "No source node has been specified! \n" );
- fprintf( stderr, "Fatal Error. \n");
- exit(1);
- }
-
- if( flag_OUT == FALSE ) {
- fprintf( stderr, "No output node has been specified! \n" );
- fprintf( stderr, "Fatal Error. \n");
- exit(1);
- }
-
- if( flag_FS == FALSE ) {
- fprintf( stderr, "Starting frequency unspecified! \n" );
- fprintf( stderr, "Fatal Error. \n");
- exit(1);
- }
-
- if( flag_FE == FALSE ) {
- fprintf( stderr, "Ending frequency unspecified! \n" );
- fprintf( stderr, "Fatal Error. \n");
- exit(1);
- }
-
- if( flag_FP == FALSE ) {
- fprintf( stderr, "Number of frequency partitions unspecified! \n" );
- fprintf( stderr, "Default of 20 will be used. \n");
- freq_part = 20;
- }
- }
- /* ------------------------------------------------------------------------- */
-