Content-type: text/html Man page of yacts

yacts

Section: (1)
Updated: 12 July 2015
Index Return to Main Contents
 

NAME

yacts - yet another continuous time simulator  

SYNOPSIS

yacts [-h] [-V]
yacts [-v] [-i]
yacts [-o out] [-v] <script file>
yacts [-s] [-v] <script file>
yacts [-p] [-v] [-f] [-c nc] [-j nj] [-n fn] [-o out] <script file>

 

DESCRIPTION

This program solves a system of ordinary differential equations, specified by the yacts script, given to it as an argument. The script must define several special variables, but is otherwise free to make any additional computations. It may also contain more definitions, which are parsed, but not evaluated if they do not participate in defining values of special variables.

The yacts script is a J+ program (and, at the same time, a valid J program, see J language documentation on www.jsoftware.com), subject to lazy evaluation by yacts interpreter. It consists of series of (possibly functional) assignments, like a bunch of mathematical formulae written on a sheet of paper. Continuing this similarity, J+ language is not imperative in the sense that it does not prescribe that the assignments will be executed sequentially in order of specification. Rather, the program is reinterpreted each time a driver (yacts in this case) asks J+ interpreter for the value of a specific variable. The interpreter then performs minimum necessary calculations to compute the requested value, while keeping track of changed variables (the driver program can change them too) and their dependencies. In short, J+ is J, supplemented by lazy execution and aggressive dead code elimination.  

J PLUS LANGUAGE

Consider the following J+ script, which (as all J+ scripts) is a valid J program:

         a =: 1
         b =: (a =: a + 2) + (a =: a + 1)

When it is loaded into J+ interpreter, it is first converted into the static single assignment (SSA) form.

         a =: 1
         b =: (a2 =: a1 + 2) + (a1 =: a + 1)

Suppose now the driver program asks J+ interpreter for the value of "a". The interpreter finds the latest version of the requested variable and executes the code, necessary to compute it. In this case

         a =: 1
         a1 =: a + 1
         a2 =: a1 + 2

and the driver will receive 4. The interpreter keeps track of all the computed values, so, if the driver subsequently requests "b", only the following statement will be evaluated

         b =: a2 + a1

returning 6. The driver may also set the values of the variables, but, in contrast to requesting the values, the _first_ version of the variable gets modified. So, for example, if interpreter sets the value of "a" to 5 and then requests "a" again, the following code will be executed

         a1 =: a + 1
         a2 =: a1 + 2

returning 8. That's, basically, all the J+ language in a nutshell, it is really that simple. But, coupled with J's concise array operations and the yacts numerical library, it is powerful enough to eloquently express a number of complex mathematical simulations and process them efficiently in single-CPU and cluster environment.  

YACTS VARIABLES

YACTS is a program, which drives the J+ interpreter to solve the problems, expressed as systems of coupled ordinary differential equations. In fact, it is an example program, using J+ interpreter, you can (and encouraged to) write your own similar drivers for other problems.

Striving for simplicity, YACTS defines only three "special" variables, defining the simulation itself, and an arbitrary number of "output" variables for rendering (in textual or graphical form) various derived quantities. The output variables are not part of simulation and do not take part in trajectory file name hashing (more on this later).

The variables are:

T
time, scalar. Initial, current and time of the next frame to compute.
S
state, array. The initial and current state of the simulation.
dSdT
state change. Change of state in time, used to compute the future state.
OUT
literal, vector. The default output variable. its value is computed and printed to standard output stream when the current frame is processed. It is used to render the results in textual and graphical (with the help of external utilities) form.

The user may define additional, arbitrarily named, output variables for alternative kinds of output. The names of these variables can be specified via the "-o" option to yacts.

Consider, for example, a trivial YACTS script, outputting the constant value:

       T=:0
       S=:1
       dSdT=:0
       OUT=: ": T, S
       T=:T+0.5

