783 views

Uploaded by Santiago Morillo

- ATP QUICK GUIDE
- Rulebook
- EL-4650, EMTP APLICATION GUIDE
- Atp Emtp Rule Book Download - diakakaconpue.pdf
- EL-4651
- Electromagnetic Transient in Power System and Insulation Coordination Studies
- ATP Draw Tutorial
- TRANSFORMER MODELING IN ATP EMTP
- Vacuum Circuit Breaker Model.pdf
- - Vacuum Circuit Breaker Current-Zero Phenomena
- Documentation Using EMTP
- Thesis - Simulating Power Quality Problems by Atp-emtp
- TR7 TP133 Full Content Part1 مهم
- ATPDraw%Manual%3.5
- Comparison of Simulation Tools Atp Emtp and Matlab Simulink for Time Domain Power System Transient Studies
- EL EL-4651-V2.pdf-4651-V2
- Atpdraw User Manual
- Power Syst Electromagnetic Transient
- Surge Arrester Modeling
- EMTP RV

You are on page 1of 169

April 1996

ACKNOWLEDGMENTS

The writing of this manual would not have been possible without the participation of the many users of MODELS who, over the years, have contributed suggestions and prompted discussions on many aspects of the language and its use in ATP. These people certainly deserve a large share of the credit for the work that has been done.

PREFACE

This Users Guide has been written with the purpose of introducing the MODELS language for use with ATP. It is written mostly in a conversational style, as opposed to the more formal descriptions found in the MODELS Language Manual of the ATP Rule Book. The purpose of this guide is to explain how the MODELS language is held together, and to illustrate its usage with discussions and examples. I realize that a manual like this is never done. There are many aspects to using a programming language and to doing simulation. They are best understood through one's own experience and glimpses at the experience of others. We can continue adding examples to this Guide forever. This first version covers the basic aspects of using the MODELS language. The main features of the language are discussed in detail and illustrated with examples. The interface between MODELS and ATP is also discussed at length. What is not included are detailed examples of electrical and control components, descriptions which, in my opinion, are beyond the scope of this introduction. The objective of this manual is to explain the "how" and the "why" of using MODELS. The "what" of the applications belongs to one or more separate tutorials covering those subjects, for the application specialists to provide. As it is true for any tool, how much a program is used depends to a large extent on how much its features are understood. With the usual time pressure of our work, of course we wish to be able to use something like this instantly. Having the time to play with a new tool is a luxury we can't always afford. But one has to realize that any product that took a few years to prepare needs at least a few hours of exposure to it to get the whole picture. I hope that the time looking at this manual will be time well spent. Laurent Dub, April 1996.

OUTLINE

Acknowledgments Preface Outline Contents Introduction 1. Basic aspects of the MODELS language 2. Writing a model 3. Writing expressions 4. Specifying simulation directives 5. Using a model 6. Using MODELS in ATP 7. Libraries of models and functions Appendix A Syntax of the MODELS language Appendix B Keywords of the MODELS language Appendix C Pre-defined constants and variables Appendix D Pre-defined functions Bibliography Index In closing ...

CONTENTS

Acknowledgments ..................................................................................................i Preface.................................................................................................................. ii Outline.................................................................................................................. iii Contents............................................................................................................... iv Introduction ...........................................................................................................1 1. Basic aspects of the MODELS language .........................................................2 1.1. Why use MODELS....................................................................................2 1.1.1. MODELS in ATP................................................................................2 1.1.2. Starting to use MODELS ...................................................................2 1.1.3. Overall form .......................................................................................3 1.1.4. Similar to a programming language ...................................................3 1.1.5. What's particular to MODELS ............................................................4 1.1.6. What about TACS?............................................................................5 1.1.7. Reasons for using MODELS in a project ...........................................6 1.2. Value-holding elements, and values .........................................................6 1.2.1. Kinds of value-holding elements ........................................................6 1.2.2. Scalars and arrays.............................................................................7 1.2.3. Use of arrays .....................................................................................8 1.2.4. Representation of numbers ...............................................................9 1.2.5. Limits .................................................................................................9 1.3. Notation, format, and conventions ............................................................9 1.3.1. Model, MODELS, and MODEL ..........................................................9 1.3.2. Equal sign and assignment sign ......................................................10 1.3.3. Parentheses, brackets, and braces .................................................10 1.3.4. Blank lines .......................................................................................11 1.3.5. Names .............................................................................................11 1.3.6. Delimiters.........................................................................................11 1.3.7. Comments .......................................................................................12 1.3.8. Line indentation ...............................................................................12 2. Writing a model ..............................................................................................13 2.1. Defining the value-holding elements .......................................................13 2.1.1. Defining constant elements..............................................................13 2.1.2. Defining data elements ....................................................................14 2.1.2.1. Using a data value as an array dimension................................14 2.1.2.2. Dependent data values.............................................................14 2.1.3. Defining input elements ...................................................................15 2.1.4. Defining variable elements...............................................................16 2.1.5. Defining output elements .................................................................17 2.2. Defining the submodels...........................................................................17 2.2.1. Locally-defined submodels ..............................................................18 2.2.2. Foreign submodels ..........................................................................19 2.2.3. External submodels .........................................................................21 2.3. Defining the functions..............................................................................23 2.3.1. Statement functions .........................................................................23

i 2.3.2. Pointlist functions.............................................................................24 2.3.2.1. External point list ......................................................................25 2.3.3. Foreign functions .............................................................................26 2.4. Writing the procedures ............................................................................28 2.4.1. The EXEC procedure.......................................................................28 2.4.2. The INIT procedure..........................................................................28 2.4.2.1. Executing both INIT and EXEC at time zero.............................29 2.4.2.2. INIT procedure and HISTORY assignment ..............................29 2.4.3. Named procedures ..........................................................................30 2.5. Writing the statements of a procedure ....................................................32 2.5.1. Value assignment statement............................................................32 2.5.2. Differential equation, Laplace and z transfer functions ....................33 2.5.2.1. Numerical solution ....................................................................34 2.5.2.2. Initialization...............................................................................36 2.5.2.3. Values of y at t0........................................................................37 2.5.2.4. Using CDIFFEQ, CLAPLACE, and CZFUN ..............................37 2.5.2.5. Limits ........................................................................................37 2.5.3. Integral value assignment ................................................................38 2.5.4. History expression assignment ........................................................39 2.5.5. IF statement.....................................................................................40 2.5.5.1. Explicit IF statement .................................................................40 2.5.5.2. Implicit IF statement .................................................................41 2.5.6. WHILE statement.............................................................................42 2.5.7. FOR statement ................................................................................43 2.5.8. DO statement...................................................................................44 2.5.9. REDO statement..............................................................................45 2.5.10. COMBINE statement .....................................................................45 2.5.10.1. Using the linear COMBINE for linear equations......................46 2.5.10.2. Using the iterated COMBINE for nonlinear equations ............49 2.5.10.3. Using the linear COMBINE for nonlinear equations................50 2.5.11. ERROR statement .........................................................................51 2.5.12. USE statement...............................................................................52 2.5.13. Call to a procedure ........................................................................53 2.5.14. Call to a pre-defined procedure .....................................................53 2.5.14.1. WRITE() procedure ................................................................53 2.5.14.2. WRITE1(), WRITE2() procedure ............................................54 3. Writing expressions ........................................................................................55 3.1. Regular expressions ...............................................................................55 3.1.1. Referring to a named value-holding element ...................................55 3.1.2. Specifying a numerical value ...........................................................58 3.1.3. Using a value calculated by a function.............................................58 3.1.4. Using a value calculated by a procedure .........................................59 3.1.5. Logical and numerical operators......................................................59 3.1.6. Limits on a regular expression .........................................................60 3.1.7. Using expressions with arrays .........................................................61 3.2. Special expressions ................................................................................62 3.2.1. Linear sum .......................................................................................62

USERS GUIDE TO MODELS IN ATP

i 3.2.2. Polynomial of derivatives .................................................................63 3.2.3. Integral expression ..........................................................................63 Specifying simulation directives......................................................................66 4.1. Specifying the time step range................................................................66 4.2. Specifying the input interpolation method ...............................................67 4.3. Specifying the size of the delay storage..................................................68 4.4. Specifying history expressions................................................................69 Using a model ................................................................................................71 5.1. Assigning data values .............................................................................71 5.2. Assigning input values ............................................................................71 5.3. Retrieving output values..........................................................................72 5.4. Specifying simulation directives ..............................................................72 5.5. Calling a model more than once per time step........................................73 5.6. State of a model......................................................................................74 Using MODELS in ATP ..................................................................................76 6.1. The MODELS section of a data case......................................................76 6.1.1. Inputs from ATP...............................................................................77 6.1.1.1. Inputs from the circuit ...............................................................77 6.1.1.2. Inputs from a PL4 plot file.........................................................78 6.1.1.3. Inputs from the TACS section...................................................80 6.1.1.4. Inputs from ATP program variables ..........................................82 6.1.2. Outputs to ATP ................................................................................83 6.1.3. Variables in the MODELS section....................................................84 6.1.4. RECORD for printout/plotting...........................................................84 6.1.5. Model descriptions...........................................................................85 6.1.6. MODELS formatting vs. ATP formatting ..........................................87 6.2. Using a model in the MODELS section ...................................................87 6.3. Using a model with the type-94 component ............................................90 6.3.1. Thevenin, iterated, and Norton ........................................................91 6.3.2. Initializing the type-94 component ...................................................94 6.3.3. Foreign models with a type-94.........................................................95 6.4. Using MODELS with ATP's FREQUENCY SCAN...................................96 6.5. Steady-state initialization ........................................................................97 6.6. List sizes in ATP for MODELS ................................................................99 Libraries of models and functions.................................................................100 7.1. Signal sources ......................................................................................100 7.1.1. Examples of some common sources .............................................101 7.1.2. Sample data case ..........................................................................102 7.2. Library of complex-value functions........................................................103 7.2.1. Examples of complex-value functions............................................103 7.2.2. Sample data case ..........................................................................105 7.3. Library of TACS-like devices.................................................................106 7.3.1. TACS type-50 frequency meter .....................................................106 7.3.2. TACS type-51 relay-operated switch .............................................107 7.3.3. TACS type-52 level-triggered switch..............................................107 7.3.4. TACS type-53 transport delay........................................................108 7.3.5. TACS type-54 pulse delay .............................................................108

USERS GUIDE TO MODELS IN ATP

4.

5.

6.

7.

i 7.3.6. TACS type-55 digitizer ...................................................................110 7.3.7. TACS type-56 point-by-point nonlinearity ......................................110 7.3.8. TACS type-57 time-sequenced switch...........................................110 7.3.9. TACS type-58 controlled integrator................................................111 7.3.10. TACS type-59 simple derivative...................................................112 7.3.11. TACS type-60 input-IF component ..............................................112 7.3.12. TACS type-61 signal selector ......................................................112 7.3.13. TACS type-62 sample/hold and track/hold...................................113 7.3.14. TACS type-63 instantaneous min/max ........................................114 7.3.15. TACS type-64 min/max tracking ..................................................115 7.3.16. TACS type-65 accumulator / counter...........................................116 7.3.17. TACS type-66 RMS value............................................................117 Appendix A Syntax of the MODELS language .............................................118 MODELS section in ATP...............................................................................118 Description of a local model ..........................................................................119 Statement......................................................................................................123 Directive in a USE statement ........................................................................128 Expression ....................................................................................................129 Regular expression .......................................................................................130 Value-holding element ..................................................................................132 Syntactic element..........................................................................................133 Appendix B Keywords of the MODELS language.........................................135 Keywords of the MODELS section of ATP ....................................................135 Keywords of the Model description ...............................................................136 Keywords of the Statements .........................................................................137 Keywords of the Directives in a USE statement............................................138 Keywords of the Expressions........................................................................138 Keywords of the Regular expression ............................................................139 Keywords of the Comments ..........................................................................139 Appendix C Pre-defined constants and variables.........................................140 Pre-defined constants ...................................................................................140 Pre-defined global variables..........................................................................140 Pre-defined local variables............................................................................141 Appendix D Pre-defined functions ................................................................143 Numerical functions ......................................................................................143 1-to-1 functions returning one value for each argument ...........................143 2-argument functions returning a single value ..........................................144 n-argument functions returning a single value ..........................................145 Logical functions ...........................................................................................145 1-to-1 functions returning one value for each argument ...........................145 n-argument functions returning a single value ..........................................146 Random value functions................................................................................146 Simulation functions ......................................................................................148 deriv(x)......................................................................................................149 deriv2(x)....................................................................................................150 prevval(x)..................................................................................................151 delay(x, dval, pol)......................................................................................151

USERS GUIDE TO MODELS IN ATP

i predval(x, tval, pol) ...................................................................................151 predtime(x, xval, pol) ................................................................................152 backval(x, tval, pol) ...................................................................................152 backtime(x, xval, pol) ................................................................................152 histval(x, tval)............................................................................................153 histdef(x)...................................................................................................153 Bibliography ......................................................................................................154 Index .................................................................................................................159 In closing ... .......................................................................................................165

INTRODUCTION

This manual starts with a discussion of the basic aspects of the MODELS language, providing a general presentation of what the language does, what is special about the language, and the nuts and bolts of its rules and conventions. This is followed by a more in-depth look at the process of writing a model, writing expressions, and specifying simulation directives in a model. Various aspects of using a model are discussed next. This is then followed by a detailed presentation about using MODELS in ATP. It includes an explanation of the different declarations that can be included in the MODELS section. It also describes the different ways in which MODELS is interfaced with ATP, and how each approach can be used in the simulation of a circuit. The text concludes with a discussion and examples of building libraries of models and functions that can be assembled as a toolkit to be used in present and future simulation projects. Four sections are added as appendices to this manual. They are built for use as a quick reference to the MODELS language. The first is a summary reference to the syntax of the MODELS language. It condenses the contents of the Language Manual, presenting only the structure and the diagrams, without the text. Next comes a summary of that summary, providing a structured overview of only the keywords of the MODELS language, without the details of the full syntax rules. The other two appendices show the pre-defined constants and variables, and the pre-defined functions of MODELS, with discussions and examples.

MODELS is a general technical description language supported by a simulation solver. It is a programming language targeted to time-domain simulation, and is used as a tool for describing the dynamic behavior of complex physical systems. In ATP, it can be used for describing the operation of circuit components and of control components. It can also be used for generating signals or for analyzing measurements from the circuit. Finally, it can be used as the interface between ATP and outside programs.

1.1.1. MODELS in ATP The purpose of having MODELS available in ATP is four-fold: 1) to have a tool for developing models of circuit and control components which cannot be built easily with the set of existing components available in ATP and TACS; 2) to have the flexibility of a full programming language without having to interact with ATP at the programming level; 3) to be able to describe not only how a component operates, but also how the initial state (initial values and initial history) of the component is established, at any required detail level; 4) to have a standard program interface to ATP defined at the modeling level in terms of voltages, currents, and control signals, as opposed to an interface which would be defined at the programming level in terms of the variables, common blocks, and subroutines of ATP; this makes it possible to connect external programs to ATP for modeling of components, access to measurements, or interaction with equipment, without requiring a programming knowledge of the internal operation of ATP, and without requiring any modification to be made to the source code of ATP.

1.1.2. Starting to use MODELS Looking at the MODELS language for the first time can feel like a large task. With some guidance at the beginning, it can be easily divided into simple parts. Starting with examples provides an easy exposure to the main aspects of the language as well as, later on, to the finer details of its syntax. Many examples are provided with this guide, and can be used as a base from which modifications can be made to describe more complex operations.

1.1.3. Overall form The structure of the language is simple, and is similar to the structure of other programming languages, for example, Pascal or Modula-2. It has a small number of keywords that can be remembered easily. There are no formatting rules to complicate its use, and every construct is introduced by a descriptive keyword. The basic module is called a model. A model consists of procedures describing how the model operates, value-holding elements to carry the state and the history of its operation and to exchange information with the outside, and directives influencing the operation of the model in a simulation. Value-holding elements can be constant or variable, and can be assigned values from inside the model (types CONST and VAR) or from outside the model where the model is used (types DATA and INPUT). Two standard procedures can be defined for each model. The initialization procedure (INIT) describes the initial point of operation of the model before the simulation is started. The execution procedure (EXEC) describes how the operation of the model is updated at each successive instant of the simulation. Additional procedures can be defined for describing other actions of the model and to access the value of specific variables of the model. The simulation directives include control of the size of the time step used in the model, choice of interpolation method for determining input values at internal substeps, assignment of history expressions describing the pre-simulation values of some of the variables of the model, and allocation of special storage required for the past values of variables referenced in the model using a delay() function. A model is defined independently from the directives and location of where it will be used. Multiple instances of the same model can be used, each maintaining its individual operating point and history.

1.1.4. Similar to a programming language Users who apply the language to develop models of components and to possibly build library of components need sufficient power and flexibility from the description language. Users who more occasionally apply the language to represent a component or a numerical process, for example, need the language to be simple, so that it may be used and read with familiarity. Using a programming language approach seemed to fill both types of needs. In this regard, MODELS includes the following capabilities: - a regular syntax for the use of variables, arrays, expressions, and functions; - the use of various types of variables, holding values modified by the procedures of the model; variables can be numerical and logical, in either scalar or array form;

4 - a set of pre-defined numerical and logical functions; additional functions can be defined by the user, in the form of parametrized expressions, point lists, and externally-programmed functions; - the use of conditions and loops (if, while, for, etc.) for structuring the execution flow of a procedure; - the use of comments within a description, as an aid to producing models and procedures that are self-documenting; - the use of arbitrarily-long names to facilitate self-documentation; - an individual naming scope for each model, to allow the user to assign meaningful names to the variables used in a description, without the risk of conflicting with names chosen in other parts of the simulation; - separation of the description of a model, from its use in a simulation; - the use of multiple instances of the same component, each possibly supplied with different parameters, different inputs, or different simulation directives; - a mechanism for dividing a large component description into smaller units, for reduced model complexity, explicit identification of interfaces and operation, easier testing, and use of prototyping during model development; - the possibility to specify operations that are executed only when some conditions are met, for example for initialization, or when simulation difficulties or errors are detected.

1.1.5. What's particular to MODELS Two aspects differentiate MODELS from a regular programming language. One aspect is the set of operations and functions needed for the representation of systems that vary in time: - time automatically increases during a simulation; - individual instances of the models of a system automatically update their operation according to the increasing value of the simulation time; - the values of the variables are persistent over successive instants of time, and maintain their value during the simulation until assigned a different value; - expressions can be described as generic functions of the time "t", allowing a clear symbolic representation; an example would be referring to the time value of an oscillating signal by simply using A*sin(omega*t), with A and omega being defined elsewhere in the model; this expression automatically takes on the appropriate value at different times of the simulation; - a number of pre-defined time-based functions are available, including time integrals, time derivatives, time differential equations, Laplace and z transfer functions, and references to past and predicted values of a variable.

5 The other aspect is that MODELS automatically manages the storage and retrieval of the history values of the variables of a model, as needed during the execution of the simulation. The time-based functions of the language all have direct access to the past values of a variable, as needed for the calculations, without imposing on the user the task of specifying how that information is stored and accessed.

1.1.6. What about TACS? TACS had been designed to represent mostly-linear control systems described in the form of a block diagram. TACS allows the user to assemble a description of a control system using a set of pre-defined function blocks and devices. However, it was not designed to accommodate operations represented by algorithms, although we can achieve some measure of conditional assignments by using type-60 and type-61 devices. TACS doesn't provide a mechanism to solve sets of nonlinear simultaneous equations. Any feedback loop involving a nonlinear device is automatically cut open so it can fit in the linear matrix solution of TACS, effectively inserting delays of one timestep on the outputs of such nonlinear devices. Depending on the size of the time step and on the nature of the simulated system, the consequences of this approach can range from satisfactory to numerically unstable. The interface between TACS and the simulated circuit is a unidirectional information-type interface, passing measured values from the circuit to TACS, and control variables from TACS to the circuit. No iteration mechanism is provided. At each time step, the circuit is first solved completely, measured values are passed to TACS, then TACS is solved and its outputs applied to the circuit at the next time step of the simulation. Again, depending on the size of the time step and on the nature of the simulated system, this arrangement ranges from satisfactory to numerically unstable. When TACS is used for representing control system components, this delay provides satisfactory results, as control devices always involve an element of delay in their operation in the real systems. Similarly, it is possible to control the value of an impedance in the circuit without adverse effects due to the delay (for example, representing an arc by controlling the value of a resistance). However, using a control signals to inject currents or voltages intended to represent the true power connection of a circuit component is typically not a stable proposition, unless the injected currents or voltages are strictly history values calculated from a past state of the simulation, as in the case of using a Norton equivalent to represent an inductance using bilinear transformation. Finally, in contrast with TACS, the user is not limited to a pre-defined set of components, but can build libraries of components and submodels as required by different applications.

1.1.7. Reasons for using MODELS in a project Here are some of the reasons why it may be beneficial to use MODELS in a project: - when we need to do incremental development of the various parts of the simulated system, prototyping individual elements as we go; - when we need to include multiple or detailed aspect of the operation of some of the elements of the system, for example representing the thermodynamic behavior in conjunction with the electrical behavior; - when we want to include the representation of elements of the system that are already developed and available as separate subroutines written in a different program; an example might be using a model supplied by the manufacturer of a particular element; - when we have to develop from scratch the modeling of some of the components of the system, in the case that they could not be easily represented by using what's already available in ATP; we can do some of this in TACS, but MODELS provides a full algorithmic description language that can simplify the work; - when we need a component to be solved simultaneously with the rest of the circuit, avoiding the one-step delay otherwise imposed by TACS.

1.2.1. Kinds of value-holding elements If we sort the types of value-holding elements according to the value held by each named element, we have: - for values global to a simulation (i.e. to all model instances of all models): - global variables: t, starttime, stoptime, startstep - global numerical constants: pi, inf, undefined - global logical constants: false, no, open, off true, yes, closed, on - for values global to all instances of one model: - constants - for values local to each instance of a model: - data, inputs, variables, resident variables If we look at the value-holding elements in terms of where we specify the expressions used for calculating their value, we can note the difference between model definition and model use:

7 - in expressions global to all instances of a model, specified in the model definition: value expression of constants default expression of data default expression of inputs all value assignment expressions of variables

- in expressions local to each instance of a model, specified in the USE statement: - use expression of data - use expression of inputs If we look at the value-holding elements in terms of where they are visible, we can see the difference between names that are private to a model, and names that are visible outside the model where they are declared: Type constant data variable input output Access private public private public public Where value is specified model definition default value in model definition local value in use instance model definition default value in model definition local value in use instance local value in use instance

The naming of the types is not perfect, in the sense that data are as constant as the constants, and inputs are certainly as variable as the variables. They are identified by separate type names to underline their difference of being public or private with respect to the model where they are defined.

1.2.2. Scalars and arrays Value-holding elements in a model can be declared as individually-named scalar elements:

DATA d1, d2, d3 VAR y10, y11, y12

DATA d[1..3] VAR y[10..12]

8

DATA d[1..3]

DATA d[1] d[2] d[2] -- some descriptive comment -- ... -- ...

y[10] := d[1] + k[5] y[11] := d[2] + k[6] y[12] := d[3] + k[7]

y[10..12] := d[1..3] + k[5..7]

1.2.3. Use of arrays Array elements can be grouped by range inside numerical and logical equations:

vbr[1..3] := vk[1..3] -vm[1..3] gate[1..6] := fire[1..6] AND flag>0

wabs[1..6] := abs(w[1..6])

In the few circumstances where a group of array elements cannot be used as a range, for example on the left side of a Laplace assignment, it is still possible to use an indexed array notation inside a FOR structure, as in the following:

FOR i=1 TO 3 DO laplace(y[i]/x[i]) := (s_polynomial)/(s_polynomial) ENDFOR

The use of an array notation can simplify the description of a model, and also contributes to reducing the execution time of the simulation.

1.2.4. Representation of numbers All quantities inside a MODELS simulation are represented as double-precision floating point numbers. Some observations follow: - the value of a Boolean operation or conversion is 0.0 or 1.0 in doubleprecision (note that in MODELS, numerical operators can be applied to Boolean values and vice versa);

9 - when used as index to an array, the result of an expression is internally rounded to the nearest integer; - both rounding and truncation can be forced inside an expression using the functions round() and trunc(); - all operations involving some kind of value comparison automatically include a round-off multiplier of 10-8, which means that the granularity of any point value is 10-8 times its value, to the left and to the right, anywhere on the number line. Examples, where margin = b times 10-8 : a>b a=b a >= 0 is calculated as is calculated as is calculated as a > b+margin a >= b-margin AND a <= b+margin a >= 0 (because margin=0)

1.2.5. Limits Values are specified in expressions. In addition, each expression can be qualified by a minimum value and a maximum value. These limits are themselves described using an expression which may vary in value during a simulation. Limits are discussed in more detail below, in the sections on COMBINE, differential equations and transfer functions, integrals, and expressions.

a := 3*b -c {min: amin, max: amax} y := integral(x) {dmax: 3*a} laplace(y/x) := (s_numerator)/(s_denominator) {dmin: ymin*cos(omega*t)}

1.3.1. Model, MODELS, and MODEL When referring to the MODELS language, we use all upper case characters for the word. When referring to a model description written in the MODELS language, we use the word model written in regular lower case. The upper case singular form MODEL is the keyword that starts a model description.

1.3.2. Equal sign and assignment sign A distinction is made in the MODELS language between value assignment and value equality. Value assignment is identified by the assignment operator ":=". Value assignment is an action. When a value is assigned to a named value-holding element, the assignment operation is expressed using ":=", for example:

USERS GUIDE TO MODELS IN ATP

10

w[2] := expression

or

laplace(y/x) := (s_numerator)/(s_denominator)

Value equality is identified by the equality operator "=". Value equality is a condition that can be true or false. It is used as a logical relation in a logical expression, for example:

IF a = b THEN ... ENDIF

1.3.3. Parentheses, brackets, and braces The left and right parenthesis characters "(" and ")" are used to enclose the arguments of a function. In this case, the left parenthesis must immediately follow the function name, without any space. For example:

y := delay(x1, delay_value) integral(w) := expression laplace(x1/x2) := (1|s0) / (1|s0 + tau|s1) histdef(integral(y2)) := 2*histdef(y1)

The parentheses can also be used by themselves inside an expression to designate a sub-expression:

y := a -(2*b -c)

The left and right square bracket characters "[" and "]" are used to identify an element or a range of elements of an array. In this case, the left bracket must immediately follow the function name, without any space. They can be used with an array name to identify elements of that array:

wabs[1..n] := abs(w[1..n])

The brackets can also be used by themselves inside an expression to indicate a grouping of values into an array value:

vpp[1..3] := [va-vb, vb-vc, vc-va]

The left and right brace characters "{" and "}" are used to identify some attribute, like default value, limit value, type, argument count, etc. For example:

INPUT va { v(NODEA) } CONST twopi { val: 2*pi } DATA freq { dflt: 50 } FUNCTION windspeed FOREIGN { ixarg: 2 }

11

1.3.4. Blank lines MODELS has its own syntax rules, separate from ATP. Among other things, it allows the insertion of white space anywhere in the MODELS section, including blank lines and tabs. So, for example, there is no need to start blank lines in the MODELS section with "C ", necessary for indicating comment lines in the rest of ATP.

1.3.5. Names Names can be composed using any combination of letters, digits, and the underscore character "_", with the restriction that a name must start with a letter. Names are not case-sensitive. Upper and lower case can be used for readability, but not for distinguishing two names of the same spelling. Keywords of the language are typically written in capitals for readability, but this is not necessary for interpretation by the parser. Hyphens are not permitted inside a name, and will be interpreted as a minus sign.

1.3.6. Delimiters From a parsing point-of-view, all constructs of the language are self-delimiting. This means that some kind of end delimiter indicates where a construct ends, whether implicitly or explicitly. An implicit delimiter is what is used for indicating the end of a name, keyword, operator, or value. For example, names terminate at the first character that is not a recognized name character, and values terminate at the first character that is not a legal value character. Explicit end delimiters are keywords that indicate the end of a construct, for example, ENDMODEL or ENDIF.

1.3.7. Comments Two aspects contribute to making a model understandable. The first is to choose names that are appropriately descriptive of the value or function they are representing. The other is the liberal use of in-line comments and block comments. An in-line comment starts with a string of two or more hyphens, and automatically terminates at the end of the line. A block comment is a block of text starting with the keyword COMMENT and ending with the keyword ENDCOMMENT. This can be used to annotate a model, or to temporarily block out a part during model development or testing.

12

MODEL m1 comment --------------------------------------------------| This is a block comment describing this model | | (the vertical bars and the hyphens are only decorative) | ------------------------------------------------ endcomment VAR a -- this is an in-line comment describing this variable

1.3.8. Line indentation Line indentation in the form of tab or space characters can be used to increase the readability of a model description. There are no pre-defined formatting rules imposed by the language. Indentation rules are therefore a matter of arbitrary style. However, the use of tabs is often counter-productive if a model description is to be viewed on different text editors treating tabs in different ways.

13

2. WRITING A MODEL

This section introduces the elements used when building a model description of something. The dynamic operation of a model is represented by the named elements that hold the values used in and created by the model (constants, data, inputs, variables, and outputs), and by a description of how these values are calculated and used. Procedures contain the statements where these values are used and assigned. Various types of statements are available for representing how a value is calculated and assigned. Submodels and functions can also be defined to carry out some of the calculation of these values. The use of each model and submodel can be customized for each use instance, by means of simulation directives specified in the model definition and in the USE statements introducing each instance.