The time starts at 0 and the state, initially, is 1. The time derivative is 0 (that's why the initial value will never change). The time between frames is 0.5 units. That is, the ODE will be integrated (possibly evaluating dSdT many times) until the time is increased by 0.5 and then the frame will be written to disk (in trajectory file) and processed (the "OUT" variable will be computed and its result is printed to stdout). Running this script will produce

       $yacts constant
       0 1
       0.5 1
       1 1
       1.5 1
       2 1
       ...
       ...

etc on standard output, indefinitely, very fast, and also write the trajectory file named constant_<some_seemingly_random_hex_number>.trj . The output shows the current time and state at each frame (just as requested in the variable OUT) and the "random" number is the sha1 hash of the "meaningful" part of the YACTS script. The word "meaningful" in this context means "all the statements, influencing the trajectory". That is "T", "S" and "dSdT". Changes in the "OUT" variable definition, as well as code, that influences "OUT" (but not "T", "S", "dSdT") will not contribute to the trajectory hash. Thus, the purpose of the hash is to help keep track of various simulation parameters (however many the user will define) and never mix them up in the same trajectory.

Now for something a little more complex. Pendulum. :-) The pendulum equation is a second order differential equation, which can be written as system of two ODEs:

          T =: 0
          S =: 0 0.1        NB. position and velocity
          sin =: 1&o.
          dSdT =: ({: , (_0.1 * sin)@{.) S
          OUT =: 100 gnuplot {. S
          T =: T+0.3

the magic of "gnuplot" function is that when output of this yacts script is piped through "gnuplot" program, like this

          $ yacts pendulum | gnuplot

the user will see the sliding graphical plot of the last 100 points of the pendulum position as function of time.

There are more visualization and numerical computation functions, defined in the YACTS library.  

YACTS LIBRARY

J is a very powerful language with a long history. However, it is not the only programming language. There are other languages, in which, historically, a number of very useful and efficient numerical algorithms were implemented. J+ provides (and YACTS makes use of) an efficient interface between C++ (or, potentially, any other compiled language) and J. This interface makes it easy to "plug in" additional well tested numerical code to be used seamlessly within J+ environment.

For now, the following functions are defined:

fft
(monad, dyad) multidimensional Fast Fourier Transform (FFT) with FFTW library, monadic case makes the forward transform, while the dyadic case with the left argument of "1" the backward transform. The transform is unnormalized: forward transform, followed by the backward one, will multiply data by the number of elements in the original array.
fftr2c
(monad) multidimensional real-to-complex forward FFT.
fftc2r
(dyad) multidimensional complex-to-real backward FFT. The left argument is the shape of the resulting real array (this information is not fully preserved by fftr2c).
int
(adverb). The right argument of the resulting verb specifies the integration limits, while the optional left argument the requested error tolerances. This adverb can handle one-dimensional integrals with infinite limits and mild singularities on endpoints (or at specified points in the middle of interval) using quadvav pure J integrator (it uses essentially the same algorithm as "quadgk" function in MATLAB, but, additionally, supports vector integrands) and will use cuhre algorithm from the Cuba library for higher-dimensional (also, possibly vector) integrals.
memo
(adverb) similar to J memoization adverb "M.", memo caches the computed results of a verb, so that repeated invocation of the same verb on the same arguments does not cause the result to be recalculated. Unlike "M.", memo stores the cache permanently on disk, preserving it between invocations of yacts.
loadtrj
(dyad) Loads the last frame from the YACTS trajectory file, specified by its right argument. The left argument specifies the shape of the resulting array (the number of equations in the loaded trajectory must fit exactly into the specified shape for this operation to succeed). Useful for chaining several simulations together.
gnuplot
(monad,dyad) Displays a set of graphs in a sliding window when its output is piped via "gnuplot" program. The left argument is the number of points to accumulate in the window (default 50), the right argument is a vector of values, each value (when accumulated via several invocations) will produce a separate line graph in the plot window.
rasterplot
(dyad) Interpolates and plots scalar or vector fields in a grayscale raster. The left argument is a vector of two values, specifying the dimension of the final raster, the right argument is either rank 2 array (in which case rasterplot performs bilinear interpolation of its values to cover the whole specified raster dimension) or rank 3 array with the last dimension equal to 2 (this specifies the two-dimensional vector field of two-dimensional vectors, which is interpolated and rendered using the Line Integral Convolution, LIC, method, producing a grayscale image, showing the vector field flow). In both cases the result is 2-dimensional array with the dimensions, specified as left argument to the rasterplot, additionally, in the case of vector field plot, the values lie in the range [0,1].
pnmplot
(monad, dyad) renders grayscale or color raster in Portable Anymap (PNM) format. The left argument specifies the number of color gradations (255 by default) in the resulting image. The right argument is either grayscale raster (2-dimensional array) or color raster (rank 3 array with the last dimension of 3, corresponding to RGB components of color). In both cases the elements of arrays are assumed to lie in the interval [0,1].

The following dialog in YACTS interactive mode (available via "-i" option) illustrates the behavior of some of these library functions:

       |   fft 1 2 3 4 5
       |15 _2.5j3.44095 _2.5j0.812299 _2.5j_0.812299 _2.5j_3.44095
       |   1 fft fft 1 2 3 4 5
       |5 10 15 20 25
       |   (# %~ 1 fft fft) 1 2 3 4 5
       |1 2 3 4 5
       |   (# %~ # fftc2r fftr2c) 1 2 3 4 5
       |1 2 3 4 5
       |   fft 1 2 3 4 ,: 5 6 7 8
       | 36 _4j4 _4 _4j_4
       |_16    0  0     0
       |   ([: % *:) int 1 _
       |1
       |   ^. int 0 1
       |_1
       |   ([: +/ *:) int 0 1 ,: 0 1
       |0.666667
       |   ([: +/ *:) int 0 1 , 0 1 ,: 0 1
       |1
       |   *: int 0 1 , 1 2 ,: 2 3
       |0.333333 2.33333 6.33333
       |   a =: 3 : '(2&((1!:2)~) ''cache miss'') ] y'
       |   a 3
       |cache miss
       |3
       |   a 3
       |cache miss
       |3
       |   a memo 3
       |cache miss
       |3
       |   a memo 3
       |3

Vertical line on the left denotes the left boundary of the terminal window.  

INTEGRATING AND PROCESSING

While integration of the ODE is inherently sequential, processing the frames (provided they are already calculated and stored in the trajectory file) is inherently parallel. yacts provides a number of options to make use of this fact. In particular, it has an option "-s" to disable frame processing (making the current instance of yacts dedicated to integrating the ODE and saving the trajectory frames, without processing the OUT block).

While the first instance of yacts does that, another one may be launched (with the same problem definition, but different command line options), which would not compute trajectory at all, but, instead, read the frames from the trajectory file (written out by the first instance in parallel) and process _only_ the OUT block on each frame. There is also "-f" option, making this second instance to hang at the end of the trajectory file, when it reaches it, waiting for and processing the new frames as they are being appended (much like "tail -f"). Even better, with the help of "-o" option, several instances of "process only" YACTS may be used to display various aspects of simulation in different windows.

Another useful options are "-c" and "-j", they make it easy to submit array jobs on computing clusters, processing the trajectory frames in parallel (all the while the first instance continues the integration, as facilitated by the "-n" option). This may be useful if processing of the frames is computationally intensive (e.g. involves sophisticated rendering like LIC).  

OPTIONS

-h
The option -h or invocation with no arguments displays help.
-V
Display versions of yacts and of the libraries used.
-i
Interactive mode, enters read-eval-print loop with all the yacts library functions defined. Similar in function to jconsole, useful for developing and testing individual sentences.
-s
Simulation only, disable processing of OUT blocks.
-p
Processing only, disable simulation.
-v
Display progress of some long running verbs. Progress reports are printed to stderr as a running percentage. Currently int and rasterplot (when computing LIC) will do this.
-c nc
Job number of the current instance in the parallel job array. Must be 0<=nc<nj. Default: 0.
-j nj
Total number of jobs in the parallel job array. Default: 1.
-n fn
Maximum number of frames to process. Processing stops, after processing this many frames. Default: number of frames in the trajectory file.
-f
Follow. Wait and follow past the end of the trajectory file (like "tail -f"). In case of parallel processing the -f option applies to the last job in the array (with nc=nj-1). Please note that it is absolutely necessary to give -n option in this case.
-o out
The name of output variable to gather output from. Default: OUT
 

SEE ALSO

yacts-trj(1), gnuplot(1), display(1), convert(1).  

ACKNOWLEDGMENTS

Most of the power of YACTS comes from the fact that it uses J programming language, developed by Kenneth E. Iverson and Roger K.W. Hui under umbrella of JSoftware, Inc and released recently under the terms of GNU General Public License. The ODE integration is done via SUNDIALS library, developed by Nonlinear Solvers and Differential Equations Project at Center for Applied Scientific Computing in Lawrence Livermore National Laboratory. The Fastest Fourier Transform in the West (FFTW) library was developed at MIT by Matteo Frigo and Steven G. Johnson. The Cuba library is being developed at the Max Planck Institute for Physics in Munich by Thomas Hahn, in there the Cuhre algorithm (used by yacts) is by J. Berntsen, T. Espelid and A. Genz. The algorithm, implemented and extended by quadvav numerical integrator, is originally by Lawrence F. Shampine, professor emeritus at Southern Methodist University.  

BUGS

Probably many. Most annoying, as of current alpha version, is poor error handling. In many cases, instead of giving error message and continuing, yacts verbs, when facing wrong arguments or other user-provoked error conditions, will fail assertions and make yacts quit. The error handling will be reworked in future versions.  

AUTHOR

Konstantin L. Metlov <metlov@fti.dn.ua>


 

Index

NAME
SYNOPSIS
DESCRIPTION
J PLUS LANGUAGE
YACTS VARIABLES
YACTS LIBRARY
INTEGRATING AND PROCESSING
OPTIONS
SEE ALSO
ACKNOWLEDGMENTS
BUGS
AUTHOR

This document was created by man2html, using the manual pages.
Time: 18:43:10 GMT, July 12, 2015