Each model can contain any number of value-holding elements, identified by type, name, and, if an array, range of array indices. The type, name, and range of these elements must first be declared in a model before they can be used. These declarations are grouped in a model by type: constant, data, input, output, variables. In summary, the names of data and inputs are public (although they can be assigned private default expression). The names of constants and variables are private (can't be referenced in the USE statement). The value of a constant or data is constant in time. The value of a variable or input can vary in time.

2.1.1. Defining constant elements Constants are used for holding values that are defined inside the model, and that do not vary during the simulation. The names of the CONST elements are only visible inside the model where they are declared. Their value is assigned inside the model, in the declaration. The same value is used in all use instances of the model.

CONST twopi {val: 2*pi} CONST power_of_2[0..8] {val: [1,2,4,8,16,32,64,128,256]}

There is a set of constants that have pre-defined names and values. They can be used without needing to be declared:

14 - pre-defined numerical constants: - pi - inf - undefined - false, no, open, off true, yes, closed, on 3.14159... a large value, typically 1020 the special value 88888.88888 the value 0 the value 1

2.1.2. Defining data elements Data are used for holding values that are defined outside the model, and that do not vary during the simulation. The names of the DATA elements are visible inside the model where they are declared, and also in the USE statements defining instances of the model. Their value is assigned in the USE statements. A default value can also be optionally assigned inside the model, in the declaration. When a default value exists for a data element, assigning that element a value in the USE statement is optional. Different values can be used in different use instances of the model.

DATA n DATA freq {dflt: 50} -- an array dimension used in the model -- providing a default value

Data elements are typically used for parameters and dimensions that can be assigned a different value in different use instances of the model. Once assigned, DATA values do not vary in time. Their value is constant over the full length of a simulation. Data values are automatically calculated in the USE statement the first time the use instance is called. 2.1.2.1. Using a data value as an array dimension A data value can be used in the expressions defining the range of indices of an array. This can be useful for dimensioning an array to just the size needed in an application.

DATA n INPUT vterm[1..n] VAR vtmax[1..n] -- a dimension assigned differently in each use instance -- a variably-dimensioned input -- a variably-dimensioned variable

2.1.2.2. Dependent data values If we declare what should be a dependent data value (one that depends on the value of another data) as DATA in order to assign it a default value, we risk that it be reassigned an erroneous value in a USE statement. For example:

DATA n DATA n2 {dflt: n*n} -- an array dimension -- another array dimension

15 This is because it's inadvertently making public a name that is really private to the model. For array dimensions, this is unavoidable, and at best could be checked for consistency in the INIT procedure of the model.

DATA n -- an array dimension DATA n2 {dflt: n*n} -- another array dimension ... INIT IF n2<>n*n THEN ERROR write('Some error message...') STOP ENDIF ...

When the data is not needed as the dimension of an array, it's better practice to hide it to the outside by declaring it as a variable, and then assign its value in the INIT procedure in function of the data value it depends on. For example, instead of doing:

DATA freq {dflt: 50} DATA omega {dflt: 2*pi*freq} -- a frequency in Hz -- the equivalent frequency in rad/sec

DATA freq {dflt: 50} VAR omega ... INIT omega := 2*pi*freq ... -- a frequency in Hz -- the equivalent frequency in rad/sec

2.1.3. Defining input elements Inputs are used for holding values that are defined outside the model, and that vary during the simulation. The names of the INPUT elements are visible inside the model where they are declared, and also in the USE statements defining instances of the model. Their value is assigned in the USE statements. A default value can also be optionally assigned inside the model, in the declaration. When a default value exists for an input element, assigning that element a value in the USE statement is optional. Input values are automatically re-calculated in the USE statement each time the use instance is called.

INPUT vterm[1..3] vref {dflt: 0} -- value of measured terminal voltages -- value of a reference voltage, =0 if not used

Arrays of inputs can be variably dimensioned. The above example of a 3-terminal model can be replaced with a model designed for n terminals, with the value of n determined at simulation time as a data in the USE statement:

DATA n INPUT vterm[1..n] vref {dflt: 0} -- number of terminals -- value of measured terminal voltages -- value of a reference voltage, =0 if not used

16

2.1.4. Defining variable elements Variables are used for holding values that are defined inside the model, and that vary during the simulation. The names of the VAR elements are only visible inside the model where they are declared, except when they are declared as OUTPUT (see section below). Their value can be assigned in any statement inside the model. Once assigned a value, a variable maintains that value during the simulation, until it is assigned a new value. To continue the previous example, one could track the input voltages for maximum amplitude for each terminal, let's say, and the maximum for all terminals. Let's define the variables vtmax[ ] and vmax:

DATA n INPUT vterm[1..n] vref {dflt: 0} VAR vtmax[1..n] vmax -----number of terminals value of measured terminal voltages value of a reference voltage, =0 if not used tracked maximum absolute value of each terminal voltage tracked maximum absolute value of all terminal voltages

To update the value of these variables during the simulation, statements describing how to do that can be included in the EXEC procedure of the model, with initialization in the INIT procedure, for example:

INIT ... vtmax[1..n]:=0 -- initialize tracked maximum values vmax:=0 -- initialize overall tracked maximum value ... ENDINIT EXEC ... FOR i:=1 TO n DO -- for each terminal vtmax[i]:= max(vtmax[i], abs(vterm[i])) -- update tracked maximum ENDFOR vmax:= max(vmax, vtmax[1..n]) -- update overall tracked maximum ... ENDEXEC

Various other ways of assigning values to variables are described in more detail in this manual, in the section on "Writing the statements of a procedure".

2.1.5. Defining output elements Variables can be declared as OUTPUT of a model. The names of variables declared as output are made visible to the USE statements defining instances of the model. No other variable is visible outside the model. Continuing the above example, the values of vtmax[ ] and vmax can be specified as output of the model, as shown here:

17

DATA n -INPUT vterm[1..n] -vref {dflt: 0} -VAR vtmax[1..n] -vmax -OUTPUT vtmax[1..n], vmax number of terminals value of measured terminal voltages value of a reference voltage, =0 if not used tracked maximum absolute value of each terminal voltage tracked maximum absolute value of all terminal voltages -- can be used as outputs of the model

As mentioned before, the dynamic operation of a model is represented by the named elements that hold the values used in and created by the model, and by a description of how these values are calculated and used. This representation can be decomposed into a hierarchy of models, each holding the description of a specific aspect of what is being modeled. How do we select to represent something as a model rather than defining it as a procedure or a function? A function has the characteristic of an expression. For a given set of arguments, it calculates and returns a set of values, without maintaining any trace of previous calls to the function, without holding any state to be used by future calls to the function, and without modifying the state of the model in which it is defined. A procedure expresses how something is done, modifying and making reference to values held in the model. A model has both value holders, to represent the state of operation of what is modeled, and procedures, to act on that state. A model maintains its own memory storage of values for each instance in which it's used. Functions don't need that kind of storage, as there is nothing to store between calls. Procedures use the existing storage of the model where they are defined. When used as a submodel inside another model, a model can be written in the MODELS language, with its description inserted locally in the declarations of the calling model. This is the locally-defined submodel. A model can also be a separate program, written in any language, and accessed through the programming interface of MODELS. This is a foreign submodel. A local or foreign model can possibly be described outside the calling model where it is used. This is declared in the calling model as an external submodel.

2.2.1. Locally-defined submodels This is the standard way of introducing a submodel. A submodel is a full model of its own, except for the fact that it is declared and used inside another model. Once it is declared, it can be used in that model in as many use instances as required, each one maintaining its own separate state of operation.

18

MODEL component -- defining a model CONST ... DATA ... INPUT ... VAR ... OUTPUT ... MODEL controller -- defining a local submodel CONST ... DATA ... ... ENDMODEL ... EXEC ... USE controller AS control_1 -- using the submodel ... ENDUSE ... ENDEXEC ENDMODEL

An alternate way, that is still a locally-defined submodel, is to replace the actual description of the submodel by a reference to the file containing that description. The above example could be rewritten as:

MODEL component -- defining a model CONST ... DATA ... ... $INCLUDE filename { inserting a local submodel (notice the ATP formatting) ... EXEC ... USE controller AS control_1 -- using the submodel ... ENDUSE ... ENDEXEC ENDMODEL

The $INCLUDE directive is an ATP command used for accessing the contents of other files. It's a formatted command, and must start in column 1 of a new line.

2.2.2. Foreign submodels MODELS has a simple interface for accessing other programs that can be used as submodels or functions inside a model. A program accessed as a model has to meet the following requirements: - its call arguments are pointers to four arrays - it has two separate entry points, one for initialization, and one for execution The four arrays hold values of data, inputs, outputs, and stored variables. The data, inputs, and outputs correspond to the regular data, inputs, and outputs of a model. The array of stored variables is a service of MODELS, to hold internal values of the program between calls, allowing the called program to be used for more than one use instance without requiring the called program to manage separate storage for individual instances.

USERS GUIDE TO MODELS IN ATP

19 The two entry points correspond to the INIT and EXEC procedures of a model. The initialization routine is called only when an instance of the model is used for the first time. The execution routine is called when the state of the model is to be updated according to new conditions. The declaration of the foreign model indicates the local name identifying that submodel in the calling model, the foreign name of the model, and the length of each of the four arrays.

MODEL component -- defining a model CONST ... DATA ... ... MODEL controller FOREIGN control_program {ixdata:3, ixin:2*n+4, ixout:n, ixvar:5} ... EXEC ... USE controller AS control_1 -- using the submodel ... ENDUSE ... ENDEXEC ENDMODEL

In the above example, the local name is "controller", and the foreign name is "control_program". That foreign name is not necessarily the name of the foreign program itself. It is a unique identifier used in the subroutine "fgnmod" of MODELS, to recognize which foreign model is being called. It is inside that subroutine that the actual call to the foreign program is made. That subroutine needs to be edited when installing calls to new foreign programs. That subroutine is fully documented with comments, and should present no difficulty when used. Part of that subroutine is shown below, showing how the identifier "controller" of the previous example would be used:

20

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(*) ... In the following lines, register the foreign model names as declared in the models: DATA refnam(1) / 'SAMPLE_MODEL' / ! Example "ftnmodel.dat" DATA refnam(2) / 'SAMPLE_C_MODEL' / ! Example "cmodel.dat" DATA refnam(3) / 'CONTROLLER' / ! Added for this example DATA refnam(4) / ' ' / ... The following lines call the actual foreign subroutines/procedures: - actual names may be different from the foreign names used in the models - notice how each one uses both an initialization routine and an execution routine IF ( iname.EQ.1 ) THEN ! "sample_model" 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 ! "sample_c_model" 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 ! "controller" IF (iniflg.EQ.1) THEN CALL contri(xdata, xin, xout, xvar) ELSE CALL contrm(xdata, xin, xout, xvar) ENDIF CONTINUE ! ------------------------------------------ELSE IF ( iname.EQ.4 ) THEN ...

C C

C C C C C

It is when actually using the foreign model that the contents of the data, input, and output arrays is identified. Just like when using a local model, it is possible to specify how data, input, and history values are calculated. One difference is that the value of the local simulation time must be explicitly passed to the foreign program as one of the inputs. It's not done "magically" in the background. Outputs of the foreign model are used just like those of a local model. The contents of the array of variables is specified and managed inside the called program, not in the USE statement. However, it is possible to assign initial values to these variables using HISTORY directives, just like in a regular USE statement. Note that only initial values are passed to the foreign program, not full history expressions available only for regular models. The following example illustrates the definition and the use of a simple foreign model. Note that the four arrays have the pre-defined names "xdata", "xin", "xout", and "xvar":

21

DATA n VAR a[1..n] ... MODEL ftnmodel FOREIGN sample_model {ixdata:1, ixin:n, ixout:n, ixvar:n} ... EXEC ... USE ftnmodel AS ftnmodel DATA xdata[1]:=n -- set value of xdata[1] INPUT xin[1..n]:= ... -- load inputs xin[1..n] HISTORY xvar[1..n]:=0 -- set history of xvar[1..n] OUTPUT a[1..n]:=xout[1..n] -- use outputs xout[1..n] ENDUSE ...

The foreign program, in this case, is a Fortran subroutine that writes some text and updates the values of the outputs, without using the value of time (which is thus not passed as an input):

SUBROUTINE samplm(xdata, xin, xout, xvar) DIMENSION xdata(*), xin(*), xout(*), xvar(*) CHARACTER*80 text80 ! Buffer used to assemble messages for output text80 = 'Executing model "sample_model".' 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

In the example, "xdata[1]" holds the dimension of the other three arrays, "xin" holds input values received from the calling model, "xout" holds output values sent back to the calling model, "xvar" holds state values stored in memory by MODELS between calls. Note how xvar is referenced before a new value is assigned to it, requiring a reference to the initial value of xvar at the first execution of the subroutine.

2.2.3. External submodels If a submodel is used in a model, but defined somewhere else, it can be introduced in the calling model as "external". It needs to be declared in the calling model, but the declaration can be as simple as mentioning the model's name and saying it's external, like this:

22

MODEL component -- defining a model CONST ... DATA ... ... MODEL controller EXTERNAL ... EXEC ... USE controller AS control_1 -- using the submodel ... ENDUSE ... ENDEXEC ENDMODEL

The full definition of the external model can be placed anywhere at the same level of the calling model or above. For the previous example, it could be found either at the same level of the "component" model as a locally-defined model:

MODEL component -- defining a model ... MODEL controller EXTERNAL ... ENDMODEL MODEL controller CONST ... DATA ... ... ENDMODEL

MODEL component -- defining a model ... MODEL controller EXTERNAL ... ENDMODEL MODEL controller FOREIGN control_program {ixdata:3, ixin:2*n+4, ixout:n, ixvar:5} ...

or at a higher level:

MODEL system MODEL sub_system_1 MODEL component -- defining a model ... MODEL controller EXTERNAL ... ENDMODEL ... ENDMODEL MODEL sub_system_2 ... ENDMODEL MODEL controller ... ... ENDMODEL

23

MODEL component -- defining a model ... MODEL controller EXTERNAL ... ENDMODEL $INCLUDE filename { a file holding a library of models ...

A function operates like an expression. When it is called, it uses the existing values of all the named references used in the function, to calculate and return a result to the expression from where it was called. A function has access to the value of its arguments and to the values of all valueholding elements of a model. However, as compared to a procedure, a function cannot modify any value other than the result it is returning. As compared to a model, a function does not have internal variables that can retain values between calls, that is, a function doesn't carry a state. A function can return a single value, or a list of values in the form of an array. Array-returning functions can be used inside expressions that use array arithmetic. In addition to the pre-defined functions supplied by MODELS, three types of custom functions can be defined in a model. Statements functions are simply reusable named expressions. Point list functions express a relation between input and output in terms of (x, y) coordinates. Foreign functions are functions that are defined in a separate program and accessed through the programming interface of MODELS.

2.3.1. Statement functions Statement functions are defined inside a model in the form:

FUNCTION somename(argname1, argname2, ... ) := expression

These functions are macro-expressions that can be used in other expressions of a model. The function's expression can be a single-value expression or an expression returning an array of values. That expression can contain references to the named arguments of the function, as well as to any value-holding element of the model. The function is used by indicating the name of the function, and by providing a list of values used by the arguments of the function:

somename(value1, value2, ... )

24 The form under which the list of values is provided is flexible, and can be a mixture of single values and of ranges of array elements, using expressions and array expressions, for example:

somename(expr, array_expr, ... )

An example of this would be a two-argument function used for calculating the amplitude of a complex number, given its real and imaginary part. The arguments can be supplied as a list of two separate values, like this:

FUNCTION c_ampl(real, imag) := sqrt(real*real +imag*imag) ... ym := c_ampl(xr, xi)

or can be supplied as an array of two values, with the array, in this case, being a representation of the real and imaginary part of a complex number:

VAR cx[1..2] -- a complex variable as real and imaginary FUNCTION c_ampl(real, imag) := sqrt(real*real +imag*imag) ... ym := c_ampl(cx[1..2])

2.3.2. Pointlist functions Pointlist functions are useful when data about a function is available in the form of a table. Pointlist functions are single-valued functions expressed as a list of coordinates in a 2-dimension plane, sorted in increasing value of the input coordinate. For example, a curve of resistance in function of temperature could be expressed as:

FUNCTION temp_dep POINTLIST (-273, 1.e-6), (-60, 1.e-4), (0, 1.e2), etc...

The first coordinate of each pair corresponds to the input value, and the second coordinate corresponds to the output value of the function. What gets interesting is that the values of the coordinates can be expressed using regular expressions making reference to other variables or functions of the model. Very complex functions can be assembled using this possiblilty. An interesting example is the description of a parametrized family of curves. A pointlist function specifies what curve the function will use for different values of a parameter "k". Each curve can in turn be described using an expression that contains a reference to another function of any type. The following example illustrates a simple 1-parameter family of curves.

25

VAR a, k FUNCTION FUNCTION FUNCTION FUNCTION

curve2(x) ... -- a statement function or a point list for k=2 curve4(x) ... -- a statement function or a point list for k=4 curve6(x) ... -- a statement function or a point list for k=6 f POINTLIST (2, curve1(a)) (4, curve2(a)) (6, curve3(a)) -- used inside the function f(k) -- any value between 2 and 6

In the above example, the family is reduced to a set of three representative curves. The pointlist function simply specifies which of these curves (themselves functions) will be used for the three representative parameter values 2, 4, and 6. Interpolation is provided automatically. When the interpolation order is not specified, as in y:=f(2.5) in the above example, the interpolation is linear, that is, the function calculates the values of f(a) for k=2 and for k=4, and interpolates linearly between the two values to return a value for k=2.5 . The interpolation order can be specified as a second argument when using the function, and can be either 0, 1, or 2, (none, linear, quadratic), as shown in the section on "Using a function". 2.3.2.1. External point list It is possible to use the $INCLUDE function of ATP for gaining access to a list of points stored in a separate file, possibly generated by another program. The formatting requirements are that each pair be enclosed in parentheses, with the enclosed coordinates separated by a comma. The pairs must be sorted in increasing value of the first coordinate, for example:

(0,0) (1,2) (2,4) (3,6) etc...

Using separate lines is not required, although a maximum line length of 80 characters is imposed by ATP. As everywhere else in a model, spacing characters are ignored.

(0,0) (1,2) (2,4) (3,6) etc...

Supposing that these coordinates are available in a file named "xy.lst", they could be included in a model as follows:

FUNCTION xyfun POINTLIST $INCLUDE xy.lst -- with data points located in the following file:

26

2.3.3. Foreign functions Foreign functions are functions written in any language and linked to ATP before execution. The function call is handled by the programming interface of MODELS. A foreign procedure accessed as a function must meet the following requirements: - it has one function argument that is a pointer to an array - it returns the number of output values placed by the function in the argument array The values returned by the function in the argument array must be placed at the beginning of that array. The declaration of the foreign function in a model indicates the local name identifying that function in the calling model, the foreign name of the function, and the length of the argument array.

MODEL component VAR speed[1..2] -- velocity [m/s] and direction [deg] ... FUNCTION windspeed FOREIGN wind_speed {ixarg: 2} ... EXEC ... speed[1..2] := windspeed(t) ... ENDEXEC ENDMODEL

In the above example, the local name is "windspeed", and the foreign name is "wind_speed". The dimension of the argument array is indicated as "2", because even if there is only one input argument when the function is used, the function returns two values that it places in that array. The indicated foreign name is not necessarily the name of the foreign procedure itself. It is a unique identifier used in the subroutine "fgnfun" of MODELS, to recognize which foreign function is being called. It is inside that subroutine that the actual call to the foreign procedure is made. That subroutine needs to be edited when installing calls to new foreign procedures. That subroutine is fully documented with comments, and should present no difficulty when used. Part of that subroutine is shown below, showing how the identifier "wind_speed" of the previous example would be used:

27

SUBROUTINE fgnfun ( name, namlen, xarg, nval, ierflg) IMPLICIT REAL*8 (A-H, O-Z), INTEGER*4 (I-N) DIMENSION xarg(*) ... In the following lines, register the foreign function names as declared in the models: DATA refnam(1) / 'SAMPLE_FUNCTION' / ! Example "ftnfun.dat" DATA refnam(2) / 'SAMPLE_C_FUNCTION' / ! Example "cfun.dat" DATA refnam(3) / 'WIND_SPEED' / ! Added for this example DATA refnam(4) / ' ' / ... The following lines call the actual foreign procedures: - actual names may be different from the foreign 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 nval= wind(xarg) ...

C C

C C C

It is when actually using the foreign function that the values of the input arguments are identified. Just as when using a local function, it is possible to specify how the function arguments are calculated. If the operation of the function varies in function of time, the value of time must be explicitly passed to the function as one of its input arguments. In the example of the wind speed function shown above, the only input argument used by the function is the value of the simulation time "t". The function returns two values, the wind velocity and direction, placed in the argument array of the function. Internally, MODELS uses the value returned by the function, which in this case will be "2", to find out how many values the function has placed in the argument array. The following example illustrates the definition and the use of another simple foreign function:

VAR y[1..2], k FUNCTION f1 FOREIGN sample_function {ixarg:2} ... EXEC ... y[1..2]:=f1(k+t, -k) -- each argument can be an arbitrary expression ...

The foreign procedure, in this case, is a Fortran function that uses two input values, and returns two output values placed in the argument array:

FUNCTION samplf(arg) DIMENSION arg(2) arg(1)=arg(1) +arg(2) arg(2)=arg(1)*10 samplf=2 RETURN END

28

int CFUN(double arg[]) { arg[0] = arg[0] + arg[1]; arg[1] = 10 * arg[0]; return 2; }

The procedures describe the methods used by the model for accessing and modifying the values of the value-holding elements of the model during the simulation. Two procedures have pre-defined names: EXEC and INIT. The EXEC procedure is the procedure that is called when it is time to update an instance of the model to a new simulation time. It is called automatically each time a USE statement is executed. It describes how the model operates as time increases. The INIT procedure describes how to initialize the values of the variables before the simulation begins. It is called automatically when a USE statement introduces a new instance of a model. Additional named procedures can be defined, identified by arbitrary names and performing arbitrary operations on the variables of the model.

2.4.1. The EXEC procedure The EXEC procedure is the main operating procedure of the model. It is called each time a USE statement calling that model is executed. The EXEC procedure describes how the state of a model, as expressed by the value of its variables, evolves over the time of the simulation. This evolution is described by means of an arbitrary arrangement of assignment statements (value assignment, integral assignment, Laplace and z transfer functions, differential equations, and combined simultaneous equations), algorithm control statements (for conditions and repetitions using IF, WHILE, FOR, ERROR), calls to other models (USE), and procedure calls.

2.4.2. The INIT procedure The first time that a model instance is called during a simulation, the INIT procedure of the model is executed, followed by the EXEC procedure. At subsequent time steps, only the EXEC procedure is executed. The EXEC procedure can be prevented to execute at the initial use by placing its contents inside an IF statement, but see the following discussion on the subject of executing both INIT and EXEC. The initial call to a model instance can be at a time different than time zero if, for example, the corresponding USE statement is written inside an IF statement in the EXEC procedure of the calling model.

29 2.4.2.1. Executing both INIT and EXEC at time zero Here is the reasoning at the base of the approach of having both the INIT and EXEC procedures execute at the initial time t0. If only the INIT procedure ran at t0, then it would have to contain value assignments for all the variables in the model, which means that much of the INIT procedure would duplicate what's in the EXEC procedure. Similarly, we would need to somehow call all the submodels used in the EXEC procedure, so that they be initialized too, again a duplication of the contents of the EXEC procedure. Let's turn the thing on its head and consider instead what would prevent us from having only the EXEC procedure run at t0 without an INIT procedure. The problem would be that any past value that needs to be referenced in the model during the first execution would be undefined. This can happen either explicitly, as in

a_increase := a - a_old

where "a_old" has of course not been defined yet. It can also happen in implicit references to past values, as in:

slope_v := deriv(v)

where the function deriv() needs to access, behind the scene, the value of v at the previous time step, which of course has not yet been stored in the model's running history, and is therefore undefined. By having both the INIT and EXEC procedures executing at the initial time, we minimize the size of INIT, and avoid code duplication which would easily create maintenance problems in the development life of the model. All we need to do in the INIT procedure is define any past values which will be referenced in the EXEC procedure before the model has had the opportunity to store these past values itself in its running history. 2.4.2.2. INIT procedure and HISTORY assignment Rather than forcing one to define all initial values and history expressions in the INIT procedure of a model, a more flexible three-level mechanism is available in MODELS. This mechanism owes its existence to the need of being able to assign history and initial values differently for different uses of the same model. If the definition of history and initial values had to be hard-coded in the INIT procedure of the model, then the contents of the model would have to be modified from one use to another, which runs counter to the approach of separating the definition from the use of the models. This is why MODELS has been built so that it be possible to assign HISTORY expressions in the USE statement calling a model -- this is level one.

30 In addition, default history expressions can be specified for any of a model's inputs and variables which require a history to be defined. The default history expression will be used only if no history is specified for that element in the USE statement. This is level two. Note that if an element is declared in a model as requiring a history, and that no default history is defined for it, then its history expression must be specified in the USE. What's left for the INIT procedure is assigning history and initial values which are private to the model, that is, which the user of the model doesn't need to know about (see the section on history expression assignment). This is level three. Of course, it's desirable to build the INIT procedure so that it takes care of as much of the history and initial value assignments as possible, leaving a minimum of concern to the user of the model. Notice that the expression defining the history of an element can make reference to the history expression of another element, which can be very useful in the INIT procedure.

2.4.3. Named procedures Although not yet available at the time this text is being written, it will soon be possible to define named procedures in a model. This is to provide the possibility of performing operations on a model other than what is done in the EXEC procedure. The implicit message guiding the operation of the EXEC procedure is "updating to a new simulation time". Using additional procedures, other operations can be executed, for example asking a model instance to reset a group of variables or to perform a write operation, or accessing the value of a specific variable of the model. This also makes it possible to connect to the operation of a model from more than one locations in the calling model, otherwise reserved to one USE statement for each instance. The final format for defining a procedure is not yet definitive, but would be in the line of this example:

MODEL proc_example DATA inival {dflt:0} INPUT x VAR y INIT -- this is executed when the instance is created or first USEd integral(x) := inival ENDINIT EXEC -- this is the default operation procedure, -- executed when the instance is used from a USE statement y := integral(x) -- assigns value of integral to y self.write_y -- calls the procedure 'write_y' ENDEXEC

31

PROC write_y write('In model proc_example, y=', y) ENDPROC PROC reset_integral(resetval) integral(x) := resetval ENDPROC PROC integral_value integral_value := integral(x) ENDPROC ENDMODEL -- uses one input argument -- resets the value of the integral

As shown in the above example, a procedure can have zero or more input arguments, and can return zero or more output values. A procedure can be called from inside the model where it is defined, using the instance identifier "self". As shown in the next example, a procedure can also be called from another model that uses an instance of the model where the procedure is defined:

MODEL test_proc MODEL proc_example EXTERNAL -- identifies a model description VAR k -- counter INIT k:=0 ENDINIT EXEC k:=k+1 USE proc_example AS example -- creates and updates an instance named -- "example" of the model "proc_example" DATA inival := -4 INPUT x := 2*t +3 ENDUSE IF k=4 THEN example.reset_integral(0) -- calls a proc of "example" ENDIF write('In test_proc at t=', t, ', integral value=', example.integral_value) -- calls another proc ENDEXEC ENDMODEL

In the above example, a procedure is called by identifying the name of the model instance to which it belongs, the name of the procedure, and the value of its input arguments, if any. The procedure "reset_integral" expects one input value, and returns no value. The procedure "integral_value" expects no input value, and returns one output value. A procedure can be used as a function inside an expression, returning one or more values to the expression. A procedure returning no values can be used as a statement inside another procedure. A procedure can be recursive.

Various types of statements can be used in a procedure for assigning values to the variables of the model, for controlling the algorithmic flow of a procedure, for defining and using instances of other models, and for calling the procedures of a model. They are:

USERS GUIDE TO MODELS IN ATP

32 - assigning values element := expression diffeq(d-polynomial)|y := x laplace(y/x) := (s-polynomial)/(s-polynomial) zfun(y/x) := (z-polynomial)/(z-polynomial) integral(element) := expression histdef(element) := expression - controlling the algorithm IF ... WHILE ... FOR ... DO ... REDO COMBINE ... ERROR ... - using and updating an instance of a model USE ... - using a procedure of a model instance.procname(argument values) write( ... )

2.5.1. Value assignment statement There are two types of equations available for assigning a value to a variable: explicit and implicit. The explicit value assignment has the simple form:

element := expression

The element can be a single variable y, a single element of an array variable y[expr], or a range of elements of an array variable y[expr..expr]. The types of expressions available are regular expression, sum expression, derivative polynomial expression, and integral (see the section about Expressions). A regular expression can be written to return either a single value or a list of values. Single elements, of course, can only be assigned a single value. But a range of elements can be assigned either a single value applied to all the elements of the range, or individual values taken from the list of values returned by the expression. Minimum and maximum limits can be placed on the value or values returned by the expression (see Expressions). It is also possible to assign a value explicitly to the integral of a variable, as discussed in the section on integral value assignment.

USERS GUIDE TO MODELS IN ATP

33 Finally, it is possible to associate a value expression to the history of an element (see History expression assignment). The available implicit forms of value assignment are differential equation, Laplace transfer function, and z transfer function, discussed below.

2.5.2. Differential equation, Laplace and z transfer functions These three types of assignments can each describe how the value of a variable changes with respect to the value of another variable over time. They are discussed together because their representation and their solution are similar, and are based on the same approach. The built-in form of the differential equation is a first-degree (the exponent applied to the derivatives) nth-order (the highest order of the derivative) ordinary differential equation (of one variable), as follows: or, using the operator D to replace d/dt :

(a0 D0 + a1D1 + a2D 2 +...) y = x

expressed using the keyword DIFFEQ, and the vertical bar as an operator meaning "applies to":

DIFFEQ(polynomial)|y := x

where the polynomial in D is expressed as follows, with the value of each coefficient described by an expression:

expr|D0 expr|D1 expr|D2 ...

The Laplace-transform transfer function describes the variation of a variable y with respect to a variable x, expressed as a ratio of two linear polynomials in s:

Y (s) b0 + b1s + b2 s2 +... = X (s) a0 + a1s + a2 s2 +...

This is expressed using the following notation, again using the vertical bar as the operator "applies to":

LAPLACE(y/x) := (numerator)/(denominator)

(expr|s0 expr|s1 expr|s2 ... )

The z-transform transfer function describes the variation of a variable y with respect to a variable x, expressed as a ratio of two linear polynomials in z-1:

Y (z) b0 + b1z 1 + b2 z 2 +... = X (z) a0 + a1z 1 + a2 z 2 +...

34 This is expressed using the following notation, again using the vertical bar as the operator "applies to":

ZFUN(y/x) := (numerator)/(denominator)

(expr|z0 expr|z-1 expr|z-2 ... )

In each of the above types of representations, the polynomials are linear in D, s, or z-1. However the coefficients of the polynomials can be arbitrary time-variant nonlinear expressions. When the coefficients are known to be constant, the use of the keyword CDIFFEQ, CLAPLACE, and CZFUN will reduce execution time by avoiding the recalculation of the coefficients at each time step. The elements y and x are single-value elements, whether single variables or single elements of a variable array, and cannot be a range of multiple array elements. 2.5.2.1. Numerical solution Using the differential equation is equivalent to using the Laplace transfer function with N(s)=1, as the variable s translates to the time derivative d/dt when converted from the frequency domain to the time domain. As seen below,

(a0 D0 + a1D1 + a2D 2 +...) y = x

is equivalent to

Y (s) 1 = X (s) a0 + a1s + a2 s2 +...

Conversely, the Laplace representation can be solved in the time-domain by converting the numerator and the denominator to polynomials of derivatives of the variables y and x, where

Y (s) b0 + b1s + b2 s2 +... = X (s) a0 + a1s + a2 s2 +...

becomes

(a0 + a1D + a2D 2 +...) y (t ) = (b0 + b1D + b2D 2 +...) x(t )

where D is the operator d/dt. To avoid having to calculate derivatives, we can integrate symbolically this equation with respect to time on both sides, as many times as required to eliminate all derivatives, each time using the bilinear transformation. This process produces an equation expressed in terms of the present and past values of y and x: y(t0) = f( x(t0), x(t1), x(t2), ..., y(t1), y(t2), ... ) where

35 x(t0) = x(t), x(t1) = x(t-t), x(t2) = x(t-2t), .. or, using the z-domain notation, x(t0) = t, x(t1) = z-1x, x(t2) = z-2x, ... to produce an equivalent z-transform transfer function

Y (z) B0 + B1z 1 + B2 z 2 +... = X (z) A0 + A1z 1 + A2 z 2 +...

The equation now shows a new set of coefficients, each a function of the original coefficients of the respective polynomials. To summarize, differential equations and Laplace transfer functions are converted to z-transform transfer functions. This is done in the solver by applying a numerical transformation to the coefficients of each polynomial. Instead of using values of derivatives, the equation is solved numerically by making simple references to as many past values of y and x as needed in each case. 2.5.2.2. Initialization Because of the transformation discussed above, we can initialize the solution of any of these equations without having to provide initial conditions for the derivatives of a differential equation or Laplace transfer function. It is sufficient to describe the value of the variable at past times before time zero, simply using a history expression f(t) written in function of time. The solver will continue the calculation from time zero onward just as if all the initial conditions on the derivatives had been provided. Some textbook examples of differential equations set t=0 at a time when the system is in a transient condition, not a steady-state condition, and need initial conditions on the derivatives in order to solve the equations analytically. This situation is not representative of typical simulations, where we start a simulation from a known simple state, and then let the transient behavior start only at or after the beginning of the simulation. In any case, even if one needs to start a simulation from a transient condition, it can be argued that if one has enough information to know analytically the initial conditions of all the derivatives, one certainly has enough information to also know the shape of the variables in the form of a history expression f(t). Let's look at an example where we have to find the time domain solution for the following differential equation using Laplace transforms (from Kuo): d2x/dt2 + 3 dx/dt + 2 x(t) = 5 u(t) with initial conditions x(0) = -1 dx/dt = 2

36 This problem is not a simulation problem. In a simulation situation, if we have enough information to know not only the instantaneous value of an output but also the instantaneous value of its derivative(s) at initial time t0, we also certainly have enough information to have a very good idea of the shape of that signal around time t0. That is what we can then provide to MODELS as history of the signal at time t0 in the form of a function f(t). To use this example in MODELS, we could go around the problem and provide the analytical form of the signal as history expression f(t). But then, if we know the analytical expression of y, we don't need a differential equation to simulate it, we can just use the analytical expression directly as y = f(t) MODELS is not meant to serve as a symbolic or analytical equation solver. It is a simulation solver. The solution of differential equations in MODELS is not based on the calculated values of the inner derivatives of the signals (the analytical approach), but instead uses the measured values of the signals at one or more past simulation times (the empirical approach, implemented using z-transforms). For doing mathematical exercises not requiring simulation, it may be more appropriate to use a symbolic or analytical mathematical solver. 2.5.2.3. Values of y at t0 At the first execution of a model-use (that is, at the initial time at which each instance of that model is called), the above equations don't need to be recalculated, because the value of the variable to which they apply is already defined by its history expression. The same reasoning applies to the value of the integrals. 2.5.2.4. Using CDIFFEQ, CLAPLACE, and CZFUN Using CDIFFEQ, CLAPLACE, or CZFUN, the coefficients of the polynomials are considered to be constant, and are evaluated only once at the start of the simulation of each instance of a model, instead of at every time step. The equation itself, of course, is evaluated at each time step, whether the coefficients are constant or variable. 2.5.2.5. Limits The only limit that can be applied directly to the value of a variable calculated using a differential equation and a Laplace or z transfer function, is a dynamic limit. This is because when a limit is reached, all the derivatives of that variable become zero, therefore changing the internal state of the "component" used to produce the output represented by that variable. If we need to apply a limit (minimum and/or maximum) which does not modify the internal state of the represented component, we apply a static limit to that variable in a separate equation.

37 For a Laplace function, for example, a dynamic minimum limit can be specified along with the equation:

LAPLACE(y/x) {dmin: expr} := (...)/(...)

LAPLACE(y/x) := (...)/(...) z := y {min: expr}

An example of a component that reaches a limit is an op amp used with a resistor and a capacitor in the feedback branch. If the output of the component is clipped by a limiter placed past the component, the voltage across the capacitor in the feedback branch will show the same values as if there was no limiter. The external limit is a static limit as seen from the component. But if a Zener diode is placed in parallel with the feedback branch to limit the output voltage, the voltage across the capacitor will also be limited. This is a limit operating internally to the component, as it dynamically affects the internal operating behavior of the component. This is a dynamic limit. A mechanical example is the indicating arm of a meter reaching a stop peg at the upper end of the scale. If the arm is mounted on a spiral spring, the spring will compress while the driving torque attempts to push the arm past its allowed range. When the torque decreases, the spring needs to unwind to its resting position before the arm will start moving away from the peg. This is a static limit, also called "windup" limit, for the spring winding up. If instead the arm is mounted on a slip bushing, when the torque attempts to push the arm past its maximum position, the arm will simply slip on its shaft, ready to come off the peg as soon as the torque starts decreasing, without any unwinding delay. This is a dynamic limit, also called "no windup". This is shown in the figure below, comparing the effect of a static and a dynamic limiter on a the output value of a simple integrator:

2.5.3. Integral value assignment At any time t0 of a simulation, the time integral is defined as:

38

t0

x dt

the integral of x with respect to time, from -infinity to the present time. This can be decomposed, using t1 = t0 - t, as:

t0

x dt =

t1

x dt + x dt

t1

t0

or

The running value of an integral is calculated during a simulation by using the value of the integral at the previous time, and adding to it the value of the incremental integral over the past step. This increment, in MODELS, is calculated using the trapezoidal approximation, as the average of x(t1) and x(t0), multiplied by the time interval t0-t1:

I = x(t1) + x(t 0 ) (t 0 t1) 2

However, it is possible to bypass this process and assign a value to the integral directly, in effect resetting the value of the integral, to zero or some other value, by using an integral value assignment of the form:

integral(x) := expression

This new value becomes the starting point to which the next incremental integral will be added at the next time step. One detail to notice is the following. At a given simulation time inside the EXEC of a model, we may assign a value to x, then use the value of its time integral (which will use the present value of x to calculate the integral increment). Then further on in the EXEC at the same time step, we may assign a different value to x, then again use the value of the integral (which will use the new x to recalculate its increment), and so on. But from the point in the EXEC where a value is directly assigned to the integral, the value of the integral is not dependent on the present value of x anymore for the rest of that EXEC at that simulation time. No matter how often one changes the value of x after the reset inside the same time step, any reference to the value of the integral will always return the same value, the reset value that was assigned directly to the integral by the integral value assignment.

2.5.4. History expression assignment To associate a history expression with a variable in the INIT procedure, we use a history expression assignment:

histdef(y) := expression written as a function of the variable "t"

39 This is the third form of history assignment, as discussed in the section on the INIT procedure. The expression can itself make reference to the history expression associated with other variables. For example, to make the history expression of y dependent on the history expression associated with another variable x, we can use the histdef() function in the expression:

histdef(y) := 2 * histdef(x)

Notice the difference between the equation above, and the following:

histdef(y) := 2 * x

which would not achieve the intended purpose, but instead only use the most recent value of x whenever the history expression of y needs to be evaluated.

2.5.5. IF statement IF statements are used for grouping statements that are executed only when certain conditions are met. 2.5.5.1. Explicit IF statement The simple form of the IF statement consists of a single conditional clause:

IF condition_is_true THEN statement list ENDIF

Multiple clauses can be chained inside the same IF statement. Only the first clause found with a true condition is executed:

IF condition_is_true THEN statement list ELSIF another_condition_is_true THEN another statement list ELSIF ... ... ENDIF

A default clause, the ELSE clause, can also be defined. It is executed only when no other clause of the IF statement is found with a true condition:

IF condition_is_true THEN statement list ELSIF another_condition_is_true THEN another statement list ... ELSE another statement list ENDIF

IF condition_is_true THEN statement 1 statement 2 IF condition THEN another statement list ... ENDIF ... ENDIF

There is no "CASE" statement in MODELS at this time, although it may be added later. A case statement can be described using an IF statement with multiple clauses, as shown in the following example:

MODEL if_example -- illustrates the IF structure in MODELS VAR k INIT k:=0 ENDINIT EXEC IF k=0 THEN k:=1 ELSIF k=1 THEN write("In first 'elsif' with k=1") k:=2 ELSIF k=2 THEN write("In second 'elsif' with k=2") k:=3 ELSE write("In 'else' with k=3") ENDIF ENDEXEC ENDMODEL

2.5.5.2. Implicit IF statement When we need to determine the value taken by a variable under a variety of conditions, we can use an explicit IF statement, for example:

IF onswa=2 THEN IF ia<=ichop THEN IF di_dta<di_lim THEN onswa:=3 ENDIF ENDIF ELSE IF dva>ds THEN onswa:=2 ENDIF ENDIF

The first three conditions can be grouped using a logical expression, and the IF statement can be rewritten as:

IF onswa=2 AND ia<=ichop AND di_dta<di_lim THEN onswa:=3 ELSIF dva>ds THEN onswa:=2 ENDIF

41 But in MODELS, logical expressions return a numerical value, 0 or 1. This IF statement can therefore also be expressed as a value assignment that uses the value of a condition inside a numerical expression:

cond_1 := onswa=2 AND ia<=ichop AND di_dta<di_lim cond_2 := NOT cond_1 AND dva>ds cond_3 := NOT cond_1 AND NOT cond_2 onswa := 3*cond_1 + 2*cond_2 +onswa*cond_3

If cond_1 is true, its numerical value is 1, cond_2 is false, and the expression evaluates to: 3*1 +2*0 +onswa*0, and so on. Conditional expressions can also use a variable as a selector:

y := (a=1)*f1(x) +(a=2)*f2(x) + ...

IF a=1 THEN y:=f1(x) ELSIF a=2 THEN y:=f2(x) ... ENDIF

In this example, economy of execution time is almost not an issue. This is because of the automatic optimization used by MODELS when evaluating expressions. Each term of an expression is evaluated from left to right. If a factor is found to be zero, the value of the whole term is immediately set to zero without evaluating its other factors. In the above case, if a=1 is true, then only f1(x) is evaluated, not f2(x), because the factor (a=2) has a zero value. This has the same effect as using the IF statement. The only difference is that in the IF statement, as soon as one clause has been executed, the execution immediately jumps to the end of the IF statement; in the assignment, the terms of the expression are not mutually exclusive, and each one must be calculated, if only to find that the first factor of each remaining term is zero. In the end, the decision to use implicit conditions instead of explicit ones depends on what is being expressed. Certainly, the implicit form is not as clear. On the other hand, it can be used directly inside a function expression, while an IF statement can only be used inside a procedure.

2.5.6. WHILE statement Using a WHILE statement allows a group of statements to be executed zero or more times during the same time step, for as long as a condition is evaluated as true.

WHILE condition_is_true DO statement list ENDWHILE

42 This structure can be used for doing iterations inside a model, with the simulation time "frozen" for the duration of the iteration:

MODEL while_example -- illustrates the use of WHILE VAR k EXEC IF t=timestep THEN -- execute only at the first time step write("*** Begin results of model 'while_example' ***") k:=5 WHILE k>0 DO write('k=', k, ' in loop ') k:=k-1 ENDWHILE write('k=', k, ' after loop ') write("*** End results of model 'while_example' ***") ENDIF ENDEXEC ENDMODEL

The word "while", in this case, does not imply a reference to time, and does not mean "when". If we need to express "when a condition is true then do this", we can use an IF statement to take care of that, as shown in the example above with "IF t=timestep THEN".

2.5.7. FOR statement A FOR statement is used for repeating the execution of a group of statements using a list of values given to one or more parameters.

FOR i:= list of values FOR j:= list of values FOR ... DO statement list ENDFOR

Two differences can be observed between the implementation of the FOR statement in the MODELS language, and that found in many programming languages. The first one is that we can specify values for more than one parameter, applied to the same DO list:

FOR n:= 1 to 4 FOR m:= n to 4 DO write( m ) -- 1,2,3,4, 2,3,4, 3,4, 4 ENDFOR

The other difference is the values to be taken by each parameter are given in the form of a value list, where each term of the list can be either a single value or a range of values:

FOR z:= 0 TO 5, 6, 7 TO 9 BY 1 -- 0,1,2,3,4,5 -- 6 -- 7,8,9

43 The statement list placed inside the FOR statement is executed repeatedly until all combinations of the parameter values have been covered:

MODEL for_example -- illustrates the use of FOR in MODELS VAR k EXEC IF t=timestep THEN -- execute only at the first time step write("*** Begin results of model 'for_example' ***") FOR z:= 0 TO 5, 6, 7 TO 9 BY 1 FOR y:= 0 TO 8 BY 2 DO k:=z*10 +y write(k) ENDFOR FOR z:= 9 to 0 by -1 FOR y:= 5, 0 DO write(z*10 +y) ENDFOR ----0,1,2,3,4,5 6 7,8,9 0,2,4,6,8

-- 0,2,4,6,8,10,12,...,94,96,98

As shown in this example, the values of the parameters are assigned and combined in the sequence in which they are specified. The names of the parameters are local to the FOR statement, and don't need to be declared as variables of the model. Even though the simple examples above show only integer values, the parameters can also be assigned non-integer values:

FOR angle:= 0 TO 2*pi BY pi/4 DO write('tan(', deg(angle), ') = ', tan(angle)) ENDFOR

As for the WHILE statement, the simulation time is frozen while control of the execution is kept inside a FOR statement.

2.5.8. DO statement Like the WHILE statement, the DO statement is used for repeating the execution of a group of statements.

DO statement list ENDDO

The first difference is that in the DO statement, the statement list is executed at least once.

44 The second difference is that the condition determining whether the loop will be repeated or not, is carried by a flag set by executing the REDO statement anywhere inside the statement list. The DO statement is like a WHILE statement written as follows:

redo_flag := TRUE WHILE redo_flag = TRUE DO statement list ENDWHILE

The DO statement is used instead of the WHILE statement in situations where the loop condition is more complex than can be expressed in the simple conditional expression of the WHILE statement. Instead of having to declare and use a flag explicitly as in the last example above, we can directly use the REDO statement in one or more places inside the statement list. As for the WHILE statement, the simulation time is frozen while control of the execution is kept inside a DO statement.

2.5.9. REDO statement The REDO statement is used in combination with the DO statement described above. Each time the REDO statement is executed, it sets a flag that tells the DO group to repeat its execution from top to bottom the next time that decision is made. The status of the flag is checked only when execution of the group reaches the bottom of the group. The status of the flag is automatically reset to false each time the execution restarts at the top of the DO group.

2.5.10. COMBINE statement The default flow of execution inside a procedure is sequential. Sets of variables that need to be assigned a value simultaneously are identified in MODELS by being placed inside a COMBINE statement. An alternative is for them to be described and solved in a separate user-supplied program called by MODELS at each time step of the simulation. There are two types of solutions for simultaneous variables in MODELS. One is linear, solved using a simple Gaussian method. The other method handles simultaneous nonlinear equations using Newton iteration. The linear method is faster but less flexible. The nonlinear method is more general, although it consumes more execution time and its convergence is dependent on the set of equations being solved and on the appropriate choice of initial conditions. This is why it may be advantageous in some situations to use the linear method to solve a group of nonlinear simultaneous equations, either for the sake of speed of execution or for avoiding convergence problems.

45 2.5.10.1. Using the linear COMBINE for linear equations The linear COMBINE statement is used in the following format:

COMBINE AS identifier statement list ENDCOMBINE

COMBINE AS feedback_controller equations of the feedback controller ENDCOMBINE

When a COMBINE is used in the statement list of a repetition statement (either WHILE or FOR or DO), the identifier must be written in an indexed form, in order that each time the COMBINE statement is executed inside the repetition loop, it refers to a different set of variables:

FOR i:=1 TO n DO COMBINE AS probe[i] equations of the probe circuit, indexed with "i" ENDCOMBINE ENDFOR

The statement list of a linear COMBINE can include any arrangement of the following types of linear equations: - differential equations, which in MODELS use a linear polynomial of the time derivatives of a variable; - Laplace transfer functions, which are described using two linear polynomials of the "s" operator; - z transfer functions, which are described using two linear polynomials of the "z -1" operator; - linear value assignments of a variable or of an array element of a variable, using: - a sum expression, which is a linear sum of variables - a derivative expression, which is a polynomial of the time derivatives of a variable - the integral of a variable - the first or second derivative of a variable - no regular expression (considered nonlinear) Here is an example combining two simultaneous linear equations: a+b=6 a=t*b ( rewritten as b = 6 - a )

46

MODEL comb1 VAR a, b EXEC COMBINE AS first_group b := sum( 6| - 1|a ) a := sum( t|b ) ENDCOMBINE write('t=',t,', a=',a,', b=',b,', a+b=',a+b) ENDEXEC ENDMODEL

Each line of the COMBINE group describes how a value is assigned to each simultaneous variable. This is why the first equation is rewritten to express the value of b, as we were already using the second line to express the value of a. The syntax of the sum() expression is explained in the section on "Expressions". Notice how the format of the sum() expression requires that we place the coefficient of the left of each term, and the variable on the right of the term. This is why we could not write a := sum( b | t ), because in this case, t is not a variable of the group, b is. The linear COMBINE allows us to add min/max limits to one of the equations:

MODEL comb1 VAR a, b EXEC COMBINE AS first_group b := sum( 6| - 1|a ) a := sum( t|b ) { max: 4 } ENDCOMBINE write('t=',t,', a=',a,', b=',b,', a+b=',a+b) ENDEXEC ENDMODEL

Here are four versions of the same set of simultaneous equations showing the relationship between sin(t) and cos(t), all with the same solution of: y1 = sin(t), y2 = cos(t), y3 = -sin(t) The first set uses integrals: y1 = integral(y2) y2 = integral(y3) y3 = - y1 The second set uses derivatives: y2 = deriv(y1) y3 = deriv(y2) y1 = - y3 The third set uses a Laplace version of the integrals: Laplace(y1/y2) = 1/s Laplace(y2/y3) = 1/s y3 = - y1

47 The fourth set uses a z-transform and Laplace version of the derivatives: z-transform(y2/y1) = (1 - z -1) / (h + hz -1) Laplace(y3/y2) = s/1 y1 = - y3

MODEL comb2 -- illustrates linear COMBINE groups in MODELS VAR y1, y2, y3, x, h HISTORY y1 {dflt: sin(t)} y2 {dflt: cos(t)} y3 {dflt: -sin(t)} integral(y2) {dflt: sin(t)} integral(y3) {dflt: cos(t)} x {dflt: cos(t)} INIT h:=timestep/2 ENDINIT EXEC write(' ') write('Results at t=', t, ' :') COMBINE AS first_group y1:= integral(y2) y2:= integral(y3) y3:= sum(-1|y1) ENDCOMBINE write(sin(t),':',y1) COMBINE AS second_group y2:= deriv(y1) y3:= deriv(y2) y1:= sum(-1|y3) ENDCOMBINE write(sin(t),':',y1) COMBINE AS third_group laplace(y1/y2) := 1|s0 / 1|s1 laplace(y2/y3) := 1|s0 / 1|s1 y3:= sum(-1|y1) ENDCOMBINE write(sin(t),':',y1) COMBINE AS fourth_group zfun(y2/y1) := (1|z0 -1|z-1)/(h|z0 +h|z-1) laplace(y3/y2) := 1|s1 / 1|s0 y1:= sum(-1|y3) ENDCOMBINE write(sin(t),':',y1) ENDEXEC ENDMODEL -- (s/1)

2.5.10.2. Using the iterated COMBINE for nonlinear equations Using the iterated COMBINE, there are no restrictions on the types of value assignments and on the number of limits that can be used. All assignment types allowed in the linear COMBINE can be used, plus assignments using linear and nonlinear regular expressions. As in the linear COMBINE, all assignment statements placed in an iterated COMBINE are evaluated simultaneously. Each statement in the COMBINE

48 statement list specifies how to calculate the value of one of the simultaneous variables. The iterated COMBINE statement is used in the following format:

COMBINE ITERATE AS identifier statement list ENDCOMBINE

The same rules apply to the identifier as in the linear COMBINE. The example of the two algebraic equations, shown in the section above using the linear COMBINE, can be rewritten for the iterated COMBINE as follows:

MODEL comb1i VAR a, b EXEC COMBINE ITERATE AS first_group b := 6 - a a := t * b ENDCOMBINE write('t=',t,', a=',a,', b=',b,', a+b=',a+b) ENDEXEC ENDMODEL

COMBINE ITERATE AS first_group y1:= integral(y2) y2:= integral(y3) y3:= -y1 ENDCOMBINE

Iterated COMBINE groups are solved using the Newton method. The tolerance value is fixed at 10-8 times each value. The maximum allowed number of iterations per step is user-definable, with a default of 10. A maximum number of iterations other than 10 can be specified inside braces following the keyword ITERATE, for example:

COMBINE ITERATE {5} AS first_group b := 6 - a a := t * b ENDCOMBINE

indicating that we would allow only 5 iterations for convergence to take place. Here is an example that illustrates how an iterated COMBINE can be used with different types of assignments and multiple min/max limits. It describes a somewhat acrobatic set of simultaneous equations that should provide the following solution: y1 = y4 -y2 +2 { max: y4/y2 } y2 = 2 * t * y1 y3 = integral(y2) { max: 7.5 * y2 / t } y4 = deriv(y3) * (y2 < 4) ( Solution: y1 = 1 ) ( Solution: y2 = 2 t ) ( Solution: y3 = t 2 { max: 15 } )

MODEL comb3 -- illustrates nonlinear COMBINE ITERATE groups in MODELS VAR y1, y2, y3, y4, y5 HISTORY y1 {dflt: 0.0} -- wrong on purpose, should be 1 y2 {dflt: 2*t} integral(y2) {dflt: t*t} y3 {dflt: t*t} y4 {dflt: 2*t} y5 {dflt: t*t} EXEC COMBINE ITERATE {9} AS first_group y1:=y4-y2+2 {max:y4*recip(y2)} y2:=2*t*y1 y3:=integral(y2) {dmax: 7.5*y2*recip(t) } y4:=deriv(y3)*(y2<4) + 2*t*(y2>=4) y5:=sum(y3| +1|y2 -1|y4) ENDCOMBINE write('t=', t, ' y1=' y1 ', y2=' y2 ', y3=' y3 ', y4=' y4 ', y5=' y5) ENDEXEC ENDMODEL

2.5.10.3. Using the linear COMBINE for nonlinear equations It is possible to use the linear COMBINE statement with a group of nonlinear simultaneous assignments. The linear COMBINE group is restricted to linear expressions only in terms of the simultaneous variables of the group, but not in terms of the coefficients applied to the variables. This means that any coefficient of a diffeq(), laplace(), sum(), or derivpol() inside a COMBINE can be a nonlinear expression in terms of variables other than the simultaneous variables of the group. As discussed at the beginning of the section on the COMBINE statement, it may be desirable in some circumstances to "squeeze" a set of nonlinear equations into a linear COMBINE, either to save on execution time by eliminating the iteration, or to solve a convergence problem. Following are some options for dealing with sets of simultaneous nonlinear equations using a linear COMBINE: a) we replace the nonlinear COMBINE by breaking the evaluation loop open and by describing the equations in the best sequence one can find; we need to keep the time step small, because it's equivalent to using zero-order prediction (like Forward Euler); of course there is the problem of deciding where it is best to open the evaluation loop; that is documented in the MODELS Rule Book (rule of thumb: always on signals that vary more slowly than the others, like the output of an integral or the output of a low-pass filter) b) we use a) on the nonlinear equations of the group, and we use a linear COMBINE to solve the remaining linearized set of equations simultaneously; c) we use a) or b), and we apply some form of prediction on the inputs that should be simultaneous but that we chose to solve separately; of course, because this is prediction without correction, there is still a constraint on

50 keeping the time step small, but depending on the situation, we might be able to use a larger time step than with the implicit zero-order prediction approach; d) instead of a), b), or c) above, we rewrite the equations and provide a local iteration mechanism using a WHILE statement with an iteration condition -this allows to ease the constraints on the size of the time step, by localizing the iteration to where it's needed (so that in fact we provide both prediction and correction); e) instead of building the iteration mechanism in MODELS, we use an external program that solves the equations that we need to solve, and we attach that external program as a regular submodel or function in our model; this approach is particularly appropriate when the set of equations is the result of trying to simulate in MODELS something that would be better represented and better solved in a program which has representations and solution methods specifically designed for the domain of the application; local domain-specific solutions will always be more efficient that trying to use general representation or solution mechanisms that are not taking advantage of the specific conditions of the domain that is being represented; plus it saves the effort of having to reinvent it. When using MODELS to represent large systems, we look at MODELS as the procedural and numerical glue between the locallymore-tightly-coupled subsystems. We have the choice to represent and solve some of these subsystems using MODELS, and some of them using other programs called by MODELS.

2.5.11. ERROR statement The ERROR statement is a simple sequential structure formatted as follows:

ERROR statement list STOP

It is normally used inside an IF statement to terminate execution when the model detects some specified condition. The list of statements can then describe a list of actions to be taken before the simulation is terminated. An example would be to diagnose the situation with a write() statement or by writing information to a file.

MODEL errstp -- illustrates the ERROR statement in MODELS VAR x -- a model contains at least one variable EXEC IF t>=2 THEN -- execute only when t reaches 2 ERROR write('*** Demonstrating error stop in MODELS ***'); STOP ENDIF ENDEXEC ENDMODEL

51

2.5.12. USE statement The USE statement is the main point of call to instances of models used in a simulation. Whenever a USE statement is executed during a simulation, the corresponding instance will update itself to the present simulation time of the calling model, by running its EXEC procedure. If the instance does not exist at the time it is called, it will be automatically created, and initialized, before running its EXEC procedure. The initialization will take into account the use directives of the USE statement, the default directives of the called model, and the INIT procedure of the called model. The first function of the USE statement is to identify what model is called, and what instance of that model is called (there can be more than one instance of a model). This is done as follows:

USE modelname AS instance_identifier use directives ENDUSE

The instance identifier is either a name, or an indexed name. Indexed names are needed when placing a USE statement inside an indexed loop, for example:

FOR i:=1 TO n DO ... USE somemodel AS someid[i] ... ENDFOR

letting the USE statement call a different instance of the model for each value of the loop variable i. The use directives are described in the section "Using a model".

2.5.13. Call to a procedure Procedure calls are auxiliary points of call to an instance of a model, the main point of call being the USE statement that creates and updates that instance during a simulation. A procedure call is used for executing a named procedure of a specified instance of a model. For example, supposing that the called model includes a procedure called reset_integral(value). This procedure would be called from another model as follows:

instance_identifier.reset_integral(expression)

It could also be called from the model in which it is defined, using the reserved instance identifier self:

52

self.reset_integral(expression)

If a procedure expects input arguments, they are supplied as a list of expressions or array values when the procedure is called. If a procedure expects no input argument, then only its name is needed in the procedure call:

instance_identifier.write_y

If a procedure returns values, it is used just like a function is used in an expression, for example:

y := 3*x + self.normalized( w, alpha)

where normalized is the name of a procedure defined, in this case, in the same model.

2.5.14. Call to a pre-defined procedure A number of procedures are pre-defined, and are available in any model. They always apply to the model from where they are called, and therefore do not require an instance identifier (self is implied). Only three pre-defined procedures are available at this point, although more will be added in the future. 2.5.14.1. WRITE() procedure This procedure receives a list of numerical and text values as input, and sends a corresponding formatted line of text to the program output. Text values are strings of characters delimited by apostrophes or quotes. Numerical values are described using regular expressions.

write('This text is followed by a value equal to ', abs(x)+4 )

2.5.14.2. WRITE1(), WRITE2() procedure These two procedures are used just like the WRITE() procedure, with the exception that they send the formatted line of text to a file named models.1 or models.2 respectively.

53

3. WRITING EXPRESSIONS

Regular expressions are used in a model everywhere a value needs to be specified. Any value in a model can be represented by an expression describing symbolically how to calculate that value. Special expressions including the linear sum, the polynomial of derivatives, and the integral expression, can only be used as the right-hand side of an assignment statement.

A regular expression is the standard mechanism used in a model for representing how to calculate a value. It can include references to named value-holding elements, numerical and logical values, and calls to functions and procedures. A set of numerical and logical operators is available for joining the members of an expression in an arbitrary level of complexity. Expressions can use array arithmetic, and can calculate a list of values in the form of a onedimension array.

3.1.1. Referring to a named value-holding element In an expression, we can refer to the value of a value-holding element of the model, for example a variable, by mentioning its name:

name

If the variable is an array, we can refer to a single element of that array by also indicating its index in the form of an expression:

name[expr]

name[expr..expr]

A simple set of rules determines how the named value-holding elements of a model are visible for reference inside used expressions in different parts of the model. First, here are the definitions of the types of constant and variable named elements that can be referenced in a model: - the constants: global constants constants

the pre-defined constants pi, inf, true, false, etc... the declared constants of the model

54 data - the variables: global variables simulation variables inputs variables FOR arguments function arguments the declared parameters of the model

the pre-defined variables global to a simulation: starttime, startstep, stoptime the pre-defined variables local to each instance of each model: t, prevtime, timestep, endtime, fullstep, minstep, maxstep the declared inputs of the model the declared variables of the model the loop variables of FOR loops the named input arguments of statement functions

Here are the rules of reference, defining what elements are visible in what parts of a model: visible in any expression global constants constants data variables of any type visible in any expression visible in any expression, except in a CONST declaration not visible in constant-valued expressions, such as: - array index in any declaration - value of a constant or data - directives of interpolation degree and delay cells - array dimensions of foreign models and functions visible only inside the FOR loop where they are defined visible only inside the statement function where they are defined

An additional distinction needs to be made when using named elements inside a USE statement, as to whether we may be referring to a named element belonging to the local model or belonging to the used model: simulation variables visible in expressions defining the number of delay cells (allowing, for example, to use the size of the of the used model submodel's time step for determining the number (t, timestep, etc.) of cells in the submodel from the USE statement)

55 data of the used model visible in expressions specifying the array index of data, input, and output arrays, of arrays assigned a history, and of arrays specified in interpolation degrees and delay cells

Names used in any other expressions inside a USE statement are taken to be references to elements of the local model (calling model), not of the used model. For example, let's suppose there is a data n defined in both the local model and the used model (and carrying different values, of course). In a USE statement, if the name n is used in an array index of one of the assignments, it will be referring to the value of n from the used model. This way, we can write

USE ... DATA n := _____ INPUT a[1..n] := _____

But if the name n is used in an expression on the right-hand side (for example, defining the assigned value of an input), it would be referring to the value n of the local model, not of the used model:

USE ... INPUT a[1..n]:= 2*n*(t-2)

Specifying the context of the named elements we are referring to inside a USE statement is not a simple matter. The present set of rules allow us to use an implicit notation. These rules do satisfy most applications, but we can always find examples where it would be useful to do just the opposite of what the rule says. For example, it would be useful to write

USE ... INPUT a[1..n] := b[1..n]

or

USE ... INPUT i1 := ... i2 := 2*i1

The only way we can do the first one, according to the above rules, is if n is a name defined in the local model, not the used model. And the present set of rules doesn't allow the second example. The alternative to implicit notation would be to use an explicit notation, that is, an indication that tells directly if a name belongs to the local model or to the used submodel, either with a keyword or an operator, for example:

USE ... INPUT a[1..sub.n] := b[1..sub.n]

or

USERS GUIDE TO MODELS IN ATP

56

USE ... INPUT i1 := ... i2 := 2*sub.i1

This is not available yet, but it will become available in the future. Note that this potential ambiguity of names exists only inside a USE statement, and only when the same name is used for different purposes in both the local model and the used submodel. It might be tempting to avoid the problem altogether by not duplicating names in the two models. In a small project, this is easy to do. But when we start building libraries of models, we need the flexibility of being able to define names without worrying about their use somewhere else, that is, we need a local name space for each model, which is one of the principles on which MODELS is designed.

3.1.2. Specifying a numerical value There are no different types of numerical values in MODELS. No distinction needs to be made between Booleans or integers or reals, and no specification of their storage to use a small or large number of bytes. Values are all stored as reals, using the maximum precision available. This approach may require a slightly larger area of memory for storage, but it simplifies the language greatly, and it removes the burden of doing type conversion during the simulation. Integer, decimal, and scientific notations are accepted. A value may be signed. The first character following the optional sign must be a digit, and cannot be a decimal point. Here are some valid examples:

0, 0.0, -0.1, -1E-6, 1.E3, 0.2E-9

3.1.3. Using a value calculated by a function MODELS provides a set of pre-defined functions for numerical and logical operations, like abs(), sin(), and(), etc., and a set of pre-defined simulation-related functions like prevval(), delay(), deriv(), etc. It is also possible to define local functions in a model, including statement functions and point list functions. And it is possible to include in a model functions represented in separate programs (foreign functions). These functions are all used in the same way, inside an expression, by indicating the name of the function and the value of its arguments. Notice that the left parenthesis must immediately follow the name of the function. For example:

y1:= 2*abs(x+w) +4 y2:= prevval(x) - prevval(w) y3:= min(va, 2*vb, v[1..n]) p[1..n]:=sqrt(v[1..n]) ----single input, single output single input, single output multiple input, single output multiple input, multiple output

As shown in these examples, the value of each input argument can be described using a regular expression. When a function expects a list of values as input,

57 these values can be described using a list of expressions, including expressions that return multiple values in the form of an array.

3.1.4. Using a value calculated by a procedure Two types of procedures can be defined: ones that perform an operation on a model without returning a value to the point of call, and ones that also return a value or a list of values. Procedures that return one or more values are called from inside an expression, just like a function. The only difference is that instead of indicating just the name of the procedure, we also need to indicate in which model instance it is operating, for example:

w := controller.status y := 3*x + self.normalized( w, alpha)

where status is the name of a procedure defined in a submodel used with the instance name controller, and normalized is the name of a procedure called from the same model where it is defined.

3.1.5. Logical and numerical operators A set of operators can be used inside an expression to express how its members are joined: logical binary op OR AND > >= < <= = <> numerical binary op +,*,/ ** MOD logical unary op numerical unary op NOT true if either member is true true only if both members are true true if left greater than right true if left greater than or equal to right true if left smaller than right true if left smaller than or equal to right true if left equal to right true if left not equal to right addition and subtraction multiplication and division exponentiation modulo (division remainder) true if member is false or <=0 negative of member

58 The above sequence also shows the default order of precedence among the operators. Here are some examples:

a AND b OR t-ton>0 a*b-c/d**2 -- = (a AND b) OR ((t-ton)>0) -- = (a*b) - (c/(d**2))

Parentheses can be used for explicitly indicating the sequence of operations. At each level of precedence, the evaluation proceeds from left to right. In cases when the result of an operation provides a value that cannot be further modified at that level of precedence, the remaining members of that level are not evaluated. For example, in the expression

a*b*(more...)+c

if the value of b is found to be zero, the evaluation of the sub-expression inside the parentheses is skipped, and the value of the expression is a*0 +c, that is, c. The same approach is used with the logical operations. As soon as a member in an AND sequence is found to be false, the rest of the sequence is not evaluated, and the returned value is false. As soon as a member in an OR sequence is found to be true, the rest of the sequence is not evaluated, and the returned value is true.

3.1.6. Limits on a regular expression We can specify minimum and maximum limits to be applied to the value returned by an expression. These are static limits, that is, they are calculated and applied after the expression has been evaluated, and do not affect how the expression is evaluated:

a*b {min: 3*abs(c)-d}

In the above example, the minimum is applied to the result of the complete expression, not to the value of b. It is possible to apply limits to part of an expression, by enclosing that part in parenthesis, thus making it a separate expression to which a limit can be applied:

a*(3*b +c {min: ... , max: ... })

In this example, the limits are applied to the value of 3*b+c. Again, notice that the limit is applied to the complete expression to which it is attached, not to the last member of that expression. Here, the expression is not applied to c. Additional parentheses can be used to make this more explicit:

a*((3*b +c) {min: ... , max: ... })

59

3.1.7. Using expressions with arrays Operators can be used with ranges of array elements, and can return groups of array values. Individual values can be assembled in array form by enclosing them inside square brackets. Here are some examples:

a[1..3] := 0 [0,0,0] c[1..3] := [1, 2, 3] [1,2,3] a[1..3] := c[1..3] [1,2,3] a[4..6] := [1, a[2..3] -[1, 2]] [1,1,1] a[4..6] := a[4..6] -1 [0,0,0] a[4..6] := a[1..3] +10 [11,12,13] a[4..6] := 10 +a[1..3] [11,12,13] a[4..6] := a[1..3] +[10,10,10] [11,12,13] a[4..6] := a[1..3] -a[4..6] 10] a[4..6] := a[1..3] *10 [10,20,30] a[4..6] := 10 * a[1..3] [10,20,30] a[4..6] := a[1..3] / 0.1 [10,20,30] a[4..6] := 12 / a[1..3] [12,6,4] a[4..6] := a[1..3] AND [0,0,1] [0,0,bool(a[3])] a[1..3] := a[1..3]**2 [1,4,9] a[4..6] := 10**a[1..3] [10,100,1000] a[4..6] := a[4..6] {max:[100,100,8]} [10,100,8] a[4..6] := a[4..6] {max:9} [9,9,8] a[1..3] := a[4..6] MOD 6 [3,3,2] a[1..3] := 11 MOD a[1..3] [0,1,2] -- 1-to-n assign -- n-to-n assign -- n-to-n assign -- n-to-n subtract -- 1-to-n subtract -- 1-to-n add -- 1-to-n add -- n-to-n add -- n-to-n subtract -- 1-to-n multiply -- 1-to-n multiply -- 1-to-n divide -- 1-to-n divide -- n-to-n AND -- 1-to-n exponent -- 1-to-n exponent -- n-to-n limit -- 1-to-n limit -- 1-to-n modulo -- 1-to-n modulo = = = = = = = = = = = [-10,-10,= = = = = = = = =

Functions and procedures can receive lists of values and arrays as arguments, and can return lists of values in the form of an array. See the respective sections for details.

60

Unlike regular expressions, which can be used anywhere in a model, three special types of expressions can only be used as the right-hand side of an assignment statement. They are the linear sum, the polynomial of derivatives, and the integral expression.

3.2.1. Linear sum A polynomial of variables can be grouped in a sum() expression, a special expression used in a linear COMBINE group of statements. This form of expression distinguishes the summed variables from their coefficients, allowing the use of nonlinear coefficients while still retaining the overall form of a linear summation. When used in a linear COMBINE statement, the variables of the sum can only be any of the simultaneous variables of the COMBINE group. But the coefficient expressions can refer to any other variable of the model. The symbolic notation is:

a0 + a1 x1 + a2 x2 +...

In MODELS, each of these coefficients can be described using a regular expression. The coefficients are separated from their respective variables using the "applies to" operator.

sum((b+c*d)|x1 + c|x2)

To express the bias term a0, a coefficient without a variable, we write that coefficient followed by an "applies to" operator followed by no variable, to prevent that coefficient to simply be included in the expression of the coefficient of the next term.

sum((a+b)| +(b+c*d)|x1 + c|x2)

because, without that first operator, the expression would be interpreted as:

sum((a+b)+(b+c*d)|x1 + c|x2)

The linear sum can also be used outside of a COMBINE statement, but without any advantage over simply using a regular expression. Minimum and maximum limits can be attached to this expression, and also to the value of each of its coefficients. For example:

sum((b+c*d){max:a1max}|x1 +c|x2) {min:minvalue, max:maxvalue}

61

3.2.2. Polynomial of derivatives A polynomial of time derivatives of a variable can be grouped in a derivpol() expression for use in a linear COMBINE statement. The expression follows the same notation as used in a DIFFEQ statement. When used in a linear COMBINE statement, the variable to which the derivatives are applied can only be any of the simultaneous variables of the COMBINE group. But the coefficient expressions can refer to any other variable of the model. The symbolic notation is: or, rewritten using the operator D to replace d/dt :

(a0 D0 + a1D1 + a2D 2 +...) x

In MODELS, the expressions describing each coefficient are separated from the D operator using the "applies to" operator.

derivpol((a+b)|D0 +(b+c*d)|D1 + c|D2)|x

The polynomial of derivatives can also be used outside of a COMBINE statement, with the advantage of being able to indicate higher orders of time derivatives than those provided by the functions deriv() and deriv2(). Minimum and maximum limits can be attached to this expression, and also to the value of each of its coefficients. For example:

derivpol((b+c*d){max:a1max}|D1 +c|D2)|x {min:minvalue, max:maxvalue}

3.2.3. Integral expression Using the integral of a variable x in a model automatically creates an extra variable carrying the value of the integral. That value is updated automatically at each time step, using the current value of x to calculate its updated value. The value of the integral is accessed using an integral expression:

y := integral(x)

That value can also be reset, using the integral assignment statement:

integral(x) := new_value

The integral of x with respect to time is calculated using the trapezoidal rule, with the assumption that x is linear over each step interval.

integral = x1 + x0 t 2

62 This is a reasonable assumption to make when the time step is small enough to follow the faster variations of x with respect to time. In cases where the time step is too large, these faster variations are simply filtered out of the integral value, with a possible loss of accuracy, but without consequences on the numerical stability of the calculation. It is possible to apply limits to the calculated value of a time integral. Because the integral does carry an internal state from one step to the next, this limit is a dynamic limit, that is, the value of the limit modifies not only the output value of the integral, but also its internal state, the value that will be carried over to the next time step. Limits are applied to the value of an integral as follows:

y:=integral(x) {dmin:expression, dmax:expression} -- dynamic limits

To only apply a static limit, that is, a limit that affects only the value of the output, not the state of the integral, we apply the limit outside the use of the integral:

y := integral(x) y := y {min:expression, max:expression} -- static limits

Following is an example showing the different effect of using a dynamic limit and a static limit on an integral:

MODEL ilim VAR x, y dlim nolim slim -- illustrates dynamic limit on integral in MODELS ----step signal =1 from t=0 to t<=1, =-1 for t>1 integral(x), dynamic limit=0.7 integral(y), no limit static limit=0.7 applied to 'nolim'

HISTORY x {dflt: 0} y {dflt: 0} integral(x) {dflt: 0} integral(y) {dflt: 0} EXEC x:= 1 IF t>1 THEN x:= -1 ENDIF y:= x dlim :=integral(x) {dmax: 0.7} nolim :=integral(y) slim :=nolim {max:0.7} ENDEXEC ENDMODEL

The values of the variables x, nolim, slim, and dlim are shown in the following figure:

63

64

The simulation directives affecting the operation of a model are: - the constraints placed on the size of the time step used by the model - the interpolation method to be used on the external input values at intermediate internal time steps - the number of delay cells to be reserved for storing the past values of variables and inputs affected by the delay() function - and the history expressions describing analytically the value of some of the inputs and variables of the model prior to its simulation. It is possible to specify default characteristics for these directives in each model description. This is what is covered in this section. It is also possible to specify or modify simulation directives in the USE statement of individual instances of a model. That is covered in the section on "Using a model".

It is possible to define local limits, minimum and maximum, on the size of the local time step to be used for the step-by-step solution of a model. The implications of updating a model at a smaller or larger time step than the one used outside the model, are discussed in the section on "Pre-defined local variables", in Appendix C. When a model is called from outside for updating its internal state to a new simulation time, the interval of time since the last call for update determines the step that the model could take to carry on its operation. But this outside step may not be properly scaled to the fineness of representation needed to follow the internal dynamic operation of the model, being either too large or too small. By specifying a minimum and/or a maximum limit on the size of the time step, we can maintain it within an appropriate range. If the outside time step is too large for the model, that is, larger than the specified maximum, the model will subdivide the outside step into finer internal steps. If the outside time step is too small for the model, that is, smaller than the specified minimum, the model will ignore the request for update, which would provide no significant change in the state of the model. The expressions used for describing these limits can make reference to the value of any variable in the model, providing the possibility to dynamically adjust these limits, and consequently the size of the time step, to changing conditions monitored in the operation of the model.

65 Typically, the size of the time step would be maintained between 1/100 and 1/10 times the size of the smallest time constant of the model. A finer step would be a waste of execution time. A larger step would affect accuracy.

TIMESTEP MAX: 0.1 * min(tau1, tau2, tau3) TIMESTEP MIN: 0.01 * min(tau1, tau2, tau3)

When the time step size is limited to a maximum value, and the outside step exceeds that value, the model will select a local time step that is a sub-multiple of the outer time step, and that fits inside the allowed limit. But when this happens, we don't have values for the external inputs to the model at those intermediate time steps. We use the input interpolation directive to specify what method of interpolation will be used for estimating the value of the inputs at the sub-steps. The directives are flexible. We can select different methods for different inputs. A default method can also be specified. Also, the method specified in the model definition can be modified later in the USE statement of individual instances of the model. The degree of the fitting polynomial can be specified as 0, 1, or 2, for step, linear, and quadratic interpolation, respectively. When not specified, linear interpolation is used. Step interpolation is no interpolation, that is, for all times ti between t-t and t0, y(ti) keeps the value y(t-t). Linear interpolation uses a straight line between the values y(t-t) and y(t). Quadratic interpolation uses the values y(t-2t), y(t-t), and y(t) to fit a parabola used for finding the values of y(ti) between t-t and t. The following notation is used:

INTERPOLATION DEGREE DFLT: 0 DEGREE(y1, y2): 1 DEGREE(y3): 2

INTERPOLATION DEGREE DFLT: 0 INTERPOLATION DEGREE(y1, y2): 1 INTERPOLATION DEGREE(y3): 2

66

Many functions of MODELS require past values of a variable for calculating the value of the function, for example, derivatives and integrals. The storage needed for recording these past values is taken care of automatically by the solver. This can be easily determined by the solver, because the storage window is never much longer than two or three cells back depending on the level of interpolation needed. Such is not the case for the delay() function. The size of the storage needed for recording the past values of a variable to be accessed by a delay() function depends on what size of delay will be used, and on the size of the time step at which the samples are recorded. For example, a delay value of 500 ms, in a simulation using a time step of 1 ms, would require 500 cells of storage for that variable. And this estimation is not necessarily so simple, considering that both the size of the delay used and the size of the time step can be described in the form of symbolic expressions, the value of which may vary dynamically during a simulation. Choosing to store all past values in order to avoid having to specify any storage dimensions is not a practical alternative either. This has been tried in earlier versions of MODELS, for use with the function pastval(). The storage needs can be considerable, and require paging from memory to external storage, a process that consumes more execution time, especially when considering the fact that most of those past values are never used. The present approach is to provide a simulation directive, in the model definition and/or in the USE statement, indicating how many cells must be reserved for storing a moving window of past values for each variable accessed by a delay() function. Typically, the expression specifying the number of cells will include a reference to the size of the time step used in the model. It must be understood, however, that this expression is evaluated only once when each instance of the model is created, and that the size cannot be adjusted later. A reference to the variable timestep would be using the value of that variable at the time when it is used, that is, at the time when the instance of the model is created and initialized. As a footnote, specifying the number of cells is also the approach that was used in TACS, although in a different form. For each delay device (type 53), we have to specify the maximum delay time for which the device will be used. Specifying the maximum time delay in MODELS would not suffice, because the timestep can also vary. The following notation is used:

DELAY CELLS DFLT: max(delay1, delay2)/timestep +1 CELLS(y1, y2): 50 CELLS(y3): 10

67 and the DELAY keyword can also be repeated. When a default value is not specified, a default value of 100 cells will be used.

To summarize what has been discussed in other sections, two types of references to the history expression of a variable or input are possible. One is hidden and is made internally by the solver whenever it needs to access a non-existing past value from a time t preceding the simulation of the model, for example when needing a delay value from a time before the simulation was started, or when needing pre-simulation values for the first few evaluations of a laplace(), diffeq(), deriv(), etc. The other type of reference is one that can be written explicitly in the model description in any expression. Two functions are available for this. One is histval(y,t1) which will use the history expression of variable y to evaluate y(t1). The other is histdef(y), which is equivalent to writing histval(y,t) for the generic value of time t. To understand the need to specify history functions, consider, for example, using a delay function which would make reference to the past value of a variable for a time preceding the time of the first execution of that model instance, as in

y := delay(x, delaysize)

which corresponds to asking for the value of x at time t-delaysize. If t-delaysize >= t0, then the value of x at that time has been stored in the delay storage cells of the model. But if t-delaysize < t0, then that value is undefined unless the model has access to an analytical expression describing how to calculate the value of x at times t<t0 . That is the purpose of being able to define history expressions for some of the variables and inputs of a model. A history expression is an expression that the model will use when it needs to find the value of a variable or input from a time for which no value has been stored in the model's running history. From this definition, it can be seen that history expressions can be used also for defining initial values. The possibility of referring to the variable t in history expressions allows us to define history values as regular expressions described as a function of time. In addition to allowing the definition of history expressions as an explicit function of time, this is also useful for defining the initial values of a model when it is impossible to predict exactly the time at which an instance of the model will be first executed during the simulation. As discussed in the section about the INIT procedure, it is possible to specify history expressions in three places in a model: as simulation directives in the model definition, as simulation directives in the USE statement of each instance of

USERS GUIDE TO MODELS IN ATP

68 the model, and in the INIT procedure of the model. A history expression specified as a simulation directive in the model definition is only a default expression that the model will use when it is not re-specified in the USE statement or in the INIT procedure. The notation is the following:

HISTORY y1 y2 {dflt: 0} y3 {dflt: A*sin(omega*t)}

As shown here, the history expression may include a reference to the variable t. When no expression is specified, the directive indicates that a history expression will be needed for that variable in the USE statement of each instance where the model is used. Consider that HISTORY directives are only declarations of history expressions, they are not a list of executed statements. The expressions will be evaluated only when and if required during the simulation. The initial value of integrals can also be specified using a history expression:

HISTORY integral(y) {dflt: expression}

HISTORY y[n1..n2] {dflt: expression} HISTORY y[n1..n2] {dflt: array expression} element -- same value for each element -- individual value for each

There is one difficulty with assigning a history expression in the model definition if the exact size of the group is variable, and depends on data determined in the USE statement. In the first example above, there is no problem, because the same value will be assigned to all elements of the group, whatever its size. In the second case, it depends on how the array expression is written. If it is written as a list of values, for example:

HISTORY y[n1..n2] {dflt: [expr1, expr2, expr3, ... ]}

then there may not be enough values in the list to cover the size of the group. The solution for this is to declare only the names in the model definition:

HISTORY y[n1..n2]

and to specify the history expressions in the USE statement, where the number of required values will be known:

HISTORY y[n1..n2] := [expr1, expr2, expr3, ... ]

69

5. USING A MODEL

Each USE statement defines an individual instance of a model. It is in the USE statement that we assign values to the data and the inputs of a model, and that we have access to the values of its outputs. We can also specify different simulation directives for different instances of the same model.

As discussed in the section about writing a model, data are constant values of a model, such as parameters and array dimensions, defined when a new instance of a model is created in a USE statement. The same data name can carry different values in different instances of the same model. Data values are assigned in a USE statement using the following notation:

USE modelname AS instance_name DATA n :=3 -- an array dimension used in the model freq := 60 -- overriding a default value of 50 ... ENDUSE

A data element that had been assigned a default value in the model definition does not need to be specified in the USE statement. But if it is, the new value will replace the default value of the model definition.

A model receives information through its input elements. It is in the USE statement that we specify how to calculate, at each time that the model instance is called, the values of its inputs. Different input expressions can be assigned to the inputs of a model in different instances where the model is used. Input values are specified in a USE statement using the following notation:

USE modelname AS instance_name DATA n := 3 INPUT vterm[1..3] := [va,vb,vc] vref := sqrt(3)*abs(v0) ... ENDUSE -- number of terminals -- value of measured terminal voltages -- reference voltage, replacing default value

An input element that had been assigned a default value in the model definition does not need to be specified in the USE statement. But if it is, the new value will replace the default value of the model definition.

70

The only values of a model that are visible to a calling model in a USE statement are the values of the model's outputs. The values of the outputs of a model can be assigned to variables of the calling model, using an output assignment inside a USE statement, as shown below:

USE modelname AS instance_name DATA n := 3 -- number of terminals INPUT vterm[1..3] := [va,vb,vc] -- value of measured terminal voltages vref := sqrt(3)*abs(v0) -- reference voltage, replacing default value OUTPUT vmax[1..3] := vtmax[1..3] maxval := vmax ... ENDUSE

An important aspect of using a model is illustrated in the above example. The names on the right-hand side of the OUTPUT assignments, vtmax[1..3] and vmax, are names of output variables from the used model. The names on the lefthand side of the output assignments, vmax[1..3] and maxval, are names of variables in the calling model. Notice how the variable named vmax exists in both the calling model and the called model, with a different meaning and a different array size. This illustrates how the meaning and the value of a named element are local to each model where the name is defined.

The simulation directives of a model are the limits on the time step size, the interpolation method used for different inputs of the model during sub-steps, the number of delay cells to allocate for the storage of the past values of some variables and inputs, and the history expressions to associate with some variables and inputs of the model. Simulation directives can be specified in the model definition and in the USE statements. In the model definition, they apply to all instances of the model. In the USE statements, they can be defined individually for each instance, possibly replacing the default directives of the model definition. The formats are similar to those used in the model definition, with the difference that for history expressions, just as for data and inputs, the assignment operator ":=" is used instead of the "dflt:" attribute.

TIMESTEP MAX: 1E-4 MIN: 1E-5

71

INTERPOLATION DEGREE DFLT: 0 DEGREE(y1, y2): 0 DEGREE(y3): 1 -- repeating from model def, for clarity -- modifying from model def -- modifying from model def

It is possible to call a model for update from a USE statement more than once per simulation time. This is needed when a model is used by another model or program from inside an iteration loop. It requires that the solver be able to reset the state of the called model to its previous original state from which to execute the model again. This is done automatically by the program when using the option ITERATE in a USE statement. The ITERATE is indicated just after the instance name, as follows:

USE modelname AS instance_name ITERATE

This option indicates to the solver that the model can be used more than once at each time step, for example when called from inside an iteration loop. When this option is specified, MODELS saves the initial state of the model when called at a new time step, and re-starts from that saved initial state at each re-update of the model at the same time step. The following data case provides a simple illustration.

72

MODEL iteruse MODEL sub EXTERNAL VAR a EXEC FOR i:=1 TO 3 DO USE sub AS sub ITERATE INPUT in:=i*t OUTPUT a:=out ENDUSE write('in iteruse at t=', t, ', a=', a) ENDFOR write(' ') ENDEXEC ENDMODEL MODEL sub INPUT in OUTPUT out VAR out EXEC out:=10*in write('in sub at t=', t, ', in=', in, ', out=', out) ENDEXEC ENDMODEL

Notice how it is the same instance of the model that is re-updated for each value of i inside the FOR loop. If we did not indicate the keyword ITERATE, the program would create separate instances of that model for each pass, and the instance names would need to be indexed, as:

USE sub AS sub[i]

Normally in a simulation, we need to retain the value of some variables of a model from one simulation step to the next. This is done automatically by MODELS, without requiring any special directives. All values of a model at the end of an execution are kept in memory, and are available to the model at the beginning of the next execution. When talking about the "state" of a model, the word "state" is taken in its generic meaning, as a snapshot of all information relevant to the condition of a model at a given instant of time. As indicated in the Language Manual, this description of the state of a model instance at the completion of an execution step includes: - the values of all of its variables - the history of some of its variables - the state of all submodels used in the model. Let us consider a model with a certain number of variables. A loose definition of the state variables of the model would be the set of variables for which the model needs a value from time t1 in order to calculate the new state of the model at time t0.

73 This is what is taken care of automatically by MODELS. Values that need to be carried from the past are automatically made part of the running history of the model, which can include values from the previous step and from earlier steps of the simulation. This is also why there is the possibility of assigning history expressions to a variable or an input, so that values can be found by the program if needed for reference to instants that fall before the start of the simulation of the model. For example, a model needs to have access to the previous value of a variable x when x is used in an expression before a value has been assigned to it at the current execution time. A model also uses the history of variable x whenever a time function is applied to x, such as deriv(x), integral(x), etc, and implicitly in interpolations. The history of x is also used by the program in the implicit value assignments of laplace(y/x), laplace(x/u), and the same for diffeq() and zfun().

74

This section covers the details of using MODELS in ATP. We use the words MODELS section to refer to the section of an ATP data case containing the declarations and directives related to defining and using one or more models in a simulation. All models used in a simulation are defined in the MODELS section. When a model is used as a control-type component, its use is also specified in the MODELS section in a USE statement. When a model is used as a circuit-type component, its use is specified directly in the circuit, using a type-94 nonlinear component. Models can also be used in ATP for performing calculations in the frequency domain, when conducting FREQUENCY SCAN simulations.

When we have one or more models in an ATP data case, we need to define a MODELS section. It is placed before the branch section, if any, and after the TACS section, if any. When we use the MODELS section in conjunction with a circuit, we assemble the data case as follows:

BEGIN NEW DATA CASE ... MODELS INPUT ... OUTPUT ... VAR ... MODEL ... MODEL ... ... USE ... USE ... ... RECORD ... ENDMODELS circuit description ... plotting instructions ... BEGIN NEW DATA CASE BLANK

75

BEGIN NEW DATA CASE ... MODELS STAND ALONE VAR ... MODEL ... MODEL ... ... USE ... USE ... ... RECORD ... ENDMODELS plotting instructions ... BEGIN NEW DATA CASE BLANK

6.1.1. Inputs from ATP Some values can be passed from the circuit to the MODELS section at each time step of the simulation. They are: - the voltage at a node - the current through a switch - the status of a switch - electrical and mechanical quantities from a machine component In addition, other types of values can also be used as inputs to the MODELS section. They are: - variables from the TACS section - values from a PL4 plot file - internal values from the ATP program 6.1.1.1. Inputs from the circuit When we declare an input in the MODELS section, we specify its name, and we describe what value is carries. This is done using the following notation:

INPUT name1 name2 name3 name4 switch name5 name6 { { { { v(nodename) } i(switchname) } imssv(nodename) } imssi(switchname) } ----voltage at a node current through a switch imaginary part of s-s voltage at a node imaginary part of s-s current at a

{ switch(switchname) } { mach(variable) }

For a voltage, we just identify the name of the node. For a current, we identify the switch (the only way to measure a current in ATP) by its branch name, or by the name of a node to which it is connected. We do the same for a switch status.

76 During the simulation, the values of voltages and currents are calculated in the time domain. But in the steady-state phasor solution, both real and imaginary parts of a voltage or current are available. At simulation time t=0, the real part of the complex value is carried in the regular v() and i(), and the imaginary part in imssv() and imssi(). For a machine value, we use the variable names identified in the description of the machine. When the inputs expected by a model are in the form of an array, we declare them as individual input variables in the MODELS section, and we pass them to the model in array form, as illustrated below:

MODELS INPUT va {v(NODEA)} vb {v(NODEB)} vc {v(NODEC)} ... MODEL test INPUT v[1..3] ... ENDMODEL ... USE test AS example INPUT v[1..3] := [va-vb, vb-vc, vc-va] ... -- phase-phase

6.1.1.2. Inputs from a PL4 plot file It is possible to input values from a PL4 file directly into the MODELS section. The connection to the PL4 file is done in 3 steps: 1) before the MODELS section, indicate to ATP that an existing plot file is to be processed:

C --- template for next card. POSTPROCESS PLOT FILE MULPPF 2 LUNPPF 63 L63TYP 3

where: - this is the same request as when using POSTPROCESS PLOT FILE with TACS - MULPPF defines in what multiple the original plot points will be used - 1 means all points will be used, n means every nth point is used - if using a multiple, adjust the time step accordingly to keep the simulation synchronized with the PL4 data - LUNPPF indicates the I/O unit allocated to the connection - if left blank, a default value of 63 is assigned - selecting a different unit may conflict with units already used by ATP

77 - L63TYP indicates the type of formatting of the PL4 file - if left blank, a default value of 1 is assigned - 1=UNFORMATTED, 2=FORMATTED, 3=C-LIKE - UNFORMATTED is the default because it allows use of double precision when preparing the PL4 file using the request CUSTOM PLOT FILE (see the July 1995 issue of Can/Am EMTP News for details) 2) before the MODELS section, open the ATP connection to the existing PL4 file:

$OPEN, UNIT=63 FILE=dc45.pl4

3) in the MODELS section, specify any number of signals from the PL4 file as inputs to MODELS:

INPUT gen {PL4(1)} curr {PL4(2)}

where: - gen and curr are arbitrary input names of the MODELS section - PL4 is the input type - 1, 2, etc indicate the corresponding curve number in the PL4 file The 3rd subcase of benchmark case DC46.DAT illustrates the use of PL4 values as input to the MODELS section:

BEGIN NEW DATA CASE C BENCHMARK DC-46 C 3rd of 3 subcases produces the same solution, but illustrates the new C connection to a plot file from MODELS. Just like with TACS, first line C of plot data at time t=0 is ignored. It is not required to use MODELS C as STAND ALONE, but can also be mixed with solution of a circuit. POSTPROCESS PLOT FILE 2 63 3 $OPEN, UNIT=63 FILE=dc45.pl4 ! { Expected to be C-like (L4BYTE = 1) C deltat tmax .000100 .050 { Note DELTAT is twice that of DC-45, since use every 2nd step C print points connec s-s minmax vary again plot 1 1 0 0 1 -1 0 2 5 5 20 20 50 50 MODELS STAND ALONE INPUT gen {PL4(1)}, curr {PL4(2)} MODEL postprocess_example INPUT voltage, current VAR flux, energy, power, gen_1 INIT integral(voltage) := 0 integral(power) := 0 histdef(voltage) := 0 -- needed for the delay function ENDINIT EXEC flux := integral(voltage) energy := integral(power) power := voltage * current gen_1 := delay(voltage, timestep) ENDEXEC ENDMODEL USE postprocess_example AS test INPUT voltage := gen, current := -curr

78

ENDUSE RECORD gen AS gen test.power AS power test.gen_1 AS gen_1 ENDMODELS BLANK card ending plot cards BEGIN NEW DATA CASE BLANK

6.1.1.3. Inputs from the TACS section It is possible to include both a TACS section and a MODELS section in the same ATP data case. Typically, this allows the use of existing data cases containing a TACS section, while still being able to add one or more models to the data case as needed. We can use the value of any TACS variable as input to the MODELS section. For example, a TACS variable named signal could be used as input to the MODELS section as follows:

INPUT somename {TACS(signal)}

indicating that the TACS variable named signal would be available in the MODELS section under the name somename. When both TACS and MODELS are used in a data case, the TACS section precedes the MODELS section:

BEGIN NEW DATA CASE ... TACS HYBRID ... BLANK card ending TACS section MODELS ... ENDMODELS circuit description ...

During the simulation, the order of execution at each time step is: - circuit solution - TACS section solution - MODELS section solution The following subcase of benchmark case DC30.DAT illustrates the use of TACS variables as input to the MODELS section:

BEGIN NEW DATA CASE C 4th of 4 subcases is the same as the first and the third, except that C it uses both TACS and MODELS. The voltages BUS2 and BUS3 are input to TACS. C VSW is output from TACS and input to MODELS. GRID is output from MODELS. C Compare values at t=0 with 3rd subcase. C deltat tmax xopt copt epsiln tolmat tstart 1.0E-6 3.0E-3

79

C print points connec s-s minmax vary again plot 1 1 0 0 1 -1 5 5 20 20 100 100 TACS HYBRID 1DUMMY +UNITY 1.0 1.0 0.5E-3 90BUS2 90BUS3 99VSW = BUS2 - BUS3 33BUS2 BUS3 VSW BLANK card ends all TACS data C ============================================================================== MODELS INPUT deltav {TACS(vsw)} OUTPUT grid MODEL dc30 INPUT dv VAR grid OUTPUT grid EXEC IF abs(dv)>=1.5e8*t +1e5 THEN grid:=1 ELSE grid:=0 ENDIF ENDEXEC ENDMODEL USE dc30 AS dc30 INPUT dv:=deltav OUTPUT grid:=grid ENDUSE RECORD dc30.dv AS dv ENDMODELS C ============================================================================== GEN BUS1 15. BUS1 2.9 BUS1 BUS2 0.1 BUS2 0.1 BUS3 .017 BUS3 490. BUS2 BUS2R 24.34 BUS3 BUS3R BUS2 BUS2R BLANK card terminates electric network branches BUS2 BUS3 -1. 1.E9 NAME: Valve ! { Request "NAME: " of cols. 3-8 precedes A6 valve name in 9-14 11BUS2R BUS3R 20. GRID 12 BLANK card ends all switches 14GEN 66500. 50. -2.0508 -1. BLANK card terminates electric network sources { No node voltages printout/plotting BLANK card ending node voltage request BLANK card ending plot cards BEGIN NEW DATA CASE BLANK

6.1.1.4. Inputs from ATP program variables Any numerical non-array variables from the ATP program that are accessible to ATP's SPY can also be used as inputs to MODELS. A local name can be specified, along with an indication of the name of the ATP program variable used as input:

INPUT atp_t { ATP(t) } tmax { ATP(tmax) } -- value of ATP variable 't' -- value of ATP variable 'tmax'

80 Another way to have access to internal variable values of the ATP program is to use the special function atp() in an expression inside a model description. This provides the added advantage of being able to also access elements or array variables used in the ATP program, which is not possible in the INPUT declarations of the MODELS section.

MODEL example ... EXEC ... step := atp(istep) estimated_voltage := atp(voltk[2*index]) ... ENDEXEC ENDMODEL -- value of ATP variable 'istep' -- value of element of array 'voltk'

It is also possible to modify the value of internal program variables of ATP, by using the special procedure deposit(). This is discussed in the following section on Outputs to ATP. Following is an example combining illustrations of the atp() input that can be used in the MODELS section, of the special function atp() that can be used in a model, and of the procedure deposit() that can also be used in a model.

BEGIN NEW DATA CASE { ATPVAR.DAT } C deltat tmax xopt copt epsiln tolmat tstart 0.001 0.005 C print points connec s-s minmax vary again plot 1 1 0 0 0 0 0 0 C ============================================================================== MODELS INPUT atp_t {atp(t)} tmax {atp(tmax)} MODEL atpvar VAR step EXEC write('*** e(2) = ', atp(e[2])) write(' e(3) = ', atp(e[3])) step := atp(istep) IF step=4 THEN deposit(tmax, 0.0095) ENDIF ENDEXEC ENDMODEL USE atpvar AS example ENDUSE RECORD atp_t AS t example.step AS istep tmax AS tmax ENDMODELS C ============================================================================== A1 A2 1. A2 1. BLANK card ending electric network branches BLANK card ending switches 14A1 100. 50. -1. BLANK card ending electric network source cards -- get value of ATP variable 't' -- get value of ATP variable 'tmax'

-- write value of ATP variable e(2) -- write value of ATP variable e(3) -- get value of ATP variable 'istep' -- modify value of ATP variable 'tmax'

81

BLANK card ending voltage printout requests BLANK card ending plot requests BEGIN NEW DATA CASE BLANK

6.1.2. Outputs to ATP Any variable declared as output in the MODELS section becomes visible in the circuit, and can be used as control variable to the components of the circuit, everywhere a TACS variable can be used. Applications include controlling the operation of switches, controlling the value of a type-91 resistance and other nonlinear components, controlling the value of voltage and control sources, and controlling the value of internal variables in the machine components The output names are declared using the following notation:

OUTPUT name1 name2 ... -- comment describing the value -- comment describing the value

The names of these outputs are stored and used by ATP, and are therefore limited to the 6-character naming convention of ATP. Also, no arrays can be used, only single outputs. There is a difference between declaring a MODELS variable as output to the circuit, and specifying a variable to be recorded for printout and plotting during the simulation. The latter is done using a RECORD directive, discussed in a separate section below. Variables declared as outputs of the MODELS section are not automatically recorded for printout or plotting, unless they are also included in the RECORD directives of the MODELS section. No modifications have been made to the format rules of ATP branches, switches, sources, and machines regarding the use of control variables from TACS or MODELS. In either case, the keyword TACS used on these cards indicates control variables coming from a "control system" described outside the circuit, using either TACS or MODELS, without distinguishing between the two. Another type of output to ATP can be made directly from inside a model. The deposit() procedure allows a model to modify the value of any numerical program variable of ATP that can be changed using ATP's SPY command DEPOSIT. The ATP documentation of the SPY commands describes what variables can be modified. The deposit() procedure can be used to modify the value of single variables and of single or multiple elements of array variables of the ATP program, using the following notation: DEPOSIT( name, value ) DEPOSIT( name[ expr ] , value ) DEPOSIT( name[ expr .. expr ] , value )

82 where name is the name of a program variable accessible from SPY, and where the index of the array elements can be specified using regular expressions. An illustration is included in the example used in the previous section.

6.1.3. Variables in the MODELS section In addition to the input and output variables that can be declared in the MODELS section, it is possible to define internal variables that can be used for passing values between the models used in the MODELS section. They are named and declared as variables using the following notation:

VAR name1 name2 ... -- comment describing the variable -- comment describing the variable

The names of these variables are stored and used by ATP, and are therefore limited to the 6-character naming convention of ATP. Also, no array variables can be used, only single variables. Values are assigned to these variables in the USE statements of the MODELS section, on the left-hand side of the output assignments, receiving values from the outputs of the used models. Note that the outputs of the MODELS section can also be used for the same purpose as the variables.

6.1.4. RECORD for printout/plotting Any value-holding element existing in MODELS can be added to the printout/plotting list of ATP, by using a RECORD directive. Each RECORD identifies an element by specifying its path-name in MODELS, and by specifying a 1- to 6-character label to be used by ATP in the printout heading, for example:

RECORD controller_A.control AS ctrl RECORD top.subuse.field AS field1 RECORD source1 AS src1 RECORD SRCE__CT1___LIMR__.r AS rs

The first example adds to the printout list, identified in the list as "MODELS CTRL", the value of an element named control, from a model used at the top level of the MODELS section with the instance name controller_A. The second example adds to the printout list, identified as "MODELS - FIELD1", the variable field from a model used as subuse in a model with instance name top. The third example adds to the printout list, idendified as "MODELS - SRC1", the element named source1 defined as a variable or input or output of the MODELS section. Note that no instance name is needed in the path, because the element source1 exists at the top level of the MODELS section, outside of any model instance.

USERS GUIDE TO MODELS IN ATP

83 The fourth example adds to the printout list, with the label "MODELS - RS", the element named r from the model named limr used by a type-94 component connected to the circuit between nodes SRCE and CT1. Non-existing instance names found in a record path don't trigger an error, because an instance name starts its existence only at the instant of the simulation when the associated instance of the model is first used, which is not necessarily at the initial time of the simulation. It is therefore not an error for the program to not find a given instance name, as it may simply not have been yet created in the simulation. The only way to provide a clear indication that the record has an undefined value would be to be able to assign it the value "undefined", something like minus zero. And of course we cannot use the undefined value from MODELS (=88888.88888) because it would affect the scale limits of a plot if we used that value until the time an actual value starts being assigned to the variable.

6.1.5. Model descriptions All models used in a simulation must be described in the MODELS section of a data case. This includes models used from a USE statement in the MODELS section, as well as models used from a type-94 circuit component. The $INCLUDE command of ATP can also be used to refer to a file containing a model description, instead of including the full text of the model in the data case. The example illustrating variables of the MODELS section, above, could be rewritten in a more simple way using an $INCLUDE command:

MODELS INPUT atp_t {atp(t)} tmax {atp(tmax)} $INCLUDE atpvar.m -- get value of ATP variable 't' -- get value of ATP variable 'tmax'

USE atpvar AS example ENDUSE RECORD atp_t AS t example.step AS istep tmax AS tmax ENDMODELS

Just as foreign models can be declared inside a model (see Foreign submodels), they can also be declared at the top level of the MODELS section. The notation is identical to when a foreign model is declared inside a regular model. Here is an example:

BEGIN NEW DATA CASE C deltat tmax xopt copt epsiln tolmat tstart 1. 10. C print points connec s-s minmax vary again plot 1 1 0 0 0 0 0 0 C ============================================================================== MODELS STAND ALONE

84

VAR a1, a2, a3 MODEL ftnmodel FOREIGN sample_model {ixdata:1, ixin:3, ixout:3, ixvar:3} USE ftnmodel AS example DATA xdata[1]:=3 -- set value of xdata[1] INPUT xin[1..3]:=[t, t+1, t+2] -- load inputs xin[1], xin[2], xin[3] HISTORY xvar[1..3]:=0 -- set history of xvar[..] OUTPUT a1:=xout[1], a2:=xout[2], a3:=xout[3] ENDUSE RECORD example.xdata[1] AS xdata1 example.xin[1] AS xin1 example.xvar[1] AS xvar1 -- its value after each execution a1 AS xout1 ENDMODELS C ============================================================================== BLANK card ending plot requests BEGIN NEW DATA CASE BLANK

In this example, three variables are defined, a1, a2, a3. The foreign model is declared. One instance of that model is used, identified with the instance name example. Various values are then recorded during the simulation in the printout/plotting list of ATP. To use our own Fortran or C code with ATP, we must link our program with ATP. The details of this process are dependent on the platform on which we are running ATP. Typically, we must use the same compiler that the rest of our version of ATP was compiled on. Then we have to link our compiled file with the compiled files of ATP using a linker compatible with the compiler(s) that we have used. For example, for the Salford version of ATP, we can use the Salford Fortran, C, or Pascal compilers for our routines, and the Salford linker. It also means that we need all the compiled files of ATP in order to be able to relink them with the additional files that we create.

6.1.6. MODELS formatting vs. ATP formatting MODELS has syntax rules separate from the formatting rules of ATP. Among other things, it allows the insertion of white space (space characters, tabs, carriage returns, blank lines) anywhere in the text of a model and in the MODELS section of a data case. There is no need to start blank lines in the MODELS section with the C-in-column-one format used for indicating comment lines in the rest of ATP. Even if the "C "-formatted ATP comments can be used in the MODELS section without producing a syntax error, their use is not encouraged for two reasons. One is simply style, as they really don't belong to the MODELS language. The other reason is that a model written with this type of comment lines would not be compatible with other versions of MODELS used outside of ATP.

85

When we access a model with a USE statement in the MODELS section, the model instance that we create interacts with the circuit as a control component. This is to be compared to the circuit approach available when using a model with the type-94 circuit element (see a separate section below). The control-type component receives measurements from the circuit (the inputs), and sends back control signals (the outputs) to be used in the circuit. In this mode, ATP performs no iteration. The control signals are simply applied to the operation of the circuit at the next time step of the simulation. This is the mode of operation that was also available between the circuit and TACS. When used for representing true control components, this decoupling, and its one-step delay, are not a limitation, as any physical control component will include transmission delays in its operation. This approach can also be used without problem for representing passive circuit elements in the form of a Norton equivalent, where the value of the equivalent current source, if present, is calculated using values of voltages and currents already delayed by one or more time steps (see the representation of inductance, capacitance, and transmission lines in ATP). This forced decoupling will create numerical stability problems when used for representing circuit components that should be solved simultaneously with the rest of the circuit. This includes any component for which a Norton equivalent would use concurrent (as opposed to delayed) values of voltages or currents to calculate the value of the equivalent source (for example, any type of voltage- or current-driven voltage source or current source). In this case, it is necessary to use a type-94 Thevenin or iterated circuit element to connect the model representing the operation of the component. The USE statement available in the MODELS section lets us use all features of the USE statement available inside a regular model (see the section on the Use statement). This includes assigning data and input values, retrieving output values, and specifying history expressions, range of time step, input interpolation methods, and delay cells storage size. Here is an example where models are used from USE statements in the MODELS section. The complete data case represents a circuit that uses three models to describe the operation of a variable source, a variable current-limiting resistance, and a variable load.

86

BEGIN NEW DATA CASE { LIMR-USE.DAT } C deltat tmax xopt copt epsiln tolmat tstart 5.E-5 0.16 C print points connec s-s minmax vary again plot 100 1 0 0 0 0 0 1 C ============================================================================== MODELS INPUT vmeas {v(CT1)} -- load voltage measured at node CT1 OUTPUT srce -- source driving voltage rs -- limiting resistance rl -- load resistance $INCLUDE vs.m { inserts model source_voltage $INCLUDE limr-use.m { inserts model limr $INCLUDE resist.m { inserts model variable_resistance USE source_voltage AS source DATA vrms := 100 -- [ V ] freq := 60 -- [ Hz] OUTPUT srce := vs -- [ V ] ENDUSE USE limr AS rs DATA rsmin := 1.0 -- [ohm] ilim := 20 -- [ A ] INPUT v := srce - vmeas OUTPUT rs := r ENDUSE source rms voltage source frequency source driving voltage

ENDMODELS C ============================================================================== 91SRCE CT1 TACS RS { Variable limiting resistance CT2 LOAD 0.1 0.2 { Fixed load R-L 91LOAD TACS RL { Variable load resistance BLANK card ending branches ----------------------------------------------------CT1 CT2 MEASURING 1 BLANK card ending switches ----------------------------------------------------60SRCE { Source driving voltage BLANK card ending sources -----------------------------------------------------SRCE CT1

87

BLANK card ending voltage printout request ------------------------------------BLANK card ending plot --------------------------------------------------------BEGIN NEW DATA CASE BLANK

The included file LIMR-USE.M contains the description of the limiting resistance model, as follows:

MODEL limr -- limiting resistance DATA rsmin -- [ohm] min resistance ilim -- [ A ] max current INPUT v -- [ V ] voltage across terminals VAR r -- [ohm] resistance OUTPUT r EXEC r := abs(v)/ilim {min: rsmin} ENDEXEC ENDMODEL

The operation of that model is described in its one-line EXEC procedure, where the resistance is first calculated to create a current equal to ilim, and is then limited to be no less than the value specified by rsmin. For comparison, a version of this circuit is shown using a type-94 component, in the section below.

In ATP, the type-94 nonlinear component is a user-defined multi-branch circuit component. The operation of the component is completely described by the user in a model, placed in the MODELS section of the data case, and used not by a USE statement, but by a type-94 component in the circuit. This model can be written as a native model using the MODELS language, or it can call a foreign model using other programming languages. The type-94 component can be used in three different modes: Thevenin, iterated, and Norton. In each case, the interface with the circuit is a true electrical connection defined in terms of the voltages and currents of the data case. Each one can be used for representing multi-branch nonlinear circuit elements, with or without associated controls. The solution of the Thevenin and the iterated modes is simultaneous with the solution of the rest of the circuit, without any time delay. The solution of the Norton uses the control-type approach, with a one-step delay. The following example is the same data case as shown in the previous section, except that the limiting resistance model is used as a circuit component (type-94) instead of being used as a control component called from a USE statement.

BEGIN NEW DATA CASE C deltat tmax xopt 5.E-5 0.16 { LIMR-94.DAT } copt epsiln tolmat tstart

88

C print points connec s-s minmax vary again plot 100 1 0 0 0 0 0 1 C ============================================================================== MODELS OUTPUT srce -- source driving voltage rl -- load resistance $INCLUDE vs.m { inserts model source_voltage $INCLUDE limr-94.m { inserts type-94 model limr $INCLUDE resist.m { inserts model variable_resistance USE source_voltage AS source DATA vrms := 100 -- [ V ] freq := 60 -- [ Hz] OUTPUT srce := vs -- [ V ] ENDUSE USE variable_resistance AS res OUTPUT rl := r -- [ohm] ENDUSE RECORD rl AS rl SRCE__CT1___LIMR__.r AS rs ENDMODELS C ============================= Electrical circuit ============================= 94SRCE CT1 LIMR ITER { Variable limiting resistance >DATA RSMIN 1. >DATA ILIM 20. >END CT2 LOAD 0.1 0.2 { Fixed load R-L 91LOAD TACS RL { Variable load resistance BLANK card ending branches ----------------------------------------------------CT1 CT2 MEASURING 1 BLANK card ending switches ----------------------------------------------------60SRCE { Source driving voltage BLANK card ending sources -----------------------------------------------------SRCE CT1 BLANK card ending voltage printout request ------------------------------------BLANK card ending plot --------------------------------------------------------BEGIN NEW DATA CASE BLANK source rms voltage source frequency source driving voltage

The included file LIMR-94.M contains the description of the limiting resistance model, as follows:

89

MODEL limr -- limiting resistance -- Fixed declarations for a type-94 iterated model ---------------------------DATA n -- number of node pairs n2 {dflt: n*n} -- number of matrix elements INPUT v -- guessed voltage across terminals 1-2 v0 -- steady-state voltage across terminals 1-2 i0 -- steady-state current into terminal 1 VAR i -- calculated current into terminal 1 didv -- calculated conductance 1-2 OUTPUT i, didv -- Local declarations --------------------------------------------------------DATA rsmin -- [ohm] min resistance ilim -- [ A ] max current VAR r -- [ohm] resistance EXEC r := abs(v)/ilim {min: rsmin} IF r>rsmin -- if the current is at the limit THEN didv := 0 ELSE didv := 1/r ENDIF i := v/r ENDEXEC ENDMODEL

6.3.1. Thevenin, iterated, and Norton What follows is a comparison between the three different modes of the type-94 circuit component: Thevenin type-94 input Thevenin voltage source behind Thevenin equivalent resistance or admittance of the network seen from the component; if multi-branch, Thevenin source is a vector, Thevenin resistance is a matrix; value of branch current from the component; if multibranch, current is a vector;

output

implementation uses the compensation interface of ATP usage solution assurance speed restricted to one nonlinear component per subnetwork numerical solution is assured (no iteration between ATP and the type-94 component) faster than iterated, because no iteration is needed; slower than Norton, because a Thevenin equivalent must be calculated

Iterated type-94 input most-recent branch voltage value calculated by ATP; if multi-branch, uses a vector of voltages;

90 output branch current and branch di/dv calculated by the model; if multi-branch, current is a vector, [i/v] is a matrix;

implementation uses the iteration mechanism of ATP usage solution assurance no restriction on how many are used the ATP iterated solution is not guaranteed to converge (especially if any of the iterated components are allowed to have oscillating step discontinuities in their operating point during an iteration - but this could be restricted by the model's logic) possibly slower overall execution than Thevenin if many iterations are required at each time step due either to the interaction between many iterated nonlinear components, or to discontinuities in any of the nonlinear components; may be possible to use larger step size to compensate;

speed

Norton type-94 non-transmission input output left node voltage at time t; vector if multi-node; right node is not used; Norton equivalent of the component, as seen from the electrical circuit, in the form of a current source in parallel with the equivalent admittance of the component; if multinode, current source is a vector, admittance is a matrix; values of current source and admittance are predicted for next time step - is similar to presently using a combination of a type-60 controlled current source in parallel with a type-51 controlled resistance, except that it is extended to a matrix form; - the solution of this component is not simultaneous with that of the circuit (a delay of one time step is introduced between input and output)

91 usage - where the operating point of the component can be easily predicted with sufficient accuracy from one time step to the next (for example when the operating point of the component changes more slowly than the operating point of the rest of the circuit) - where the exact timing of the operating point of the component is not critical to the operation of the rest of the circuit (for example when representing something with an element of randomness, like the state of an arc) - where the component is not a current-controlled or voltage-controlled voltage source or current source that would need to be solved simultaneously with the circuit solution assurance the ATP solution is always assured (the equivalent circuit of the component is linear); numerical instability can be expected when the represented element is not a passive circuit element; faster execution than both Thevenin and iterated, because the component is represented directly in the nodal admittance matrix of the circuit (it's not treated as an exception to the circuit); slower execution when admittance varies often during the simulation, requiring a retriangularization of the full admittance matrix of the ATP circuit at each change

speed

Norton type-94 with transmission input left node voltage and right node voltage at time t; vectors if multi-node; the two sides are decoupled by the component; the component represents a transmission element (cable or line); two Norton equivalents of the component, as seen from the electrical circuit on each side, in the form of a current source in parallel with the equivalent admittance of the component; if multi-node, current source is a vector, admittance is a matrix; values of current source and admittance are predicted for next time step

output

implementation same as for the non-transmission type; allows to separate each side into a different subnetwork, just like a regular transmission line component usage used where the component operates as a transmission device;

92

6.3.2. Initializing the type-94 component The type-94 component is not included in the steady-state initialization of the ATP circuit at t=0. As for other nonlinear elements used in a circuit, a temporary equivalent linear circuit can be used for representing the component in the steady-state circuit solution. This provides us with representative values of voltages and currents at the component, values that we can use to initialize the operating point of the corresponding model when it is first called for execution. In the case of the Thevenin and the iterated types, the model is not called until the circuit solution is already under way at the first time step of the simulation. The pre-defined inputs v0[1..n] and i0[1..n] carry the values of voltages and currents measured at the end of the steady-state solution, which can be used to initialize the model. In the case of the Norton type, the model is called for the first time at time t=0 immediately after the steady-state solution, but before the circuit solution at the first time step. This gives us a chance to initialize not only the model, but also the values of the Norton equivalent that will be used in the circuit at the next time step, which in this case will be the first time step. Here again, the pre-defined inputs v0[1..n] and i0[1..n] carry the values of voltages and currents measured at the end of the steady-state solution, and can be used in a special section of the EXEC procedure, executed only at time t=0, to properly operate the model. To illustrate this last point, compare below the INIT and EXEC procedures of a simple model representing a constant inductance, built first as a type-94 Thevenin, and next at a type-94 Norton. Notice where the steady-state measured values of v0 and i0 are used: Thevenin:

INIT L := L1 -- initialize variable inductance value histdef(v) := v0 histdef(i) := i0 ENDINIT EXEC COMBINE AS group1 CLAPLACE(i/v) := (1|s0)/(L|s1) v := sum(vth| -rth|i) ENDCOMBINE ENDEXEC

93 Norton:

INIT st:= 2/timestep L := L1 g := 1/(st*L) ENDINIT EXEC IF t=0 flag i is ELSE flag i is ENDIF ENDEXEC -- trapezoidal rule conversion from Laplace -- initialize variable inductance value -- conductance converted from Laplace 1/sL

-- conductance values have been changed -- t=0 current through L -- history term for next step -- reset flag, no more change in g -- applying trapezoidal rule, calculate from v(t) -- history term from trapezoidal rule, for next step

6.3.3. Foreign models with a type-94 The type-94 component automatically calls the specified model at each time step of the simulation. That model describes how the component operates during the simulation. This operation can be described locally in the model itself, or can be programmed in a foreign model called by that model. This provides a way to represent the operation of a circuit component in ATP using a set of subroutines or procedures written as a separate program. They can be written in any programming language that can be linked with ATP on the used platform. The foreign programs are connected to ATP using the simple foreign interface of MODELS, in terms of data, input, output, and initial conditions. (See the section on Foreign submodels).

It is possible to include a MODELS section to be used with the FREQUENCY SCAN operation of ATP. At each frequency step, the value of the frequency is passed to MODELS, carried using the variable t. This may seem odd at first look, until one considers that this trick provides built-in access to derivatives and integrals of values with respect to frequency, instead of with respect to time. This is illustrated in the example below. For instance: - timestep holds the step in frequency between the previous frequency (now prevtime) and the present frequency (now t); - deriv(y) calculates the derivative of y with respect to frequency - integral(y) calculates the integral of y with respect to frequency - prevval(y) returns the value of y at the previous frequency step - predval(y, f1) returns the predicted value of y at frequency f1

94 - diffeq(a0|D0 +a1|D1 +...) | y := x calculates the value of y from a differential equation expressed in terms of the frequency, i.e. a0*y + a1*(dy/df) + a2*(d2y/df2) + ... = x - laplace(y/x) doesn't make any sense in this context

BEGIN NEW DATA CASE C BENCHMARK DC-52 with addition of a model and its use FREQUENCY SCAN, 1.0, 0.0, 15., 2, 1.0 0.0 1 1 1 1 { Note request for phasor branch flows C ============================================================================== MODELS INPUT v_Re_swit v_Im_swit v_Re_load v_Im_load i_Re_swit i_Im_swit state_swit {v(swit)} {imssv(swit)} {v(load)} {imssv(load)} {i(swit)} {imssi(swit)} {switch(swit)} -------real part of voltage imag part of voltage real part of voltage imag part of voltage real part of current imag part of current state of switch SWIT at node SWIT at node SWIT at node LOAD at node LOAD at switch SWIT at switch SWIT (0=open, 1=closed)

MODEL m1 ----------------------------------------------------------------------VAR pass INPUT v_Re_1 {dflt: 0} v_Im_1 {dflt: 0} v_Re_2 {dflt: 0} v_Im_2 {dflt: 0} i_Re_1 {dflt: 0} i_Im_1 {dflt: 0} state_1 {dflt: 0} INIT pass:=0 ENDINIT -- to verify that its value is kept between passes -- to verify that all types of inputs are -accessed correctly -(machine quantities are not tested here)

EXEC pass:=pass+1 write('************** In models, pass= ', pass) write(' freq= ', t) write(' Re{v1}, Im{v1} = ', v_Re_1, ', ', v_Im_1 write(' Re{v2}, Im{v2} = ', v_Re_2, ', ', v_Im_2 write(' Re{i1}, Im{i1} = ', i_Re_1, ', ', i_Im_1 write(' state_1 = ', state_1 ) ENDEXEC ENDMODEL

-) ) )

<<===

<<====

USE m1 as m1 INPUT v_Re_1 := v_Re_swit v_Im_1 := v_Im_swit v_Re_2 := v_Re_load v_Im_2 := v_Im_load i_Re_1 := i_Re_swit i_Im_1 := i_Im_swit state_1 := state_swit ENDUSE ENDMODELS C Begin branches =============================================================== SWIT LOAD 10. LOAD 1000. -1SWIT OPEN .3055 5.82 .012 138. BLANK card ending all branches GEN SWIT -1. BLANK card ending all switch cards 14GEN 1.0 0.5 -1. BLANK card ending source cards

95

GEN LOAD BLANK card ends output requests (just node voltages, for FREQUENCY SCAN) 197 .2 0.0 1.6 -20. 60.LOAD angle BLANK card ending plot cards BEGIN NEW DATA CASE BLANK

The ac steady-state initialization of the electrical circuit in ATP is performed on a linearized circuit driven by one or more sinusoidal sources. All nonlinear components are ignored by the electrical side of ATP for that initial steady-state solution (which is done using phasor algebra, superposing sources at different frequencies, if any). Two aspects of the initialization process must be considered: 1) what is considered "nonlinear" 2) what is considered to be in "steady-state" In ATP parlance, anything that cannot be represented by a linear expression in the frequency domain is considered "nonlinear" for initialization. Components and control systems represented using TACS and MODELS certainly qualify as nonlinear in this regard, even if in some rare cases a linear or linearized analytical representation of the component could be derived from the component's description. A common technique used by ATP users is to create a linear equivalent of a nonlinear component only for the purpose of initialization, and then disconnect that equivalent circuit from the rest of the circuit by means of switches opening before the first time step of the simulation. Of course, determining the correct operating point of the nonlinear element around which the equivalent circuit is to be linearized is the difficult part. Often the user will choose to start a simulation from a more simple state for which the operating point of the various nonlinear elements are more completely known, and then let the first part of the simulation bring the circuit to a more elaborate state from which, in a second part, the transient behavior of interest can be initiated and observed. The AC steady-state solution of ATP is driven by sinusoidal sources at one or more frequencies (representing DC sources as sinusoidal sources with a very small frequency). The user is required to provide (and therefore to know before doing the simulation) the amplitude and frequency of these signal or power sources. The approaches commonly used are similar to the approaches shown above. Equivalent sources can be used for the initialization and then disconnected and replaced by the real sources as soon as the simulation begins. And the initialization can be done using simplified frequency representation of the sources, letting the simulation bring the circuit to a more complex frequency contents in the first part of the simulation, from which the transient behavior can then be initiated. To initialize a component described outside the electrical circuit, we likely would use a combination of both aspects described above, in the form of an equivalent

USERS GUIDE TO MODELS IN ATP

96 source behind an equivalent impedance, with values obtained from a known operating point, and then let the simulation build the operation of the circuit to a more complete frequency contents, from which we can then initiate the transient behavior we want to study. The better the initial approximation, of course, the shorter becomes the first stabilizing part of the simulation, but also the more specific it becomes. The decisions we have to make in this iterative process in order to reach a satisfactory starting point will, if anything, make us more aware of the sensitivity of the components we are modeling with respect to the conditions of their operation. One more practical point. Models used in the MODELS section with a USE statement are updated at each time step of the simulation after the solution of the electrical circuit by ATP at that time step. This is also true at time zero of the initialization. The steady-state solution of the circuit is done first, then the USE statements are executed for the first time at t=0. Using inputs such as the real and imaginary part of currents and voltages of the circuit gives us the possibility to take into account the steady-state solution of the circuit when initializing the operating point of the models.

Two dimensions in the file LISTSIZE.DAT control the size of the storage area reserved for MODELS in ATP. list 15: character storage -- needs about 2000 + size of MODELS section list 28: numerical storage -- integer and real storage of simulation The user has control on the size of these lists in the file LISTSIZE.DAT, up to their maximum dimension. In the regular version of ATP, these maxima are 64800 and 126000 respectively. Users requiring storage larger than this must obtain a version of ATP dimensioned with larger values. Getting error messages that do not make any sense when using MODELS may indicate a storage problem. Most cases of memory overflow are reported with the correct error message, but some cases will create a problem in another area before being detected correctly.

97

Most modeling projects involve creating and using a set of basic components, that can also possibly be re-used in other projects. Using this approach, assembling a simulation can be reduced to a task of providing the framework and the logical glue for the use of components gathered out of one's developed toolkit. What follows is meant to be used as a starting point for building a library of various models, functions, and components needed in the simulation projects that one can consider doing.

Simple signal sources can often be described by a single logical and/or numerical equation. Using a statement function to express this equation is then the easiest way to create such sources. For example, a cosine source with variable amplitude, frequency, and phase angle can be represented as:

FUNCTION cos_source(a,f,p):= a*cos(2*pi*f*t +rad(p))

or, in fact, doesn't even need a function, because the expression is simple enough that it can be inserted explicitly in full wherever it needs to be used. However, a less obvious formulation, like that of the triangular waveform below, is better described only once in a function definition, and then used as a function call when it's needed. The use of a function is possible when the representation of the source is stateless, that is, doesn't carry history between the times when it is called. When history is carried, then we need to use a model for describing the operation of the signal source. Included below are a few commonly-used signal sources. For those examples, if turn-on and turn-off times need to be added, this can be easily done on the outside of the function definition. For example, to have a source operating between t>=t_on and t<t_off, one would use ramp_train(), for example, as:

signal := (t >= ... AND t < ...)*ramp_train(100, 1e-4, 0)

where the value of the logical expression is taken as numerical "1" when the expression is true, and zero otherwise, multiplied by the rest of the expression.

7.1.1. Examples of some common sources The first function is a simple one-shot pulse of specified amplitude, width, and starting time. This is an example where using a function does not present much of an advantage over using the expression directly.

USERS GUIDE TO MODELS IN ATP

98

FUNCTION single_pulse(ampl, width, tstart) := ampl*(t>=tstart AND t<tstart+width) comment --------------------------------------------| ampl : [ ] on-value of pulse (off-value is 0) | | width : [s] width of pulse | | tstart : [s] pulse start time | | pulse starts at t=tstart and lasts "width" seconds | ------------------------------------------ endcomment

Refer to the sample model "test_sources" below to see how this and the following functions can be used. The next example is simplified when using a function call. It is easier to call the function with its four arguments, than to have to figure out how to use the modulo operator each time the signal needs to be generated. The function generates a sequence of pulses of a specified amplitude, width, and period, with the beginning of the reference period (the phase, in seconds) shifted to a specified time:

FUNCTION pulse_train(ampl, width, period, tshift) := ampl*(((t-tshift+period) MOD period) < width) comment --------------------------------------------------| ampl : [ ] on-value of each pulse (off-value is 0) | | width : [s] width of each pulse | | period : [s] period of each pulse (on_time + off_time) | | tshift : [s] period shift time | | the beginning of the period is shifted by "tshift" sec | | each pulse is on for "width" seconds | | pulses are repeated every "period" seconds | ------------------------------------------------ endcomment

The next function shows a simple ramp of specified maximum amplitude and width, starting at a specified starting time:

FUNCTION single_ramp(ampl, width, tstart) := ampl/width*(t-tstart)*(t>=tstart AND t<tstart+width) comment -------------------------------------------| ampl : [ ] amplitude of ramp | | width : [s] width of ramp | | tstart : [s] ramp start time | | ramp starts at t=tstart and lasts "width" seconds | ----------------------------------------- endcomment

The next function generates a train of ramps of specified amplitude and width, with the beginning of the reference period (the phase, in seconds) shifted to a specified time. In this example, there is no dead zone, and the period is equal to the width:

FUNCTION ramp_train(ampl, width, tshift) := ampl/width*((t-tshift+width) MOD width) comment --------------------------------------------------| ampl : [ ] amplitude of ramp | | width : [s] widthor period of each ramp | | tshift : [s] period shift time | | the beginning of the period is shifted by "tshift" sec | | each ramp is on for "width" seconds | | ramps are repeated every "width" seconds | ------------------------------------------------ endcomment

99 The next function generates a triangular wave of specified amplitude and period, in phase with a cosine shifted to a specified time. The value of the third argument is calculated once when calling the function, and is used many times inside the function. That value is specified as the expression: (t - tshift + period) MOD period using values for a specified period and shift time.

FUNCTION triang(ampl, per, tmodT) := ampl*4/per*((tmodT/per<0.5)*(-tmodT+0.25*per) +(tmodT/per>=0.5)*(tmodT-0.75*per)) comment -----------------------------------------------------------| ampl : [ ] amplitude of triangular waveform | | per : [s] period of waveform | | tmodT : [s] pre-calculated value of (t-tshift+period) MOD period | | where tshift : [s] period shift time | | the beginning of the period is shifted by "tshift" sec | | value at start of period is positive maximum, like cosine | --------------------------------------------------------- endcomment

7.1.2. Sample data case The following model illustrates how the above signal source functions can be used in a model. The $INCLUDE directive refers to a file named "sources.lib". It is useful to use a file to store the definition of the functions we need most often. Even if the file (a library) contains more functions than we need to use in a data case, it is not costly to include the whole file. The only cost is reading and storing the contents of the file once at the beginning of the simulation. Then, the program uses only the functions needed during the simulation.

BEGIN NEW DATA CASE { SOURCES.DAT } C deltat tmax xopt copt epsiln tolmat tstart 0.01 2.0 C print points connec s-s minmax vary again plot 1 1 1 C ============================================================================== MODELS STAND ALONE ------------------------------------------------------------- Model definitions: MODEL test_sources $LISTOFF $INCLUDE sources.lib $LISTON VAR pulse, pulsetrain, ramp, ramptrain, tri EXEC -- using single_pulse( ampl, width, tstart ) pulse := single_pulse( 100, 0.4, 0.4 ) -- using pulse_train( ampl, width, period, tshift ) pulsetrain := pulse_train( 100, 0.4, 0.6, 0.4 ) -- using single_ramp( ampl, width, tstart ) ramp := single_ramp( 100, 0.4, 0.4 ) -- using ramp_train( ampl, width, tshift ) ramptrain := ramp_train( 100, 0.6, 0.4 ) -- using triang( ampl, period, tmodT ) tri := triang( 100, 0.6, (t-0.4+0.6) mod 0.6 ) ENDEXEC

100

ENDMODEL -------------------------------------------------------------------- Model uses: USE test_sources AS test ENDUSE ----------------------------------------------------- Printed/plotted variables: RECORD test.pulse AS pulse test.pulsetrain AS pulset test.ramp AS ramp test.ramptrain AS rampt test.tri AS tri ENDMODELS C ============================================================================== BLANK card ending plot requests BEGIN NEW DATA CASE BLANK

A complex number can be represented: - as a pair of rectangular coordinates (real part, imaginary part) - as a pair of polar coordinates (magnitude, angle) In either case, the representation can be held in a 2-element vector. Because functions can return an array of values, we can use functions to define the 2-element array arithmetic of complex numbers. The following is a library of ready-to-use functions covering the basic operations we can apply to complex numbers. These functions would normally be kept in a separate file, and included together in a model when needed.

7.2.1. Examples of complex-value functions The first set of functions shows the basic operations on complex numbers expressed in rectangular coordinates. As can be seen, this representation works well for addition and subtraction, but is costly for multiplication and especially for division:

comment --------------------------------------------------------------| operations on complex numbers using rectangular coordinates | | where a[1..2]=[ar,ai]: ar=real part of A, ai=imaginary part of A | | and b[1..2]=[br,bi]: br=real part of B, bi=imaginary part of B | | | | complex rectangular addition, subtraction, multiplication, division | | note: complex rectangular addition and subtraction can also be | | done directly using a[1..2]+b[1..2] and a[1..2]-b[1..2] | | without having to call any function | ------------------------------------------------------------ endcomment FUNCTION FUNCTION FUNCTION FUNCTION cr_add(ar,ai,br,bi) cr_sub(ar,ai,br,bi) cr_mul(ar,ai,br,bi) cr_div(ar,ai,br,bi) := := := := [ar+br, ai+bi] [ar-br, ai-bi] [ar*br-ai*bi, ar*bi+ai*br] [ar*br+ai*bi, ai*br-ar*bi]*recip(br*br-bi*bi)

101 The next group of functions shows multiplication and division of complex numbers expressed in polar coordinates. It also shows how easily the power and root operations can be expressed:

comment --------------------------------------------------------------| operations on complex numbers using polar coordinates | | where a[1..2]=[am,aa]: am=magnitude of A, aa=angle of A in radians | | and b[1..2]=[bm,ba]: bm=magnitude of B, ba=angle of B in radians | | | | complex polar multiplication, division, powern, rootn | ------------------------------------------------------------ endcomment FUNCTION FUNCTION FUNCTION FUNCTION cp_mul(am,aa,bm,ba) cp_div(am,aa,bm,ba) cp_powern(n,am,aa) cp_rootn(n,am,aa) := := := := [am*bm, aa+ba] [am/bm, aa-ba] [am**n, n*aa] [am**(1/n), aa/n]

The following pair of functions provide conversions between rectangular and polar coordinates:

comment -----------------------------------------------------------------| conversion between rectangular and polar coordinates of complex numbers | | where a[1..2]=[am,aa]: am=magnitude of A, aa=angle of A in radians | | and b[1..2]=[br,bi]: br=real part of B, bi=imaginary part of B | --------------------------------------------------------------- endcomment FUNCTION cpr_conv(am,aa) := [am*cos(aa), am*sin(aa)] FUNCTION crp_conv(br,bi) := [norm(br,bi), atan2(bi,br)]

These functions are ready to be used in a model. For example, given the real variable r, and the array variables c, d, e, f, where: c[1..2] d[1..2] e[1..2] f[1..2] with c[1] = real part, with d[1] = real part, c[2] = imaginary part d[2] = imaginary part

with e[1] = magnitude, e[2] = angle in radians with f[1] = magnitude, f[2] = angle in radians

we can represent the following operations: c+r c+d c-d r*c c*d c/r c/d e*f y[1..2] := c[1..2] + [r, 0] y[1..2] := cr_add(c[1..2], d[1..2]) or := c[1..2] + d[1..2] y[1..2] := cr_sub(c[1..2], d[1..2]) or := c[1..2] - d[1..2] y[1..2] := r * c[1..2] y[1..2] := cr_mul(c[1..2], d[1..2]) y[1..2] := c[1..2] / r y[1..2] := cr_div(c[1..2], d[1..2]) y[1..2] := cp_mul(e[1..2], f[1..2])

102 e/f e ** n e root n polar to rect rect to polar y[1..2] := cp_div(e[1..2], f[1..2]) y[1..2] := cp_powern(n, e[1..2]) y[1..2] := cp_rootn(n, e[1..2]) y[1..2] := cpr_conv(e[1..2]) y[1..2] := crp_conv(c[1..2])

7.2.2. Sample data case The following example illustrates how some of the above complex functions can be applied in a model. A file named "complex.lib", containing these functions, is inserted in the model. It contains the function declarations, as shown in the above section:

BEGIN NEW DATA CASE { COMPLEX.DAT } C deltat tmax xopt copt epsiln tolmat tstart 0.001 0.02 C print points connec s-s minmax vary again plot 1 1 1 C ============================================================================== MODELS STAND ALONE ------------------------------------------------------------- Model definitions: MODEL test_complex $LISTOFF $INCLUDE complex.lib $LISTON DATA c[1..2] -- complex number in rectangular form e[1..2] -- complex number in polar form omega VAR x[1..2], y[1..2], z[1..2] -- complex variables EXEC x[1..2]:=crp_conv(2*c[1..2]) -- = [10, 0.927 rad] y[1..2]:=cpr_conv(e[1..2])-[0,sqrt(3)] -- = [1, 0] z[1..2]:=cpr_conv([100, omega*t]) -- z[1]=100*cos(omega*t) ENDEXEC ENDMODEL -------------------------------------------------------------------- Model uses: USE test_complex AS test DATA c[1..2]:=[3, 4] -- real part=3, imaginary part=4 e[1..2]:=[2, rad(60)] -- magnitude=2, angle=60 degrees omega:=2*pi*50 ENDUSE ----------------------------------------------------- Printed/plotted variables: RECORD test.x[1] AS xmag test.x[2] AS xang test.y[1] AS yreal test.y[2] AS yimag test.z[1] AS cosine ENDMODELS C ============================================================================== BLANK card ending plot requests BEGIN NEW DATA CASE BLANK

103

The control system devices available in TACS can also be described using MODELS. Some can be expressed using nothing more than an expression. Others need their operation expressed using a more elaborate algorithm. Together, they illustrate a good cross-section of the features of the MODELS language.

7.3.1. TACS type-50 frequency meter The frequency-meter in TACS operates by measuring the time elapsed between successive zero-crossings of its input signal. Rudimentary noise filtering is accomplished by simply rejecting zero-crossings that fall outside a specified frequency range. The device is used by specifying the initial frequency of the signal, and the size of the acceptable band of frequencies, expressed as a percentage of the initial frequency. Better frequency meters can be modeled. This model simply reproduces the operation of the frequency meter installed in TACS.

MODEL fmeter DATA f0 -- initial frequency [Hz] (used until the 2nd zero-crossing) band -- max acceptable change on either side of f0 [%] INPUT x -- monitored signal [any units] VAR f -- measured frequency [Hz] txing -- time of last detected zero-crossing xprev -- previous value of signal dtmin -- minimum sampling half-period dtmax -- maximum sampling half-period a -- auxiliary variable OUTPUT f INIT f := f0 -- initial value of measured frequency txing := -2 -- initially holding a flag value xprev := x -- will be the previous value at next time step dtmax := 0.5/(1-band/100)/f0 -- largest value of half-period dtmin := 0.5/(1+band/100)/f0 -- smallest value of half-period ENDINIT EXEC IF txing = -2 THEN txing := -1 -- just skipping the first step ELSIF txing = -1 AND xprev*x <=0 THEN txing:=t ELSIF xprev*x <=0 AND t-txing >= dtmin AND t-txing <= dtmax THEN a := backtime(x, 0) -- interpolate to find the zero-crossing time f := 0.5/(a-txing) -- adjust the measured frequency txing := a -- remember the zero-crossing time ENDIF xprev := x -- will be the previous value at next time step ENDEXEC ENDMODEL

104

USE fmeter AS DATA f0 band INPUT x OUTPUT ____ ENDUSE local_name := ___________ := ___________ := __________ := f

in Hertz in percent

7.3.2. TACS type-51 relay-operated switch The relay-operated switch in TACS passes the value of the input signal when the absolute value of the driving signal is at or above a specified threshold value. Otherwise, the output value is zero. This can be represented in MODELS with a simple function:

FUNCTION relay_switch ( input, driving, threshold ) := input * ( abs(driving) >= threshold )

When the condition is true, the function returns the value input * 1 . When the condition is false, the function returns the value input * 0 .

7.3.3. TACS type-52 level-triggered switch The level-triggered switch in TACS operates similarly to the relay-operated switch, without the absolute value. The same approach can be used as above, using a simple function:

FUNCTION relay_switch ( input, driving, threshold ) := input * ( driving >= threshold )

When the condition is true, the function returns the value input * 1 . When the condition is false, the function returns the value input * 0 . Functions like this one are so simple that it is as easy to use the expression directly in a model as it is to create and call a function.

7.3.4. TACS type-53 transport delay The operation of the transport delay of TACS can be represented directly by using the delay() function of MODELS. The only difference is that in TACS, we have to specify the maximum delay time to be used by the device, while in MODELS, we specify the number of value cells to be used by the device. The difference is imposed by the fact that in TACS, the time step being fixed, it is possible to calculated the number of memory cells required by the device, by dividing the maximum delay time by the size of the time step. But in MODELS, the time step can be variable, so we need to specify the required number of cells directly, as it cannot be calculated. The task is facilitated in MODELS by being able to specify a default that applies to all uses of the delay function in a model.

105

7.3.5. TACS type-54 pulse delay The pulse delay is more interesting, as it does not require the large amount of storage that was needed to track the value of a signal at each time step in the case of the transport delay. The device simply detects the instants when the input signal becomes positive and ceases to be positive, and determines if the delay falls within an "on" period or an "off" period. Without considering initial conditions, the algorithm is quite simple. It gets more complex when combinations of initial conditions are considered, as shown in the model below. The logical operation of the device is best represented by a state machine, shown here with 7 states. A much more simple model can be constructed for cases where the delay value is known to remain constant during the simulation.

MODEL pulse_delay DATA ton_ini {dflt:-9999} -- initial value of pulse beginning time toff_ini {dflt:-9999} -- initial value of pulse ending time INPUT x -- input signal delay_val -- variable delay value VAR out -- delayed pulse state -- 0= waiting for ton -- 1= got ton -- 2= got ton, don -- 3= got toff -- 4= got toff, xon -- 5= waiting for doff -- 6= waiting for doff, got ton ton -- time when x became >0 toff -- time when x became <=0 OUTPUT out INIT out := 0 IF ton_ini = -9999 THEN state:=0 ELSE ton := ton_ini IF toff_ini = -9999 THEN IF t-ton >= delay_val THEN out:=1 state:=2 ELSE state:=1 ENDIF ELSE toff := toff_ini IF t-toff >= delay_val THEN state:=0 ELSIF t-ton >= delay_val THEN out:=1 state:=5 ELSE state:=3 ENDIF ENDIF ENDIF ENDINIT EXEC IF state = 0 THEN IF x > 0 THEN ton:=t state:=1 ENDIF ELSIF state = 1 THEN IF t-ton >= delay_val THEN out:=1 state:=2 ENDIF IF x<=0 THEN toff:=t state:=3 ENDIF IF state=3 AND out=1 THEN state:=5 ENDIF ELSIF state = 2 THEN IF x<=0 THEN toff:=t state:=5 ENDIF ELSIF state = 3 THEN IF t-ton >= delay_val THEN out:=1 state:=5 IF x > 0 THEN ton:=t state:=6 ENDIF ENDIF ELSIF state = 5 THEN

106

IF t-toff >= delay_val THEN out:=0 state:=0 ENDIF IF x>0 THEN ton:=t IF state=0 THEN state:=1 ELSE state:=6 ENDIF ENDIF ELSIF state = 6 THEN IF t-toff >= delay_val THEN out:=0 state:=1 ENDIF IF x<=0 THEN toff:=t IF state=1 THEN state:=3 ENDIF ENDIF ENDIF ENDEXEC ENDMODEL

USE pulse_delay AS DATA ton_ini toff_ini INPUT x delay_val OUTPUT _________ ENDUSE somename := __________ in seconds (optional) := __________ in seconds (optional) := __________ := __________ in seconds := out

Long models like this one would execute faster by being pre-compiled. One approach would be to write it in C or in Fortran, and link it with ATP. Then, all we need to put in this library is the following, replacing the above INIT and EXEC procedures of the model by a call to the foreign model.

MODEL pulse_delay DATA ton_ini {dflt:-9999} -- initial value of toff_ini {dflt:-9999} -- initial value of INPUT x -- input signal delay_val -- variable delay value VAR out -- delayed pulse MODEL compiled_pulse_delay FOREIGN C_pulse_delay {ixdata:2, ixin:2, ixout:1, ixvar:4} EXEC USE compiled_pulse_delay AS pdelay DATA xdata[1..2] := [ton_ini, toff_ini] -INPUT xin[1..2] := [x, delay_val] -OUTPUT out := xout[1] -ENDUSE ENDEXEC ENDMODEL pulse beginning time pulse ending time

this is array notation just loading the values and retrieving the output

7.3.6. TACS type-55 digitizer The digitizer in TACS is defined as a list of points on a straight line of slope equal to a "gain". The output value is the value of the closest point below the level of the input. This can be represented in MODELS using a straight-line pointlist function:

FUNCTION digitizer POINTLIST ( value_1, value_1 ), ( value_2, value_2 ), ( value_3, value_3 ), etc.

107 This function is then used with the interpolation degree set at zero, resulting in level steps between the defined points on the line:

y := digitizer( signal, 0)

7.3.7. TACS type-56 point-by-point nonlinearity The type-56 device is a pointlist function with linear interpolation. This can be represented directly in MODELS using a pointlist function:

FUNCTION point_by_point POINTLIST ( x1, y1 ), ( x2, y2 ), ( x3, y3 ), etc.

and using the function with the default interpolation degree of one:

y := point_by_point( signal)

7.3.8. TACS type-57 time-sequenced switch The time-sequenced switch can also be represented using a pointlist function. The x coordinate shows the values of switching times, and the y coordinate is either one or zero.

FUNCTION time_seq_switch POINTLIST ( t1, 0 ), ( t2, 1 ), ( t3, 0 ), etc.

The function is used with an interpolation degree of zero, and is multiplied by the value of the input signal.

y := signal * time_seq_switch(t)

7.3.9. TACS type-58 controlled integrator The TACS type-58 integrator is a resettable Laplace function of the form

gain d0 + d1 s

A control signal determines when the output is reset to a specified reset value. Both operations are included in the simple model below. The model also accepts an initial value:

108

MODEL type_58 DATA out_ini {dflt:0} -- initial value of out gain {dflt:1} -- function gain d0 {dflt:0} -- denominator coefficient of s0 d1 {dflt:1} -- denominator coefficient of s1 INPUT x -- input signal control {dflt:1} -- apply function when positive, else reset reset_value {dflt:0} -- used on reset VAR out -- function output OUTPUT out INIT out := out_ini ENDINIT EXEC IF control<=0 THEN out:=reset_value ELSIF t>=timestep THEN LAPLACE(out/x):=(gain|s0)/(d0|s0 + d1|s1) ENDIF ENDEXEC ENDMODEL

USE type_58 AS somename DATA out_ini := gain := d0 := d1 := INPUT x := control := reset_value := OUTPUT _____________ := ENDUSE ________ ________ ________ ________ ________ ________ ________ out (optional) (optional) (optional) (optional (optional) (optional)

7.3.10. TACS type-59 simple derivative The type-59 derivative of TACS is a mid-point derivative of the form

gain x(t ) x(t timestep) timestep

y := gain * ( x - prevval(x) ) / timestep

One may wonder why the above expression did not use the built-in function deriv() of MODELS as follows:

y := gain * deriv(x)

It is because the deriv() function in MODELS calculates the end-point derivative, that is, the derivative of x at time=t, not at time=(2t-timestep)/2, as in TACS. If we need to reproduce the operation of the TACS device, then we use the mid-point derivative expression.

109

7.3.11. TACS type-60 input-IF component The type-60 input-IF device was an attempt to provide the equivalent of an IF statement in the confines of a signal-flow block-diagram representation. The device is a switch that passes one of three inputs depending on the value of a control variable with respect to a threshold. It can be expressed in a model using an IF statement:

IF x1 < x2 THEN out:=in1 ELSIF x1 = x2 THEN out:=in2 ELSE out:=in3 ENDIF

7.3.12. TACS type-61 signal selector The type-61 signal selector is a switch that gives as output the value of one input signal from among up to 8 inputs, depending on the value of a selector signal. It can be represented in a model using an IF statement:

IF ELSIF ELSIF ELSIF ELSIF ELSIF ELSIF ELSE ENDIF selector selector selector selector selector selector selector < < < < < < < 0.5 1.5 2.5 3.5 4.5 5.5 6.5 THEN THEN THEN THEN THEN THEN THEN out:=i0 out:=i1 out:=i2 out:=i3 out:=i4 out:=i5 out:=i6 out:=i7

7.3.13. TACS type-62 sample/hold and track/hold The sample and track device of TACS can perform the functions of a sample/hold device and of a track/hold device. The two modes of operation are separated here in two different models. The sample/hold device takes samples of the input signal on each rising front of the control signal. The output maintains the sampled value between sampling. It is possible to specify an initial output value. The operation is represented as a simple state machine:

110

MODEL sample_hold DATA out_ini {dflt:0} -- initial value of out INPUT x -- sampled signal sample_control -- triggers sampling on rising positive front VAR out state -- 0= waiting for control>0 -- 1= waiting for control<=0 OUTPUT out INIT state := 0 out := out_ini ENDINIT EXEC IF state = 0 AND sample_control > 0 THEN state:=1 out:=x ELSIF state = 1 AND sample_control <= 0 THEN state:=0 ENDIF ENDEXEC ENDMODEL

USE sample_hold AS somename DATA out_ini := ________ (optional) INPUT x := ________ sample_control := ________ OUTPUT ______________ := out ENDUSE

The track/hold device passes the value of the input signal when the control signal is positive, and holds its most recent value when the control signal is not positive. The only reason why this device needs to be represented as a model rather than as a function is that we need to carry a value from one time step to the next, the value last-held by the output variable.

MODEL track_hold DATA out_ini {dflt:0} -- initial value of out INPUT x -- tracked signal track_control -- tracks when positive VAR out OUTPUT out INIT out := out_ini ENDINIT EXEC IF track_control > 0 THEN out:=x ENDIF ENDEXEC ENDMODEL

Notice that we do not need to specify an ELSE clause in the IF statement. The complete IF statement could be written as:

IF track_control > 0 THEN out:=x ELSE out:=out ENDIF

but by default, any variable of a model maintains its value until it is changed to another value, so writing out := out is redundant. The track/hold model can be used as follows:

111

USE track_hold AS somename DATA out_ini := ________ (optional) INPUT x := ________ track_control := ________ OUTPUT _____________ := out ENDUSE

7.3.14. TACS type-63 instantaneous min/max The output of the instantaneous min/max device of TACS is that of the lowestvalued or highest-valued input, respectively. In MODELS, we can use the built-in functions min(x1,x2,...) and max(x1,x2,...) to perform that operation. To find the minimum of many signals, we can use:

y := min( expr1, expr2, etc. )

y := max( expr1, expr2, etc. )

where each argument can be an entire expression, not only the name of a variable, just as for any function in MODELS except the built-in simulation functions (deriv, prevval, etc.).

7.3.15. TACS type-64 min/max tracking The min/max tracking device of TACS is a resettable track/hold device that uses as input the minimum or maximum value of a group of signals. If the reset function is not needed, we can use the track/hold model that has been defined above, and supply as input an instantaneous minimum or maximum:

USE track_hold AS somename DATA out_ini := ________ (optional) INPUT x := min( x1, x2, etc. ) track_control := ________ OUTPUT _____________ := out ENDUSE

If we need a reset control, then we can add on to the previously-defined track/hold model, as follows:

112

MODEL mintrack_hold DATA out_ini {dflt:inf} -- initial value of out, defaulted to +infinity INPUT x -- tracked signal hold_control {dflt:0} -- holds when positive reset_control {dflt:0} -- resets when positive reset_value {dflt:0} -- used on reset VAR out OUTPUT out INIT IF out_ini = inf THEN out := x ELSE out := out_ini ENDIF ENDINIT EXEC IF reset_control > 0 THEN out:=reset_value ELSIF hold_control <= 0 THEN out:=min(x,out) ENDIF ENDEXEC ENDMODEL

There are two details to notice. First, the reset control signal has priority over the hold control signal. The second is that we do not need to specify the third clause of the IF statement to indicate that the output value maintains its value when the two other conditions are not true, as this is done by default. This model can be used as follows:

USE mintrack_hold AS somename DATA out_ini := ________ INPUT x := ________ hold_control := ________ reset_control := ________ reset_value := ________ OUTPUT _____________ := out ENDUSE (optional) (optional) (optional) (optional)

The maximum track/hold model is similar, except for the value of the initial condition:

MODEL maxtrack_hold DATA out_ini {dflt:-inf} -- initial value of out, defaulted to -infinity INPUT x -- tracked signal hold_control {dflt:0} -- holds when positive reset_control {dflt:0} -- resets when positive reset_value {dflt:0} -- used on reset VAR out OUTPUT out INIT IF out_ini = -inf THEN out := x ELSE out := out_ini ENDIF ENDINIT EXEC IF reset_control > 0 THEN out:=reset_value ELSIF hold_control <= 0 THEN out:=max(x,out) ENDIF ENDEXEC ENDMODEL

113

USE maxtrack_hold AS unique_name_in_your_model DATA out_ini := ________ (optional) INPUT x := ________ hold_control := ________ (optional) reset_control := ________ (optional) reset_value := ________ (optional) OUTPUT _____________ := out ENDUSE

7.3.16. TACS type-65 accumulator / counter The type-65 accumulator keeps a running sum of its input over time. It can be put on hold, and its output value can be reset to a specified value. Its operation can be described using the following model:

MODEL accumulator DATA out_ini {dflt:0} -- initial value of out, defaulted to zero INPUT x -- input signal hold_control {dflt:0} -- holds when positive reset_control {dflt:0} -- resets when positive reset_value {dflt:0} -- used on reset VAR out OUTPUT out INIT out := out_ini IF hold_control <= 0 THEN out:=out-x ENDIF -- to prepare for out+x below ENDINIT EXEC IF reset_control > 0 THEN out:=reset_value ELSIF hold_control <= 0 THEN out:=out+x ENDIF ENDEXEC ENDMODEL

USE accumulator AS somename DATA out_ini := ________ INPUT x := ________ hold_control := ________ reset_control := ________ reset_value := ________ OUTPUT _____________ := out ENDUSE (optional) (optional) (optional) (optional)

7.3.17. TACS type-66 RMS value The type-66 rms meter in TACS continuously updates the output value of the meter, using a moving window of fixed width corresponding to the base frequency.

114

MODEL rms_meter DATA freq -- base frequency xrms_ini {dflt:-1} -- initial rms value INPUT x -- monitored signal VAR xrms -- rms value of monitored signal x2 -- internal, x*x ix2 -- internal, integral of x2 period -- 1/freq OUTPUT xrms DELAY CELLS(ix2): 1/freq/timestep +1 INIT period := recip(freq) histdef(ix2) := 0 integral(x2) := 0 IF xrms_ini <0 THEN xrms:=0 ELSE xrms:=xrms_ini ENDIF ENDINIT EXEC x2 := x*x ix2 := integral(x2) IF t>period THEN xrms := sqrt((ix2 - delay(ix2, period))/period) ENDIF ENDEXEC ENDMODEL

Using a pre-determined fixed period keeps the model simple. A more complete rms meter would allow for variable period and arbitrary dc bias. The above model can be used as follows:

USE rms_meter AS unique_name_in_your_model DATA freq := _______ in Hz xrms_ini := _______ (optional) INPUT x := _______ in any units OUTPUT ________ := xrms ENDUSE

115

This is a summary reference to the syntax of the MODELS language. It consists of all the structure and the syntax diagrams contained in the Language Manual, without any of the explanatory text.

MODELS section model declaration declaration of a local model declaration of a foreign model

116

record element

declaration in a model constant element data element input element output element variable element function submodel

117

118

simulation directive in a model history directive time step directive input interpolation directive delay cells directive

history directive

119

initialization procedure

execution procedure

named procedure

120

Statement

assignment statement algorithm control statement

assignment statement value assignment differential equation Laplace transfer function z transfer function integral value reset assignment history assignment

value assignment

differential equation

y, x

D-polynomial

121

limits

Laplace transfer function LAPLACE(y / x) := (S-polynomial) / (S-polynomial) CLAPLACE(y / x) := (S-polynomial) / (S-polynomial) LAPLACE (y / x) { limits } := (S-polynomial) / (S-polynomial) CLAPLACE (y / x) { limits } := (S-polynomial) / (S-polynomial)

y, x

S-polynomial

limits

z transfer function ZFUN(y / x) := (z-1-polynomial) / (z-1-polynomial) CZFUN(y / x) := (z-1-polynomial) / (z-1-polynomial) ZFUN(y / x) { limits } := (z-1-polynomial) / (z-1-polynomial) CZFUN(y / x) { limits } := (z-1-polynomial) / (z-1-polynomial)

122

y, x

z-1-polynomial

limits

history assignment

algorithm control statement IF statement WHILE statement FOR statement DO statement REDO statement COMBINE statement ERROR statement USE statement procedure call

123

IF statement

WHILE statement

FOR statement

DO statement

COMBINE statement COMBINE AS identifier statement-list ENDCOMBINE COMBINE ITERATE AS identifier statement-list ENDCOMBINE COMBINE ITERATE { max-iter } AS identifier statement-list ENDCOMBINE

124

ERROR statement

USE statement

write-list

USE data directive USE input directive USE output directive USE history directive USE time step directive USE input interpolation directive USE delay cells directive

125

126

Expression

regular expression sum expression in a value assignment derivative expression in a value assignment integral expression in a value assignment

Regular expression

127

logical term

logical factor

numerical expression

numerical term

numerical factor

128

value reference

numerical value

array value

named value

function value

129

Value-holding element

single-value element array-value element

single-value element

array-value element

Syntactic element

name numerical value logical value text value in-ine comment block comment separator

name

numerical value

130

in-line comment start: two or more contiguous hyphens (hyphen string) end: end of line

block comment

131

This section provides a condensed structured overview of the syntax of the MODELS language. It shows only the keywords of the language, without the details of the full syntax rules.

element declarations INPUT ... { type( ... ) } type: v, i, switch, mach, imssv, imssi, tacs, pl4, atp OUTPUT... VAR ...

model declarations MODEL ... ENDMODEL MODEL ... FOREIGN ... { IXDATA: ... IXIN: ... IXOUT: ... IXVAR: ... }

132

element declarations CONST ... { VAL: ... } DATA ... { DFLT: ... } INPUT ... { DFLT: ... } OUTPUT ... VAR ...

function declarations FUNCTION ... := ... FUNCTION ... POINTLIST ( ... , ... ) ( ... , ... ) ... FUNCTION ... FOREIGN ... { IXARG: ... }

submodel declarations MODEL ... ENDMODEL MODEL ... FOREIGN ... { IXDATA: ... IXIN: ... IXOUT: ... IXVAR: ... } MODEL ... EXTERNAL

simulation directives HISTORY ... { DFLT: ... } HISTORY INTEGRAL( ... ) { DFLT: ... } TIMESTEP MIN: ... MAX: ... INTERPOLATION DEGREE ( ... ) : ... INTERPOLATION DEGREE DFLT: ... DELAY CELLS ( ... ) : ... DELAY CELLS DFLT : ...

133

procedures INIT ... ENDINIT EXEC ... ENDEXEC PROC ... ENDPROC

assignment statements ... := ... DIFFEQ( ... ) | ... { DMIN: ... DMAX: ... } := ... CDIFFEQ( ... ) | ... { DMIN: ... DMAX: ... } := ... LAPLACE( ... ) | ... { DMIN: ... DMAX: ... } := ... CLAPLACE( ... ) | ... { DMIN: ... DMAX: ... } := ... ZFUN( ... ) | ... { DMIN: ... DMAX: ... } := ... CZFUN( ... ) | ... { DMIN: ... DMAX: ... } := ... INTEGRAL( ... ) := ... HISTDEF( ... ) := ...

algorithm control statements IF ... THEN ... ELSIF ... THEN ... ... ELSE ... ENDIF WHILE ... DO ... ENDWHILE FOR ... := ... ... DO ... ENDFOR DO ... REDO ... ENDDO COMBINE AS ... ENDCOMBINE COMBINE ITERATE AS ... ENDCOMBINE COMBINE ITERATE { ... } AS ... ENDCOMBINE ERROR ... STOP USE ... ENDUSE instance.procname( ... ) WRITE( ... ) WRITE1( ... ) WRITE2( ... )

134

DATA ... := ... INPUT ... := ... OUTPUT ... := ... HISTORY ... := ... TIMESTEP MIN: ... MAX: ... INTERPOLATION DEGREE( ... ) : ... INTERPOLATION DEGREE DFLT: ... DELAY CELLS( ... ) : ... DELAY CELLS DFLT : ...

regular-expression { MIN: ... MAX: ... } SUM( ... ) { MIN: ... MAX: ... } DERIVPOL( ... ) { MIN: ... MAX: ... } INTEGRAL( ... ) { DMIN: ... DMAX: ... }

135

... OR ... ... AND ... ... > ... ... >= ... ... < ... ... <= ... ... = ... ... <> ... ... + ... ... - ... ... * ... ... / ... ... ** ... ... MOD ... num value [ ... , ... ... ] ... - ... NOT ... name name [ ... ] name [ ... .. ... ] function name ( ... , ... ... ) ( regular expression )

-- ... end-of-line COMMENT ... ENDCOMMENT ILLUSTRATION ... ENDILLUSTRATION

136

The MODELS language provides a set of pre-defined constants and pre-defined global and local variables. Their names are pre-defined, and are visible in any model. The values of the pre-defined constants are-defined globally. The values of the pre-defined variables carry simulation information that can be accessed inside any model.

Pre-defined constants

The pre-defined constants have pre-assigned values, and can be used inside any expression, in any model of a simulation. They are: pi inf undefined false, true no, yes open, closed off, on 3.14159... a large number, typically 1020 88888.88888 the equivalent numerical values 0 and 1 the equivalent numerical values 0 and 1 the equivalent numerical values 0 and 1 the equivalent numerical values 0 and 1

The infinity value inf is dependent on the computer platform being used. The value undefined is the value carried by any variable that has not yet been assigned a value during a simulation. The value of the logical constants are represented internally as the numerical values 0 and 1.

Three variables are defined globally in a simulation. They carry the value of the starting and ending time of the simulation, and the value of time step imposed by the environment, shell, or application controlling the simulation. The value of these variables can be accessed by name inside any expression, in any model of a simulation. They are: starttime stoptime the value of t at which the simulation started the value of t at which the simulation will end

137 startstep the value of the initial time step at the outermost level

The values of starttime and startstep are set at the start of the simulation. The value of stoptime is defined by the application controlling the simulation, and may change during a simulation.

The names of the pre-defined local variables are the same in all models of a simulation, but their values are local to each instance of each model used in a simulation. The value of these variables can be accessed by name inside any expression, in any model of a simulation. They are: t prevtime timestep endtime fullstep minstep maxstep the present simulation time the simulation time at the last update the size of the interval between prevtime and t the target simulation time of a USE call the size of the interval over which to update at USE call the variable lower limit imposed on timestep the variable upper limit imposed on timestep

These variables carry information about how the state of a model is updated from a previous simulation time to a target simulation time, on each update call to a model instance from a USE statement. In a case where timestep, the time step used in the called model, is the same size as fullstep, the calling interval, which is also the time step of the calling model, the relationship between these variables is simple:

t0 fullstep endtime t

timestep

minstep <= fullstep <= maxstep timestep = fullstep t = endtime = t0 + fullstep = t0 + timestep prevtime = t0

138 In a case where fullstep is smaller than minstep, the model instance does not update itself to the outside time, because the time increase is considered to be too small to change the present state of the model significantly. The model waits until endtime - t0 >= minstep to update its state, in one large time step.

t0 fullstep fullstep fullstep endtime t

timestep

In a case where fullstep is larger than the largest time step allowed maxstep, the full step is subdivided into sub-steps of a size that satisfies the maxstep upper limit, and the model instance is executed for each sub-step successively, until the target time endtime is reached. Only then is control passed back to the calling model, along with the model's output values at time t = endtime. For this case, the relationship between the variables is as follows:

t0 fullstep endtime t timestep

timestep

timestep

fullstep > maxstep timestep <= maxstep timestep < fullstep t = { t0 + timestep, t0 + 2*timestep, ... , endtime } prevtime = { t0, t0 + timestep, ... , endtime - timestep }

139

MODELS provides a set of pre-defined functions. There are built-in numerical functions, logical functions, and random value functions. There is also a set of simulation functions that make explicit or implicit reference to the stored history of the variables of a model. In order to extend the use of single-argument functions to array arithmetic, MODELS allows single-argument functions to be used with lists of arguments. When given a list of arguments as input, a function that is normally a singleargument function will return a corresponding list of single values as output, one output for each argument (one-to-one).

Numerical functions

This is a list of all the pre-defined functions that return numerical values. They are grouped as one-to-one functions, two-argument functions returning a single value, and n-argument functions returning a single value.

1-to-1 functions returning one value for each argument When used with a single argument, these functions return a single output value. When used with a list of argument values, they return as many output values, each corresponding to the function being applied to each value supplied in the argument list. This is illustrated below using the absolute value function:

abs(a) abs(expression) expression abs(a, b) abs(expression list) abs(x[1..2]) abs(a, x[1..2]) abs(array expression) -- returns one value: the absolute value of a -- returns one value: the absolute value of the -- returns [abs(a), abs(b)] -- returns array of absolute values of each list element -- returns [abs(x[1]), abs(x[2])] -- returns [abs(a), abs(x[1]), abs(x[2])] -- returns array of absolute values of each array element

Following are the 1-to-1 numerical functions: abs( ) sqrt( ) exp( ) ln( ) absolute value square root exponential natural log arg<0 produces error arg<0 produces error

140 log10( ) log2( ) recip( ) factorial( ) trunc( ) fract( ) round( ) sign( ) rad( ) deg( ) sin( ), cos( ), tan( ) asin( ), acos( ), atan( ) sinh( ), cosh( ), tanh( ) asinh( ), acosh( ), atanh( ) base 10 log base 2 log protected division factorial integer part fractional part rounding sign function degrees to radians radians to degrees trigonometric inverse trigonometric hyperbolic inverse hyperbolic arg in radians return value in radians arg in radians return value in radians -1 if <0; 0 if 0; +1 if >0 arg<0 produces error arg<0 produces error division by zero returns value=inf arg<0 produces error

2-argument functions returning a single value These functions always return a single value, and cannot be extended to array arithmetic as the previous 1-to-1 functions. Each of the two arguments can be given in the form of a single-value expression, or the two arguments can be specified together as a two-element array expression. This is illustrated here using the atan2() function:

atan2(a, b) atan2(expr1, expr2) atan2(x[1..2]) -- returns one value: arctan(a/b) -- returns one value: arctan(expr1/expr2) -- returns one value: arctan(x[1]/x[2])

Following are the 2-to-1 numerical functions: atan2( ) binom( ) permut( ) 4-quadrant arctan(a/b) binomial function C(n,r) permutation function P(n,r) accepts zero-value arguments returns n! / (n-r)! r! returns n! / (n-r)!

141

n-argument functions returning a single value These functions take as input a list of values, and return a single value. The list of input expressions can include single values and array values. The following example illustrates how the input values can be specified:

min(a, b) -- returns the minimum value of the two arguments a and b min(expr1, expr2, ...) -- returns the minimum value of the argument list min(x[1..2]) x[2] min(a, x[1..2]) min(array expression) -- returns the minimum value of the two args x[1] and -- returns the minimum value of a, x[1], and x[2] -- returns the minimum value of all array elements

Following are the n-to-1 numerical functions: min( ) max( ) norm( ) minimum value maximum value Euclidian norm, or magnitude returns sqrt(sum(arg2)))

Logical functions

This is a list of all the pre-defined functions that return logical values. They are grouped as one-to-one functions, and n-argument functions returning a single value. The logical values true and false are represented in MODELS by the numerical values 1 and 0. Conversion between numerical and logical values is automatic, and is determined by the context in which they are used. This allows numerical values to be used in a logical context ( >0 is true, <=0 is false ), and logical values to be used in a numerical context ( true is 1, false is 0 ).

1-to-1 functions returning one value for each argument There is only one function in this category. It provides explicit conversion from numerical to logical ("Boolean"). When used with a single argument, it returns a single output value. When used with a list of argument values, it return as many output values, corresponding to each value in the argument list. bool( ) numerical to logical returns true if arg>0, false if arg<=0

142 Here are examples showing how the function can be used:

bool(a) bool(expression) bool(a, b) bool(expression list) element bool(x[1..2]) bool(a, x[1..2]) bool(array expression) -- returns one value: conversion value of a -- returns one value: conversion value of the expression -- returns [bool(a), bool(b)] -- returns array of conversion value of each list -- returns [bool(x[1]), bool(x[2])] -- returns [bool(a), bool(x[1]), bool(x[2])] -- returns array of conversion value of each element

n-argument functions returning a single value These functions take as input a list of values, and return a single logical value. The list of input expressions can include single values and array values. Logical values are expected for each argument. If numerical values are supplied, they are automatically converted to their logical equivalent, using the same rule as shown above. The following example illustrates how the input values can be specified:

and(a, b) -- returns true only if a and b are true and(expr1, expr2, ...) -- returns true only if all argument values are true and(x[1..2]) and(a, x[1..2]) and(array expression) -- returns true only if x[1] and x[2] are true -- returns true only if a and x[1] and x[2] are true -- returns true only if all array elements are true

Following are the n-to-1 logical functions: and( ) or( ) nand( ) nor( ) xor( ) logical AND logical OR logical NOT AND logical NOT OR logical exclusive OR returns true only if all args are true returns true if one or more args are true returns true if one or more args are false returns true only if all args are false returns true if only one arg is true

There is one random value function pre-defined in MODELS at this point. The function uses no arguments, and returns a value between zero and one: random( ) random value returns a random value between 0 and 1

The sequence of random numbers generated from repeated calls to the function random() is reproducible from one simulation run to the next. To generate nonreproducible sequences requires a call by the program to the date/time routine of the computer's operating system. In the present Fortran version of MODELS, this

143 is not available, because Fortran doesn't provide a standard function for doing this. When provided, it is compiler-dependent. In the future C version of MODELS, it will be available, because C provides a standard compilerindependent function for this. In the meantime, two foreign C functions have been pre-linked to ATP: C_seed() to generate a new seed, and C_random() to generate a sequence of random numbers based on that seed. C_seed(x) uses a dummy argument of any value. It returns no value. C_random(x) uses a dummy argument of any value. It returns a value between 0 and 1. The use of these functions does not affect the sequence of numbers generated by the MODELS function random(). The source code for the two C functions is the following:

#include <stdlib.h> double C_SEED(void) /* randomly seeds the C library function rand() */ { date_time_seed(); return 0; } double C_RANDOM(void) /* returns a random number between 0 and 1 */ { return (double)rand()/(double)RAND_MAX; }

FUNCTION seed FOREIGN C_SEED {ixarg: 1} FUNCTION rand FOREIGN C_RANDOM {ixarg: 1}

where the names C_SEED and C_RANDOM are already registered in subroutine fgnfun in the file named fgnmod.for of ATP. After being declared in a model, the functions can then be used as in the following example:

INIT dum := seed(0) expression ... ENDINIT EXEC ... y := x * rand(0) ... ENDEXEC -- functions in MODELS can only be used inside an

144

Simulation functions

MODELS provides special simulation functions not available in regular programming languages, for the fact that they make an implicit reference to the advancing value of time and to the accumulated history of the variables to which they are applied. These are functions such as derivative, previous value, etc, as shown below. When using the simulation functions, the first argument in the argument list is always a single value-holding element, for example x, or y[n], and is never an expression. This is because an expression has no history which can be referred to when calculating the value of the function. Some simulation functions require a second argument, for example, the value of the delay applied to a variable. All 2-argument functions, except histval(), accept an optional third argument to indicate the interpolation method used by the function. Only the values 0, 1, and 2 are recognized for this, indicating respectively: no interpolation (the signal varies in steps), linear interpolation, and quadratic interpolation. Linear interpolation is the default, and the "1" can always be omitted. The simulation functions are: deriv(x) deriv2(x) prevval(x) delay(x, dval) delay(x, dval, pol) predval(x, tval) predval(x, tval, pol) predtime(x, xval) predtime(x, xval, pol) backval(x, tval) backval(x, tval, pol) backtime(x, xval) backtime(x, xval, pol) histval(x, tval) histdef(x) dx/dt, calculated at end of step d2x/dt2, calculated at mid-step value of x at previous time step value of x at time (t - dval) predicted value of x at time tval predicted time when x will equal xval value of x(tval) within last step interval time when x was equal to xval within last step value of x(tval), using the history expression associated with x value of the history expression of x evaluated at generic time t, equivalent to writing histval(x,t)

145

deriv(x) The time derivative of x is calculated with the assumption that it is linear over each time step interval, that is, that the second derivative is constant over the interval. The program first calculates the two mid-step derivatives

deriv0.5 = deriv15 . = x(t 0 ) x(t1) t 0 t1 x(t1) x(t 2) t1 t 2

deriv0.5 deriv15 . t0.5 t15 .

deriv 2t1 =

which is then used to extrapolate linearly the first mid-step derivative, deriv0.5, to the end of the interval, using the second derivative as its slope:

derivt 0 = deriv0.5 + deriv 2t1 t 0 t1 2

When the time step is small enough to cover the higher frequencies of the signal, this method is more accurate than using the simple mid-step derivative. However, the mid-step derivative is less sensitive to discontinuities, and should be used instead of deriv() when the time step is not well matched to the frequency contents of the signal, by doing:

y:=(x-prevval(x))/timestep

y:=deriv(x)

It is possible to apply limits to the calculated value of a derivative. Because the function doesn't carry any internal variables from one step to the next, a dynamic limit has no meaning for the derivative. Only static limits can be applied to a derivative, as part of the expression where the function is used:

y:=deriv(x) {min:expression, max:expression}

deriv2(x) The second order derivative of x with respect to time, d2x/dt2, is calculated as the mid-step derivative of the first derivative, itself calculated at mid-step for the last two intervals. The method takes into account the possibility for the time step to be variable. The second derivative is calculated using:

146

deriv0.5 deriv15 . t0.5 t15 .

x(t 0 ) x(t1) x(t1) x(t 2) t 0 t1 t1 t 2 t 0 + t1 t1 + t 2 2 2

When the time step is constant, this is equivalent to calculating the second derivative as:

x(t ) 2 x(t t ) + x(t 2 t ) t 2

It must be observed that the calculated value is in fact the value of the second derivative at the previous time t1, because of the mid-step method. This means that the value of the second derivative at time t is available only after a delay of one time step. The second derivative of a variable can be used in any expression, for example:

y:=deriv2(x)

It is possible to apply limits to the calculated value of a second derivative. Because the function doesn't carry any internal variables from one step to the next, a dynamic limit has no meaning for this operation. Only static limits can be applied to a second derivative, as part of the expression where the function is used:

y:=deriv2(x) {min:expression, max:expression}

prevval(x) This function returns x(t-t), the value of a variable at the previous time step. It can be used in any expression, for example:

y:=prevval(x)

Static limits can be applied as part of the expression where the function is used:

y:=prevval(x) {min:expression, max:expression}

delay(x, dval, pol) This function returns x(t-dval), the value of a variable at a past time of the simulation.

147 When that requested past time falls before the start of the simulation, that is, before the value of the variable could started being tracked, the delay() function uses the history expression associated with that variable to calculate the past value, and returns the value histval(x, t-dval). When the requested past time falls after the start of the simulation, where tracked values of the variable are available, interpolation is used for cases where the value t-dval does not correspond exactly to one of the discrete instants of the simulation. By default, when the third argument is not specified, linear interpolation is used. Otherwise, the pol argument can be given a value of 0, 1, or 2, for step, linear, or quadratic interpolation. Using the delay function can require a considerable amount of storage for keeping track of the past values of a variable (see the simulation directive DELAY CELLS). However, the calculation is fast, as it uses a binary search to locate the stored values.

predval(x, tval, pol) This function returns x(tval), the predicted value of a variable at a future time of the simulation. The value is calculated using extrapolation from the most recent values of the variable. By default, when the third argument is not specified, linear extrapolation is used. Otherwise, the pol argument can be given a value of 0, 1, or 2, for step, linear, or quadratic interpolation. Using step extrapolation is not useful in this case, because it simply returns the present value of the variable.

predtime(x, xval, pol) This function returns t(xval), the predicted future time when the variable will take the value xval. The value is calculated using extrapolation from the most recent values of the variable. By default, when the third argument is not specified, linear extrapolation is used. Otherwise, the pol argument can be given a value of 0, 1, or 2, for step, linear, or quadratic interpolation. Using step extrapolation is not useful in this case, because if xval is different from x(t), then that value cannot be reached using step extrapolation. When the extrapolated value of the variable cannot reach the value xval, the function returns the value undefined, equal to 88888.88888 .

backval(x, tval, pol) This function returns the value x(tval), the value of a variable at a past time of the simulation, with the restriction that it must fall inside the last step interval. For

148 access to past values beyond the previous step, we need to use the delay() function. At the first step of a simulation, the requested past time will fall before the start of the simulation, that is, before the value of the variable could started being tracked. In this case, the backval() function uses the history expression associated with that variable to calculate the past value, and returns the value histval(x, tval). When the requested past time falls after the start of the simulation, where tracked values of the variable are available, interpolation is used for calculating the value of the variable between the simulation points. By default, when the third argument is not specified, linear interpolation is used. Otherwise, the pol argument can be given a value of 0, 1, or 2, for step, linear, or quadratic interpolation.

backtime(x, xval, pol) This function returns the time t(xval) at which the variable had the value xval, with the restriction that the time must fall within the last step interval. The value is calculated using interpolation from the most recent values of the variable. By default, when the third argument is not specified, linear interpolation is used. Otherwise, the pol argument can be given a value of 0, 1, or 2, for step, linear, or quadratic interpolation. Using step extrapolation is not useful in this case, because if xval is different from x(t-timestep), then that value cannot be reached using step interpolation. When the interpolated value of the variable cannot reach the value xval, the function returns the value undefined, equal to 88888.88888 .

histval(x, tval) This function uses the history expression specified for the variable x in order to calculate the value of x(tval). No interpolation is needed, because the history expression will provide a value calculated at t equal to tval. Although a history expression is intended to be used for calculating values of a variable at values of t preceding the start of the simulation, the histval() function can be used without any restriction on the value of tval. See the section on simulation directives for a discussion on assigning a history expression to a variable.

histdef(x) Using this function is equivalent to using histval(x,t). For whatever value of t, this function will return the corresponding value of the history expression associated with the variable x. At first look, this may seem useless. It becomes more interesting when we consider that during the simulation, the solver manipulates the value of the variable t behind the scenes whenever it needs to evaluate a

149 history expression at a certain time t. Using the function histdef(x) inside the expression defining the history expression of another variable y gives us a way to make a history expression dependent on the history expression defined for another variable. For example, we would use it in a history declaration as follows:

HISTORY y {dflt: histdef(x) - 2*histdef(w)}

HISTORY y := histdef(x) - 2*histdef(w)

histdef(y) := histdef(x) - 2*histdef(w)

In each case, it would have been equivalent to write the expression of the history expression as:

histval(x,t) - 2*histval(w,t)

to access the value of the history expression of x and w at whatever value of t selected by the solver at the time it evaluates the expression.

150

BIBLIOGRAPHY

This bibliography provides a list of published articles describing or referring to the MODELS language.

"The EMTP's new TACS", L. Dub (DEI Simulation Software, Oregon, USA), G. Bortoni, I. Bonfanti (CESI, Milano, Italy) Paper 89-11, 16th european EMTP Meeting, Dubrovnik (Yugoslavia), May 1989 "Development of a new three-phase synchronous machine code using MODELS", J.A. Martinez-Velasco (Univ. Politcnica Catalunya, Spain), G.A. Capolino (Mediterranean Inst. Tech., Marseille, France), G. Bortoni (CESI, Milano, Italy) Paper 90-M3, 18th European EMTP Meeting, Marseille (France), May 1990. "TACS and MODELS: Drive simulation languages in a general purpose program", J.A. Martinez-Velasco (Univ. Politcnica Catalunya, Spain), G.A. Capolino (Mediterranean Inst. Tech., Marseille, France) Proc. MCED '91, Marseille (France), July 1991. "Aplicaciones del cdigo MODELS", J.A. Martinez-Velasco (Univ. Politcnica Catalunya, Spain) 2as. Jornadas Luso-Espanholas de Engenharia Electrotecnica, Coimbra (Portugal), July 1991. "MODELS: A new simulation tool in the EMTP", L. Dub (DEI Simulation Software, Oregon, USA), I. Bonfanti (CESI, Milano, Italy) European Transactions on Electrical Power Engineering, Vol. 2, no. 1, pp. 45-50, Jan/Feb 1992. "Variable capacitance and inductance in ATP using MODELS", L. Dub (DEI Simulation Software, Oregon, USA), B.A. Mork (No. Dakota Univ, USA) EMTP News, Vol. 5, no. 1, Leuven (Belgium), March 1992. "Simulation of a microprocessor-controlled SVC", J.A. Martinez-Velasco (Univ. Politcnica Catalunya, Spain) Paper 92-013, 21st European EMTP Meeting, Crete (Greece), June 1992 "Implementation of a 6-phase synchronous machine model [...] using EMTP MODELS", H. Knudsen (ELKRAFT Power Co, Ballerup, Denmark) Paper 92-R-014, 22nd European EMTP Meeting, Leuven (Belgium), November 1992. "Modelling a generator relay protection scheme in EMTP using MODELS", N. Gstavsen, J. Rnne-Hansen (Tech. Univ. Denmark, Lingby, Denmark), S. Stvring-Hallsson (ELKRAFT Power Co, Ballerup, Denmark) Paper 92-R-006, 22nd European EMTP Meeting, Leuven (Belgium), November 1992.

151

"Educational use of EMTP MODELS for the study of rotating machine transients", J.A.Martinez-Velasco (Univ. Politcnica Catalunya, Spain) IEEE PES Winter Power Meeting, Paper 93 WM 126-3-PWRS, Columbus (USA), February 1993 "Connection of user-supplied programs to EMTP using MODELS", L. Dub (DEI Simulation Software, Oregon, USA) EMTP News, Vol. 6, no. 1, Leuven (Belgium), March 1993. "A 6.3 KV vacuum breaker model for ATP simulations", J. Kosmac, P. Zunko (Ljubljana Univ., Slovenia) First European Conference on Power Systems Transients, Lisbon (Portugal), June 1993. "EMTP simulation of source-insulator interaction in pollution tests", J.A. Martinez-Velasco (Univ. Politcnica Catalunya, Spain) First European Conference on Power Systems Transients, Lisbon (Portugal), June 1993. "Power swing simulation studies, measurement of power flow and voltage phasor oscillation at any point of the simulated system using MODELS", A. Mechraoui, D.W.P. Thomas (Univ. of Nottingham, UK) First European Conference on Power Systems Transients, Lisbon (Portugal), June 1993. "Using the simulation language MODELS with EMTP", L. Dub (DEI Simulation Software, Oregon, USA), I. Bonfanti (CESI, Milano, Italy), M.T. Correia de Barros (IST/Univ. Tcnica de Lisboa, Lisbon, Portugal), V. Vanderstockt (LABORELEC, Belgium) Proc. 11th Power Systems Computation Conference, pp. 1063-1069, Avignon (France), August 1993. "Utilizing the frequency scan feature of ATP-EMTP", M. Kizilcay (Lahmeyer Int'l, Frankfurt, Germany) European EMTP User Group Meeting, Lingby (Denmark), April 1994 "Modelling of a travelling wave phase selector for EHV transmission lines", M.S. Jones, D.W.P. Thomas (Univ. of Nottingham, UK) European EMTP User Group Meeting, Lingby (Denmark), April 1994 "Grounding system simulation by means of ATP MODELS", W. Kalat, M. Loboda, Z. Pochanke (Warsaw Tech. Univ., Poland) European EMTP User Group Meeting, Lingby (Denmark), April 1994 "Including a transmission line with corona in ATP using MODELS", M.T. Correia de Barros, M.E. Almeida (IST/Univ. Tcnica de Lisboa, Lisbon, Portugal), L. Dub (DEI Simulation Software, Oregon, USA) European EMTP User Group Meeting, Lingby (Denmark), April 1994

152

"Tower modelling for lightning surge analysis using EMTP", M.E.Almeida, M.T. Correia de Barros (IST/Univ. Tcnica de Lisboa, Lisbon, Portugal) European EMTP User Group Meeting, Lingby (Denmark), April 1994 "EMTP simulation of a digitally-controlled static VAR system for optimal load compensation", J.A. Martinez (Univ. Politcnica Catalunya, Spain) IEEE PES Summer Power Meeting, paper 94 SM 452-3 PWRD, San Francisco (USA), July 1994. "As EMTP Study of SSR Mitigation Using the Thyristor Controlled Series Capacitor", W. Zhu et al. (Oregon State University, Corvallis, Oregon, USA) IEEE PES Summer Power Meeting, paper 94 SM 477-0 PWRD, San Francisco (USA), July 1994. "Using the Electromagnetic Transient Program for frequency scans", G.T. Wrate, B.A. Mork (Michigan Tech. Univ., USA), K.K. Mustaphi, S.P. Dellwo (Northern States Power Co., Minneapolis, USA) MIPSYCON, Oct 1994. "Transient analysis of rotating machines using EMTP MODELS", J.A. Martinez-Velasco (Univ. Politcnica Catalunya, Spain) 1995 "Inclusion of corona in the evaluation of surge propogation with EMTP", M.T. Correia de Barros, M.E. Almeida (IST/Univ. Tcnica de Lisboa, Lisbon, Portugal), L. Dub (DEI Simulation Software, Oregon, USA) International Symposium on Electric Power Engineering - Stockholm Power Tech 95, Paper No. SPT HV 07-04-0253, Stockholm (Sweden), June 1995. "Representacion avanzada de interruptores mediante el EMTP", J.A. Martinez-Velasco (Univ. Politcnica Catalunya, Spain) Porto (Portugal), July 1995. "Computation of Electromagnetic transients on nonuniform transmission lines", M.T. Correia de Barros, M.E. Almeida (IST/Univ. Tcnica de Lisboa, Lisbon, Portugal), IEEE PES Summer Power Meeting, Portland, July 1995. "Interfacing with EMTP a general-purpose transmission line model", M.T. Correia de Barros, M.E. Almeida (IST/Univ. Tcnica de Lisboa, Lisbon, Portugal), L. Dub (DEI Simulation Software, Oregon, USA), B. Stein (FGH, Mannheim, Germany) Int'l Conf. on Power systems Transients (IPST ' 95), Lisbon, Portugal, Sept 1995. "Including a wind energy conversion system model in electromagnetic transients program", F. A. G. S. Reis, R. M. G. Castro (IST/Univ. Tcnica de Lisboa, Lisbon, Portugal), A. I. L. Estanqueiro, J. M. Ferreira de Jesus (INETI / ITE, Lisbon, Portugal) Int'l Conf. on Power systems Transients (IPST ' 95), Lisbon, Portugal, Sept 1995.

153

"Tripping analysis of generator negative sequence relay during a transformer energization", M. F. Ushikubo, A. Bichels (COPEL, Curitiba, Brazil) Int'l Conf. on Power systems Transients (IPST ' 95), Lisbon, Portugal, Sept 1995. "Fault arc modeling in EMTP", J. Sousa, D. Santos, M. T. Correia de Barros (IST/Univ. Tcnica de Lisboa, Lisbon, Portugal) Int'l Conf. on Power systems Transients (IPST ' 95), Lisbon, Portugal, Sept 1995. "Advanced representation of power semiconductors using the EMTP", J.A. Martinez-Velasco (Univ. Politcnica de Catalunya, Barcelona, Spain), R. Abdo (Univ. Aix-Marseille II, Marseille, France), G.A. Capolino (Univ. de Picardie, Amiens, France) Int'l Conf. on Power systems Transients (IPST ' 95), Lisbon, Portugal, Sept 1995. "Modelling the electrical and thermal behaviour of metal oxide arresters using MODELS", A. Somogyi, B, Ban, L. Prikler (Technical Univ. of Budapest, Hungary) European EMTP User Group Meeting, Hannover, Germany, Nov 1995 "A gas discharge tube module based on discharge physics for use in ATP-EMTP simulation", A. Larsson, H. Tang, V. Scuka (Uppsala Univ, Sweden) European EMTP User Group Meeting, Hannover, Germany, Nov 1995 "Circuit breaker representation for TRV calculations", J.A. Martinez-Velasco (Univ. Politcnica de Catalunya, Barcelona, Spain), European EMTP User Group Meeting, Hannover, Germany, Nov 1995 "SF6 circuit breaker modelling for shunt reactors switching", Z. Ma, C.A. Bliss, A.F.W. Harris, S.B. Tennakoon (Staffordshire Univ., UK) European EMTP User Group Meeting, Hannover, Germany, Nov 1995 "A neural network vacuum circuit breaker model for simulation of transients overvoltages", J. Kosmac, P. Zunko (Ljubljana Univ., Slovenia) European EMTP User Group Meeting, Hannover, Germany, Nov 1995 "Modelling of curcuit breakers using the type-94 component", J.A. Martinez-Velasco (Univ. Politcnica de Catalunya, Barcelona, Spain), European EMTP User Group Meeting, Hannover, Germany, Nov 1995

154

"Postprocessing of measured transient data using MODELS in the ATP-EMTP", M. Kizilcay (FH Osnabrueck, Germany) L. Dub (DEI Simulation Software, Oregon, USA), European EMTP User Group Meeting, Hannover, Germany, Nov 1995 "Investigation of transformer differential protection schemes by using ATP-MODELS", M.M. Saha, B. Hillstrm, B. Kasztenny, E. Rosolowski (ABB Network Partner, Vsteras, Sweden) European EMTP User Group Meeting, Hannover, Germany, Nov 1995 "A new method for EMTP implementation of nonlinear components", J.A. Martinez-Velasco (Univ. Politcnica de Catalunya, Barcelona, Spain), Proc. 12th Power Systems Computation Conference, Dresden (Germany), August 1996.

155

INDEX

A

Algorithm control .............................................................................. 32, 126 Arithmetic operators................................................................................. 59 Arrays ................................................................................ 7, 8, 14, 61, 143 Assigning data values .............................................................................. 71 Assigning input values ............................................................................. 71 Assigning output values ........................................................................... 72 Assigning values .............................................................................. 32, 123 Assignment operator................................................................................ 10 ATP inputs ................................................................................... 77, 78, 80 ATP outputs ............................................................................................. 83 ATP variables........................................................................................... 82

B

backtime( ) ............................................................................................. 152 backval( ) ............................................................................................... 152 Basic aspects......................................................................................... 2, 4 Blank lines ......................................................................................... 11, 87 Block comments....................................................................................... 12 Boolean operators.................................................................................... 59 Boolean values .......................................................................................... 9 Braces '{ }'................................................................................................ 10 Brackets '[ ]' ............................................................................................. 10

C

C programs ........................................................................................ 19, 26 Circuit components .................................................................................. 90 COMBINE statements...................................................................... 45, 127 Comments ............................................................................................... 12 Complex-value functions........................................................................ 103 Conditional control ................................................................................... 40 Constants..................................................................................... 6, 13, 140 Control components................................................................................. 87 Control systems ......................................................................................... 5 Controlling a procedure.................................................................... 32, 126 Curly braces '{ }' ....................................................................................... 10

D

Data ....................................................................................... 6, 14, 71, 128 Delay storage........................................................................... 68, 122, 129 delay( )..................................................................................... 68, 108, 151

156 Delimiters ................................................................................................. 11 Derivative polynomials ............................................................................. 63 Derivatives ............................................................................. 112, 149, 150 derivpol( )................................................................................................. 63 Difference between simulation language and programming language....... 4 Differential equations ....................................................................... 33, 123 Dimensions of MODELS storage in ATP ................................................. 99 DO statements ................................................................................. 44, 126 Dynamic limits.......................................................................................... 37

E

Equal sign ................................................................................................ 10 ERROR statements ......................................................................... 51, 127 EXEC procedure ...................................................................................... 28 Expressions ..................................................................................... 55, 129 External models (either local or foreign) .......................................... 21, 121 External point list for pointlist function...................................................... 25 External programs.................................................................... 6, 19, 26, 95

F

FOR arguments ....................................................................................... 55 FOR statements............................................................................... 43, 126 Foreign functions ............................................................................. 26, 121 Foreign models .......................................................................... 19, 95, 121 Formatting.......................................................................................... 11, 87 Fortran programs ............................................................................... 19, 26 Frequency meter.................................................................................... 106 Frequency-domain use of a model........................................................... 96 Functions ..................................................................... 17, 23, 58, 120, 143

G

Global constants ........................................................................................ 6 Global variables ......................................................................................... 6

H

histdef( )................................................................................................. 153 History.......................................................... 29, 39, 69, 122, 125, 128, 153 histval( ) ................................................................................................. 153

I

IF expressions.......................................................................................... 41 IF statements ................................................................................... 40, 126 Indentation ............................................................................................... 12 INIT procedure ......................................................................................... 28

157 Initialization ............................................................................ 29, 36, 69, 97 Initializing the type-94 component............................................................ 94 Inline comments....................................................................................... 12 Inputs ..................................................................................... 6, 15, 71, 128 Inputs from ATP ..................................................................... 77, 78, 80, 82 Instance of a model.................................................................................. 52 Integrals ..................................................................................... 38, 63, 125 Interpolation on inputs at sub-steps of the simulation .............. 67, 122, 129 Iterated type-94 circuit component........................................................... 91 Iteration and re-updating a model ............................................................ 73 Iteration control ............................................................................ 42, 43, 44

K

Keywords of the MODELS language ..................................................... 135

L

Laplace transfer functions................................................................ 33, 124 Libraries of models and functions .......................................................... 100 Limits ............................................................................................. 9, 37, 60 Linear sum ............................................................................................... 62 List sizes in ATP for MODELS ................................................................. 99 Local constants .......................................................................................... 6 Local models.................................................................................... 18, 121 Local variables ........................................................................................... 6 Logical functions .................................................................................... 145 Logical operators ..................................................................................... 59 Logical values ............................................................................................ 9

M

Min/max tracking.................................................................................... 115 Model description....................................................................... 17, 85, 119 Model instance......................................................................................... 52 Model, MODELS, and MODEL .................................................................. 9 MODELS in ATP .................................................................... 2, 76, 99, 118 MODELS language .................................................................................... 2

N

Named procedures .......................................................................... 30, 123 Names ..................................................................................................... 11 Norton type-94 circuit component ............................................................ 91 Numbers .................................................................................................... 9 Numerical functions ............................................................................... 143 Numerical operators................................................................................. 59 Numerical values ................................................................................. 9, 58

158

O

Operators......................................................................................... 59, 139 Outputs ...................................................................................... 17, 72, 128 Outputs to ATP ........................................................................................ 83

P

Parentheses '( )' ....................................................................................... 10 Parsing..................................................................................................... 11 Plot data as input to a model ................................................................... 78 Plotting results ......................................................................................... 84 Pointlist functions ..................................................................... 24, 110, 120 Polynomials of derivatives ....................................................................... 63 Post-processing existing plot data ........................................................... 78 Pre-defined constants and variables...................................................... 140 Pre-defined functions ............................................................................. 143 predtime( ) ............................................................................................. 152 predval( )................................................................................................ 151 prevval( )................................................................................................ 151 Procedures ...................................................... 17, 28, 32, 53, 59, 122, 127 Programming language.............................................................................. 3 Project........................................................................................................ 6 Prototyping................................................................................................. 6

R

Random value functions ........................................................................ 146 RECORD printout/plotting data ................................................................ 84 REDO statements ............................................................................ 44, 126 Referring to a named value...................................................................... 55 Regular expressions ................................................................................ 55 Repetition control ......................................................................... 42, 43, 44 Results, plotting ....................................................................................... 84 RMS value ............................................................................................. 117

S

Sample/hold model ................................................................................ 113 Signal sources ....................................................................................... 100 Simulation directives .......................................................... 66, 72, 121, 128 Simulation functions............................................................................... 148 Simulation language = Programming language + Time flow ...................... 4 Simulation results, plotting ....................................................................... 84 Simultaneous equations........................................................................... 45 Sources of signal ................................................................................... 100 Special expressions ................................................................................. 62 Square brackets '[ ]' ................................................................................. 10 State of a model....................................................................................... 74

USERS GUIDE TO MODELS IN ATP

159 Statement function arguments ................................................................. 55 Statement functions ......................................................................... 23, 120 Statements....................................................................................... 32, 123 Static limits......................................................................................... 37, 60 Steady-state circuit initialization ............................................................... 97 Submodels ............................................................................................... 17 sum( )....................................................................................................... 62 Syntax of the MODELS language .......................................................... 118

T

TACS ................................................................................................... 5, 80 TACS devices ........................................................................................ 106 Thevenin type-94 circuit component ........................................................ 91 Time step ......................................................................... 66, 122, 128, 141 Track/hold model ................................................................................... 113 Tracking min/max................................................................................... 115

U

USE ITERATE ......................................................................................... 73 USE statements ................................................................... 52, 71, 72, 127 Using a model .............................................................................. 71, 87, 90 Using MODELS in ATP............................................................................ 76

V

Value assignment ............................................................................ 32, 123 Value-holding elements ................................................................. 6, 13, 55 Values........................................................................................................ 9 Variables ...................................................................................... 6, 16, 140 Variables of the MODELS section............................................................ 84 Visibility of value-holding elements ...................................................... 6, 55

W

WHILE statements ........................................................................... 42, 126 White space ....................................................................................... 11, 87 Why use MODELS................................................................................. 2, 6 Windup and no-windup limits ................................................................... 37 write(), write1(), write2() ................................................................... 53, 127 Writing a model ........................................................................................ 13 Writing expressions.................................................................................. 55

Z

Z transfer functions .......................................................................... 33, 125

160

IN CLOSING ...

Further information on the use of MODELS in ATP can be obtained by anonymous ftp from the following two addresses: ftp.ee.mtu.edu in directory pub/atp/models ftp.rrzn.uni-hannover.de in directory pub/special/atp/models The available material includes the following files. Some of these file names are preceded by a three-digit number, for example 964, indicating the year and month of the file: ugmus.zip ugma4.zip lmusw.zip lma4w.zip lmusp.zip lma4p.zip techn.zip libs.zip this Users Guide of MODELS in ATP in Word for Windows 2.0, 8.5x11 format this Users Guide of MODELS in ATP in Word for Windows 2.0, A4 format the Language Manual of MODELS in Word for Windows 2.0, 8.5x11 format the Language Manual of MODELS in Word for Windows 2.0, A4 format the Language Manual of MODELS in WordPerfect 5.1, 8.5x11 format the Language Manual of MODELS in WordPerfect 5.1, A4 format technical notes on MODELS libraries of models and functions, including: - signal sources - complex-value functions - models of the TACS devices 60+ examples illustrating various MODELS features 20+ examples of type-94 circuit components using MODELS

examp.zip typ94.zip

The author of MODELS and of this document can be reached as follows: Laurent Dub DEI 7000 Rowan Road Neskowin, Oregon USA 97149

- ATP QUICK GUIDEUploaded byingrid_monrreal
- RulebookUploaded byRogerio Lucena
- EL-4650, EMTP APLICATION GUIDEUploaded byivanhhn
- Atp Emtp Rule Book Download - diakakaconpue.pdfUploaded bydr_bilt
- EL-4651Uploaded bygrossman1030
- Electromagnetic Transient in Power System and Insulation Coordination StudiesUploaded bybubo28
- ATP Draw TutorialUploaded byMuhammad Majid Altaf
- TRANSFORMER MODELING IN ATP EMTPUploaded bymspd2003
- Vacuum Circuit Breaker Model.pdfUploaded byGovernmentHooker
- - Vacuum Circuit Breaker Current-Zero PhenomenaUploaded bybanua luhu
- Documentation Using EMTPUploaded byNitu Maria Cristina
- Thesis - Simulating Power Quality Problems by Atp-emtpUploaded byAlejandro Ramirez Benites
- TR7 TP133 Full Content Part1 مهمUploaded byqais652002
- ATPDraw%Manual%3.5Uploaded byMarcos Vera
- Comparison of Simulation Tools Atp Emtp and Matlab Simulink for Time Domain Power System Transient StudiesUploaded byramonenrique
- EL EL-4651-V2.pdf-4651-V2Uploaded byDavid Levi
- Atpdraw User ManualUploaded byfancpuintel2
- Power Syst Electromagnetic TransientUploaded bychanchai T
- Surge Arrester ModelingUploaded byJulián García Zamora
- EMTP RVUploaded byหมัง ตู้
- ATP ManualUploaded byJose Jorge Fontalvo
- Power System Harmonic Analysis (Jos Arrillaga Bruce Smith, Neville Watson & Alan Wood)Uploaded byAngel Pm
- Modelling of Distributed Energy Resources With ATP-EMTPUploaded byPhùng Tuấn
- EMTPTBookUploaded byMurugan
- Program ATP EMTP in Overvoltage EducationUploaded byrodrigoct88
- Transmission Line Reference Book - 345 Kv and Above Epri 1982Uploaded byadriasiq3068
- Cable modelling in ATP.docUploaded byswarnankur_ghosh
- Short Circuit Presentation Lecture 14 SC Calculations According to Standard IEC 60909Uploaded byKassem Baalbaki
- Implementation of EMTP-ATP Software in the Study of Electromagnetic Transient PhenomenonUploaded byyourou1000
- atprulebooktr.pdfUploaded bying.jmsolis

- CFD ANALYSIS OF HEAT TRANSFER IN A HELICAL COIL HEAT EXCHANGER USING FLUENTUploaded byAttique Javaid
- DissertationUploaded byNura Lailatussoimah
- Inverter KEBUploaded byDomenico Leuzzi
- EN 12354-1Uploaded byAnonymous iay7d41Pk7
- Cam Design Chap 01Uploaded byzinmgoo
- Vaporsens Technical SummaryUploaded byBen Rollins
- Port a FlowUploaded byRajendra Patil
- DiagrammaticUploaded byapi-3850829
- Seismic CalculationsUploaded byMoganna Gowda
- Epson Aculaser c4200 Service ManualUploaded byhpatel_714706
- Definition of TermsUploaded byErnesto Vergara Jr.
- Group 17 elementsUploaded bytapas kundu
- Irreversibility Analysis of Two and Three Stage Vapour Compression Refrigeration Systems With Multi Evaporators and Flash-Intercooler UsingUploaded byIjrei Journal
- Engineering Mechanics: Statics Lecture 1.pdfUploaded byKhalid Yousaf
- EC2 - How to Design Concrete StructuresUploaded byThomas Crowe
- literature review of wind tunnelsUploaded byNeerajVerma
- Ventris Midi Cc Guide CompleteUploaded byfitzekack
- DPP1-Solution-Number System and Quadratic Equation 1Uploaded bySachin Arora
- Capital Budgeting 1Uploaded byDaniel Dia
- Math230 LectureNotes 5 New2Uploaded byFoo
- Modern Physics for IITJEEUploaded byMohammed Aftab Ahmed
- En Nastran FX-catalogUploaded bymariostructural2010
- Q Factor in Forest ManagementUploaded byBidya Nath
- FF_PremixPPM3b1Uploaded byworstkind
- DMMUploaded byAyyar Kandasamy
- MS 1462-2-2-2010 (CONFIRMED 2015) SOILUploaded byGan Chin Phang
- A InstantonUploaded bybayareaking
- Final SPPU -Mech- Structure _29.03.2016Uploaded byvitthalmech8687
- SolarWall - Pushing the Envelope Magazine Article - Ontario Building Envelope CouncilUploaded byconserval
- ASTM C117(1).pdfUploaded byDrinar Evan