wasora
wasora's an advanced suite for optimization and reactor analysis
wasora's an advanced suite for optimization and reactor analysis
Abstract. wasora is a free computational tool designed to aid a cognizant expert—i.e. you, whether an engineer, scientist, technician, geek, etc—to analyze complex systems by solving mathematical problems by means of a high-level plain-text input file containing algebraic expressions, data for function interpolation, differential equations and output instructions amongst other facilities. At a first glance, it may look as another high-level interpreted programming language, but—hopefully—it is not: wasora should be seen as a syntactically-sweetened way to ask a computer to perform a certain mathematical calculation. For example, the famous Lorenz system may be solved by writing the three differential equations into a plain-text input file as humanly-friendly as possible. Although its ultimate subject is optimization of nuclear reactors, it may hopefully help you with the tough calculations that usually appear when working with problems that have some kind of complexity, allowing the user to focus on what humans perform best—expert judgment and reaching conclusions. wasora is free software released under the terms of the GNU Public License, so corrections, improvements and additions are welcome and encouraged.
Introduction
History and motivation
What wasora is
What wasora is not
Licensing
Quick start
Download and run
Compiling the source
The test suite
The Real Book
Mailing list
Detailed description
Design basis
Execution and installation
Interaction with other UNIX tools
Syntax Highlighting
The type problems wasora solves
Input preparation
Parser rules
Definitions and instructions
Symbols
Functions
Types of problems
Compilation and Installation
Rationale
Architectures
Test suite
Plug-ins
Loading
Compiling and installing
Licensing issues
Reference
Keywords
Special variables
Built-in functions
Built-in functionals
Buiilt-in vector funtions
To be done.
Initial-value ordinary differential equations arise in a great variety of subjects in science and engineering. Classical mechanics, chemical kinetics, structural dynamics, heat transfer analysis and dynamical systems, amongst other disciplines, heavily rely on equations of the form $$ \dot{\vec{x}} = \vec{F}(\vec{x}) $$
During my years of undergraduate student, whenever I faced these kind of equations, I had to choose one of the following three options:
Regardless of this situation, in my last year of Nuclear Engineering I ran into a nuclear reactor model that especially called my attention and forced me to re-think the ODE-solving problem issue. The model was implemented in Simulink, a software which I had been told was the actual panacea for the engineering community—and yet I was using for the very first time. When I opened the file and took a look at the model, I was not able to understand any of the several screens the model contained. Afterward, somebody explained to me that a set of unintelligible blocks that were somehow interconnected in a rather cumbersome way was how the reactor power was computed. I wish I had a copy of the screen in order to illustrate how shockwing it was to me.
The equation represented by what seemed to me as a complex topology problem was as simple as $$ \frac{dn}{dt} = \frac{\rho - \beta}{\Lambda} + \lambda \cdot c $$
My first reaction was to ask why someone would prefer this instead of writing something like
n_dot = (rho - beta)/Lambda + lambda*c
in a text file. I do not remember what the answer was, and I still do not understand why would somebody prefer to solve a very simple differential equation by drawing blocks with no mathematical sense whatsoever.
That morning I realized that in order to to transform a user-defined string representing a differential equation into something that an ODE-solving library such as the GNU Scientific Library would understand, only a good algebraic parser plus some simple interface routines were needed. The following two years were very time-consuming for me, so I was not able to undertake such a project. Nevertheless, eventually I graduated and my focus shifted away from academic projects and some gaps of time for freelance programming popped up. I started to write wasora from scratch, and one of the first features I included was and adaptation of a small algebraic parser posted in stackoverflow.com (which should be replaced by a more efficent tree-based parser), freely available under the Creative Commons License. Before I became aware, I was very close to arriving at the tool that would have met my needs when I was an engineering student. And, with some luck, at a tool that would meet somebody else's needs as well. Hence, this is the way wasora enters into the scene.
To be done.
To be done.
Wasora is free software—both as in free speech and as in free beer, although the first meaning is far more important than the second one—and is distributed under the terms of the GNU General Public License version 3. In words of the Free Software Foundation,
Nobody should be restricted by the software they use. There are four freedoms that every user should have:0. the freedom to use the software for any purpose,
1. the freedom to change the software to suit your needs,
2. the freedom to share the software with your friends and neighbors, and
3. the freedom to share the changes you make.
When a program offers users all of these freedoms, we call it free software.
Developers who write software can release it under the terms of the GNU GPL. When they do, it will be free software and stay free software, no matter who changes or distributes the program. We call this copyleft: the software is copyrighted, but instead of using those rights to restrict users like proprietary software does, we use them to ensure that every user has freedom.
Not only does wasora provide all the four basic freedoms to the software user, but also encourages her to study, understand, analyze and hack it. And of course, to share the associated discoveries, suggestions, improvements and fixed bugs under the terms of the GNU GPL—especially with wasora's original author. To sum up:
Wasora is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.Wasora is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with wasora. If not, see http://www.gnu.org/licenses/.
The codes in the wasora suite rely on different free libraries—all of them available also under different free licenses—depending on the kind of problem each code solves. Nonetheless, the wasora framework and all the particular codes depend on the GNU Scientific Library, released freely under the GNU General Public License version 3. Check the documentation of each particular code in the suite for details of the needed libraries in each case. A copy of the GNU General Public License can be found in each of the code's distribution tarball.
License (see the section sec:licensing for details). These codes may be run as standalone processes or glued together to obtained coupled models. They all are based on a common framework that provides both mathematical—such as algebraic parsing, function definition, data interpolation, differentiation and integration procedures, etc.—and general-purpose routines like input file parsing, writing the obtained results in a concise manner and inter-process communication routines.
means a mature engineering solution. The second one is that no further reference to the PhD thesis is going to be done neither in this document nor in the documentation of the individual codes in the wasora suite—although probably the proper reference will be added to the bibliography of those future versions of this document that are to appear with the word project removed. And finally, as stated above, even though the motivation of the work is the optimization of nuclear reactors, some codes like the DAE solver mochin or the control logic analysis code colach, with the aid of even more luck, may be of interest in other fields of engineering.
TBD.
TBD.
TBD.
TBD.
TBD.
TBD.
To be done.
Rule zero: "use a computer to solve a mathematical model"
Rule one (input): "simple inputs ought to need simple outputs".
Rule two (output): "the output should be completely defined by the user"
Rules three--twenty one: Eric Raymond's Rules of UNIX Philosophy:
workflow depends on the user, recommendation: unix
qdp, gnuplot, awk, sed
To be done
TBD.
TBD.
TBD.
TBD.
TBD.
TBD.
TBD.
TBD.
TBD.
TBD.
TBD.
Algebraic
TBD.
Point-wise
TBD.
Binary routine
TBD.
TBD.
TBD.
TBD.
TBD.
TBD.
TBD.
TBD.
TBD.
TBD.
TBD.
TBD.
TBD.
TBD.
TBD.
TBD.
TBD.
This chapter contains the reference sheet for wasora version 0.3.96 automatically generated from specially-marked comments in the source code. Please bookmark this page for future reference.
This section lists all the primary keywords that wasora understands in the input file, along with the secondary keywords and the arguments that may be passed. Throughout the section, the following typographic convention is used:
construction | description |
KEYWORD | a keyword that is recognized by wasora (case insensitive) |
identifier | a generic identifier |
var | a variable identifier |
vector | a vector identifier |
matrix | a matrix identifier |
function | a function identifier |
file | a file identifier |
filepath | a file path |
expr | an algebraic expression that may involve any valid object |
num_expr | an algebraic expression that may involve only constants and NUMBER s |
string | a text string |
printf_format | a C printf -like format string expecting a floating point argument (i.e. %g ) |
[ xxx ] | the construction xxx is optional and may or may not be given |
{ xxx | yyy } | either xxx or yyy |
A primary keyword must start a new line. Leading blanks are allowed. Keywords are case insensitive, they are shown here capitalized because of style. Identifiers are case sensitive. Algebraic expressions work as expected, i.e. basic operators are +
, -
, *
and /
. The exponentiation operator is ^
and brackets (
& )
change operator hierarchies as usual:
# expressions can contain variables and functions, whose
# arguments may be expressions themselves, and so on
c = (1 + sin(pi/4)^(5/2))/(1 - log(abs(a-b)))
Logical operators <
, >
, |
(or) and &
(and) can be used. The equal sign =
is an operator within an algebraic expression. Keep in mind that they operate on floating point arithmetic:
a = 1
b = 2
IF (a+eps)<1&(b+eps)>1
PRINT "both a and b are less than one"
ENDIF
Comments start with a hash #
and last until the end of the line. If an argument to a keyword needs to include a space, double quotes should be used. The following snippets illustrates the behavior of wasora's parser:
# this file shows some particularities about the wasora parser
# there are primary and secondary keywords, in this case
# PRINT is the primary keyword and TEXT is the secondary, which
# takes a single token as an argument, in this case the word hello
PRINT TEXT hello
# if the text to be printed contains a space, double quotes should be used:
PRINT TEXT "hello world"
# if the text to be printed contains quotes, they should be escaped:
PRINT TEXT "hello \"world\""
# it does not matter if the argument is a string or an expression, whenever
# a certain argument is expected, either spaces are to be remove or
# the arguments should be enclosed in double quotes:
PRINT 1 + 1
PRINT "1 + 1"
PRINT 1+1
# to insert comments, the hash `#` character is used
PRINT sqrt(2)/2 # comments may appear in the same line as a keyword
# in case a hash character is expected to appear literally in an argument
# it should be escaped to prevent wasora to ignore the rest of the line:
PRINT TEXT "\# this is a commented output line" # this is a wasora comment
# secondary keywords and/or arguments can be given in different lines either by
# a. using a continuation marker composed of a single backslash:
PRINT sqrt(2)/2 \
sin(pi/4) \
cos(pi/4)
# b. enclosing the lines within brackets `{` and `}`
PRINT sqrt(2)/2 \ {
sin(pi/4) \
# comments may appear inside brackets (but not within continued lines)
cos(pi/4) }
# arguments may be given in the command line after the input file
# they are referred to as $1, $2, etc. and are literally used
# i.e. they can appear as arguments or even keywords
# if a $n expressions appears in the input file but less than n
# arguments were provided, wasora complains
# this behavior can be avoided by giving a default value:
DEFAULT_ARGUMENT_VALUE 1 world
DEFAULT_ARGUMENT_VALUE 2 2
PRINT TEXT "hello $1"
PRINT sqrt($2)/$2
# try executing this input as
# $ wasora parser.was WORLD
# $ wasora parser.was WORLD 3
# if a literal dollar sign is to part of an argument, quote it with a backslash:
PRINT TEXT "argument \$1 is $1"
The rest of the section contains all the keywords that wasora understands.
=
<var>[ [<expr_tmin>, <expr_tmax>] | @<expr_t> ] = <expr> <vector>(<expr_i>)[<expr_i_min, expr_i_max>] [ [<expr_tmin>, <expr_tmax>] | @<expr_t> ] = <expr> <matrix>(<expr_i>,<expr_j>)[<expr_i_min, expr_i_max; expr_j_min, expr_j_max>] [ [<expr_tmin>, <expr_tmax>] | @<expr_t> ] = <expr>
.=
{ 0[(i[,j]][<imin:imax[;jmin:jmax]>] | <expr1> } .= <expr2>
ABORT
Catastrophically abort the execution and quit wasora.
ABORT
Whenever the instruction ABORT
is executed, wasora quits without closing files
or unlocking shared memory objects. The objective of this instruction is, as
illustrated in the examples, either to debug complex input files and check the
values of certain variables or to conditionally abort the execution using IF
clauses.
# a complex problem definition
# [...]
#
NUMBER nrefl1 4
NUMBER nrefl2 24
NUMBER nz 30
VECTOR deltaz SIZE nz
deltaz(i)<1:nrefl1-1> = 48.2/(nrefl1-1)
deltaz(i)<nrefl1:nrefl2> = 530.7/(nrefl2-nrefl1+1)
deltaz(i)<nrefl2+1:nz> = 34.4/(nz-nrefl2)
# check if we built the deltaz vector correctly
PRINT_VECTOR i deltaz
ABORT
# more complex problem definitions follow
# [...]
#
PHASE_SPACE n c
VAR rho
beta = 550e-5
Lambda = 5e-4
lambda = 0.15
n_0 = 1
c_0 = beta/(lambda*Lambda)
SEMAPHORE rho_ready WAIT
READ SHM_OBJECT rho_shm rho
n_dot .= (rho - beta)/Lambda * n + lambda*c
c_dot .= beta/Lambda * n - lambda*c
WRITE SHM_OBJECT pow_shm n
SEMAPHORE pow_ready POST
PRINT t n rho c
# if power is greater than 150% quit
IF n>1.5
PRINT TEXT "unacceptable power"
ABORT
ENDIF
ALIAS
Defines a scalar alias of an already-defined indentifier.
ALIAS <name> <identifier>
CALL
Executes a previously dynamically-loaded user-provided routine.
CALL <name> [ expr_1 expr_2 ... expr_n ]
CLOSE
CLOSE
CONST
Marks a scalar variable, vector or matrix as a constant.
CONST name_1 [ <name_2> ] ... [ <name_n> ]
DEFAULT_ARGUMENT_VALUE
Give a default value for an optional commandline argument.
DEFAULT_ARGUMENT_VALUE <num_expr> <string>
If a $n
construction is found in the input file but the
commandline argument was not given, the default behavior is to
fail complaining that an extra argument has to be given in the
commandline. With this keyword, a default value can be assigned if
no argument is given, thus avoiding the failure and making the argument
optional.
DIFFERENTIAL
DIFFERENTIAL { <vars> | <vectors> | <matrices> }
FILE
Defines a file, either as input or as output, for further reference.
< FILE | OUTPUT_FILE | INPUT_FILE > <name> <printf_format> [ expr_1 expr_2 ... expr_n ] [ INPUT | OUTPUT | MODE <fopen_mode> ] [ OPEN | DO_NOT_OPEN ]
FIT
FIT <function_to_be_fitted> TO <function_with_data> VIA <var_1> <var_2> ... <var_n> [ GRADIENT <expr_1> <expr_2> ... <expr_n> ] [ RANGE_MIN <expr_1> <expr_2> ... <expr_n> ] [ RANGE_MAX <expr_1> <expr_2> ... <expr_n> ] [ DELTAEPSREL <expr> ] [ DELTAEPSABS <expr> ] [ MAX_ITER <expr> ] [ VERBOSE ] [ RERUN | DO_NOT_RERUN ]
FUNCTION
Defines a function of one or more variables.
FUNCTION <name>(<var_1>[,var2,...,var_n]) { [ = <expr> ] | [ FILE_PATH <file_path> ] | [ ROUTINE <name> ] | [ VECTOR_DATA <vector_1> <vector_2> ... <vector_n> <vector_n+1> ] } [COLUMNS <num_expr_1> <num_expr_2> ... <num_expr_n> <num_expr_n+1> ] [ INTERPOLATION_THRESHOLD <expr> ] [ INTERPOLATION { linear | polynomial | spline | spline_periodic | akima | akima_periodic | nearest | rectangle } ] [ DATA <num_expr_1> <num_expr_2> ... <num_expr_N> ]
HISTORY
Record the time history of a variable as a function of time.
HISTORY <variable> <function>
IF
Begins a conditional block.
IF expr
<block_of_instructions_if_expr_is_true>
[ ELSE ]
[block_of_instructions_if_expr_is_false]
ENDIF
IMPLICIT
Defines whether implicit declaration of variables is allowed or not.
IMPLICIT { NONE | ALLOWED }
By default, wasora allows variables (but not vectors nor matrices) to be
implicitly declared. To avoid introducing errors due to typos, explicit
declaration of variables can be forced by giving IMPLICIT NONE
.
Whether implicit declaration is allowed or explicit declaration is required
depends on the last IMPLICIT
keyword given, which by default is ALLOWED
.
# implicit declaration is allowed by default
a = 1
# from now on, explicit declaration is needed
IMPLICIT NONE
VAR b
b = 2
# we now go back to implicit declarations
IMPLICIT ALLOWED
c = 3
PRINT %g a b c
INCLUDE
Include another wasora input file.
INCLUDE <file_path> [ FROM <num_expr> ] [ TO <num_expr> ]
Includes the input file located in the string file_path
at the current location.
The effect is the same as copying and pasting the contents of the included file
at the location of the INCLUDE
keyword. The path can be relative or absolute.
Note, however, that when including files inside IF
blocks that instructions are
conditionally-executed but all definitions (such as NUMBERS
) are processed at
parse-time independently from the evaluation of the conditional.
The optional FROM
and TO
keywords can be used to include only portions of a file.
VAR a
# the input file compute.was should compute
# the value of variable a
INCLUDE compute.was
PRINT a
# this file is included2.was
b = 1
PRINT "a is greater than a certain threshold"
a = 0.2
IF a>0.5
INCLUDE included2.was
ENDIF
# although b is set to one only if a>0.5, it is properly defined
# and can be used in a PRINT because the definitions are not
# influenced by conditional blocks
PRINT %g b
# include a file that depends on the commandline argument
VAR a
INCLUDE case-$1.was
PRINT TEXT "result for case $1:" a
INITIAL_CONDITIONS_MODE
Defines how initial conditions of DAE problems are computed.
INITIAL_CONDITIONS_MODE { AS_PROVIDED | FROM_VARIABLES | FROM_DERIVATIVES }
In DAE problems, initial conditions may be either:
AS_PROVIDED
)FROM_VARIABLES
)FROM_DERIVATIVES
)FROM_VARIABLES
option means calling IDA's IDACalcIC
routine with the parameter IDA_YA_YDP_INIT
.
The FROM_DERIVATIVES
option means calling IDA's IDACalcIC
routine with the parameter IDA_Y_INIT.
Wasora should be able to automatically detect which variables in phase-space are differential and
which are purely algebraic. However, the DIFFERENTIAL
keyword may be used to explicitly define them.
See the SUNDIALS documentation for further information.
LOAD_PLUGIN
Loads a wasora plug-in from a dynamic shared object.
LOAD_PLUGIN { <file_path> | <plugin_name> }
A wasora plugin in the form of a dynamic shared object (i.e. .so
) can be loaded
either with the LOAD_PLUGIN
keyword or from the command line with the -p
option.
Either a file path or a plugin name can be given. The following locations are tried:
./
../
LD_LIBRARY_PATH
/etc/ld.so.cache
/lib
, /usr/lib
, /usr/local/lib
make install
procedure,
the plugin should be loaded by just passing the name to LOAD_PLUGIN
.
LOAD_ROUTINE
Loads one or more routines from a dynamic shared object.
LOAD_ROUTINE <file_path> <routine_1> [ <routine_2> ... <routine_n> ]
M4
Calls the m4
macro processor with definitions from wasora variables.
M4 { INPUT_FILE <file_id> | FILE_PATH <file_path> } { OUTPUT_FILE <file_id> | OUTPUT_FILE_PATH <file_path> } [ MACRO <name> [ <format> ] <definition> ] }
MATRIX
Defines a matrix.
MATRIX <name> ROWS <num_expr> COLS <num_expr> [ DATA num_expr_1 num_expr_2 ... num_expr_n ]
MINIMIZE
MINIMIZE <function> [ METHOD { conjugate_fr | conjugate_pr | vector_bfgs2 | vector_bfgs | steepest_descent | nmsimplex2 | nmsimplex | nmsimplex2rand } [ GRADIENT <expr_1> <expr_2> ... <expr_n> ] [ GUESS <expr_1> <expr_2> ... <expr_n> ] [ MIN <expr_1> <expr_2> ... <expr_n> ] [ MAX <expr_1> <expr_2> ... <expr_n> ] [ STEP <expr_1> <expr_2> ... <expr_n> ] [ VERBOSE ] [ NORERUN ] [ MAX_ITER <expr> ] [ TOL <expr> ] [ GRADTOL <expr> ]
NUMBER
Defines a named number.
NUMBER <name> [ = ] <num_expr>
PARAMETRIC
Sistematically sweeps a zone of the parameter space.
PARAMETRIC <var_1> [ ... <var_n> ] [ TYPE { linear | logarithmic | random | gaussianrandom | sobol | niederreiter | halton | reversehalton } ] [ MIN <num_expr_1> ... <num_expr_n> ] [ MAX <num_expr_1> ... <num_expr_n> ] [ STEP <num_expr_1> ... <num_expr_n> ] [ NSTEPS <num_expr_1> ... <num_expr_n> ] [ OUTER_STEPS <num_expr> ] [ MAX_DAUGHTERS <num_expr> ] [ OFFSET <num_expr> ] [ ADIABATIC ]
PHASE_SPACE
PHASE_SPACE { <vars> | <vectors> | <matrices> }
PRINT
Prints plaint-text data to the standard output or to an output file.
PRINT [ FILE <file_id> | FILE_PATH <file_path> ] [ NONEWLINE ] [ SEP <string> ] [ NOSEP ] [ HEADER ] [ SKIP_STEP <expr> ] [ SKIP_STATIC_STEP <expr> ] [ SKIP_TIME <expr> ] [ SKIP_HEADER_STEP <expr> ] [ <object_1> <object_2> ... <object_n> ] [ TEXT <string_1> ... TEXT <string_n> ]
Each argument object
that is not a keyword is expected to be part of the output,
can be either a matrix, a vector, an scalar algebraic expression. If the given object
cannot be solved into a valid matrix, vector or expression, it is treated as a
string literal if IMPLICIT
is ALLOWED
, otherwise a parser error is raised.
To explicitly interpret an object as a literal string even if it resolves to a valid
numerical expression, it should be prefixed with the TEXT
keyword. Hashes #
appearing literal strings have to be quoted to prevent the parser to treat them as
comments within the wasora input file.
Whenever an argument starts with a porcentage sign '%', it is treated as a
printf-compatible format definition and all the objects that follow it are printed
using the given format until a new format definition is found. All the objects are
treated as double-precision floating point numbers, so only floating point formats
should be given. The default format is '%e'.
Matrices, vectors, scalar expressions, format modifiers and string literals can be
given in the desired order, and are processed from left to right.
Vectors are printed element-by-element in a single row. See PRINT_VECTOR
to print
vectors column-wise. Matrices are printed element-by-element in a row-major fashion
if mixed with other objects but in the natural row and column fashion if it is the
only given object.
If the FILE
keyword is not provided, default is to write to stdout.
If the NONEWLINE
keyword is not provided, default is to write a newline '\\n' character after all the objects are processed.
The SEP
keywords expects a string used to separate printed objects, the default is a tab '\\t' character.
Use the NOSEP
keyword to define an empty string as object separator.
If the HEADER
keyword is given, a single line containing the literal text
given for each object is printed at the very first time the PRINT
instruction is
processed, starting with a hash #
character.
If the SKIP_STEP
(SKIP_STATIC_STEP
)keyword is given, the instruction is processed only every
the number of transient (static) steps that results in evaluating the expression,
which may not be constant. By default the PRINT
instruction is evaluated every
step. The SKIP_HEADER_STEP
keyword works similarly for the optional HEADER
but
by default it is only printed once. The SKIP_TIME
keyword use time advancements
to choose how to skip printing and may be useful for non-constant time-step problems.
PRINT_FUNCTION
Prints one or more functions as a table of values of dependent and independent variables.
PRINT_FUNCTION <function_1> [ { function_2 | expr_1 } ... { function_n | expr_n-1 } ] [ FILE <file_id> | FILE_PATH <file_path> ] [ HEADER ] [ MIN <expr_1> <expr_2> ... <expr_m> ] [ MAX <expr_1> <expr_2> ... <expr_m> ] [ STEP <expr_1> <expr_2> ... <expr_m> ] [ NSTEPs <expr_1> <expr_2> ... <expr_m> ] [ FORMAT <print_format> ]
PRINT_VECTOR
Prints one or more vectors.
PRINT_VECTOR [ FILE <file_id> ] FILE_PATH <file_path> ] [ { VERTICAL | HORIZONTAL } ] [ ELEMS_PER_LINE <expr> ] [ FORMAT <print_format> ] <vector_1> [ vector_2 ... vector_n ]
READ
Reads data (variables, vectors o matrices) from external objects.
[ READ | WRITE ] [ SHM <name> ] [ { ASCII_FILE_PATH | BINARY_FILE_PATH } <file_path> ] [ { ASCII_FILE | BINARY_FILE } <identifier> ] ///kw+READ+usage [ IGNORE_NULL ] [ object_1 object_2 ... object_n ]
SEMAPHORE
Performs either a wait or a post operation on a named shared semaphore.
[ SEMAPHORE | SEM ] <name> { WAIT | POST }
SHELL
Executes a shell command.
SHELL <print_format> [ expr_1 expr_2 ... expr_n ]
SOLVE
Solves a non-linear system of \( n \) equations with \( n \) unknowns.
SOLVE <n> UNKNOWNS <var_1> <var_2> ... <var_n> RESIDUALS <expr_1> <expr_2> ... <expr_n> ] GUESS <expr_1> <expr_2> ... <expr_n> ] [ METHOD { dnewton | hybrid | hybrids | broyden } ] [ EPSABS <expr> ] [ EPSREL <expr> ] [ MAX_ITER <expr> ] [ VERBOSE ]
# solves the system of equations
# y = exp(x)
# x+y = 2
#
SOLVE 2 UNKNOWNS x y RESIDUALS exp(x)-y x+y-2
PRINT " x = " %f x
PRINT " y = " %f y
# solves the system of equations
# y = exp(-f(z)*x)
# x = integral(f(z'), z', 0, z)
# 2 = x+y+z
# where f(z) is a point-wise defined function
FUNCTION f(x) INTERPOLATION akima DATA {
0 0
0.2 0.2
0.5 0.1
0.7 0.8
1 0.5
}
# the initial guess (may be given with the GUESS keyword also)
x = 0.5
y = 0.5
z = 0.5
VAR z'
SOLVE 3 UNKNOWNS x y z METHOD hybrids RESIDUALS {
y-exp(-f(z)*x)
integral(f(z'),z',0,z)-x
x+y+z-2
}
PRINT " x = " %f x
PRINT " y = " %f y
PRINT " z = " %f z
TIME_PATH
Forces transient problems to pass through specific instants of time.
TIME_PATH [ expr_1 ] [ expr_2 ] ... [ expr_n ]
The time step dt
will be reduced whenever the distance between
the current time t
and the next expression in the list is greater
than dt
so as to force t
to coincide with the expressions given.
The list of expresssions should evaluate to a sorted list of values.
VAR
Defines one or more scalar variables.
VAR <name_1> [ <name_2> ] ... [ <name_n> ]
VECTOR
Defines a vector.
VECTOR <name> SIZE <num_expr> [ DATA <num_expr_1> <num_expr_2> ... <num_expr_n> ] [ FUNCTION_DATA <function> ]
WRITE
Writes data (variables, vectors o matrices) to external objects.
See the READ
keyword for usage details.
done
Flag that indicates whether the overall calculation is over.
done_outer
Flag that indicates whether the parametric, optimization of fit calculation is over or not. It is set to true (i.e. \( \neq 0 \)) by wasora whenever the outer calculation is considered to be finished, which can be that the parametric calculation swept the desired parameter space or that the optimization algorithm reached the desired convergence criteria. If the user sets it to true, the current step is marked as the last outer step and the transient calculation ends after finishing the step.
done_static
Flag that indicates whether the static calculation is over or not.
It is set to true (i.e. \( \neq 0 \)) by wasora if step_static
\( \ge \) static_steps
.
If the user sets it to true, the current step is marked as the last static step and
the static calculation ends after finishing the step.
done_transient
Flag that indicates whether the transient calculation is over or not.
It is set to true (i.e. \( \neq 0 \)) by wasora if t
\( \ge \) end_time
.
If the user sets it to true, the current step is marked as the last transient step and
the transient calculation ends after finishing the step.
dt
Actual value of the time step for transient calculations. When solving DAE systems,
this variable is set by wasora. It can be written by the user for example by importing it from another
transient code by means of shared-memory objects. Care should be taken when
solving DAE systems and overwriting t
. Default value is 1/16, which is
a power of two and roundoff errors are thus reduced.
end_time
Final time of the transient calculation, to be set by the user. The default value is zero, meaning no transient calculation.
i
Dummy index, used mainly in vector and matrix row subindex expressions.
infinite
A very big positive number, which can be used as end_time = infinite
or
to define improper integrals with infinite limits. Default is \( 2^{50} \approx 1 \times 10^{15} \).
in_outer_initial
Flag that indicates if the current step is the initial step of an optimization of fit run.
in_static
Flag that indicates if wasora is solving the iterative static calculation. Flag that indicates if wasora is in the first step of the iterative static calculation. Flag that indicates if wasora is in the last step of the iterative static calculation.
in_transient
Flag that indicates if wasora is solving transient calculation.
in_transient_first
Flag that indicates if wasora is in the first step of the transient calculation.
in_transient_last
Flag that indicates if wasora is in the last step of the transient calculation.
j
Dummy index, used mainly in matrix column subindex expressions.
max_dt
Maximum bound for the time step that wasora should take when solving DAE systems.
min_dt
Minimum bound for the time step that wasora should take when solving DAE systems.
ncores
The number of online available cores, as returned by sysconf(_SC_NPROCESSORS_ONLN)
.
This value can be used in the MAX_DAUGHTERS
expression of the PARAMETRIC
keyword
(i.e ncores/2
).
on_gsl_error
This should be set to a mask that indicates how to proceed if an error ir raised in any routine of the GNU Scientific Library.
on_ida_error
This should be set to a mask that indicates how to proceed if an error ir raised in any routine of the SUNDIALS IDA Library.
on_nan
This should be set to a mask that indicates how to proceed if Not-A-Number signal (such as a division by zero) is generated when evaluating any expression within wasora.
pi
A double-precision floating point representaion of the number \( \pi \), equal to
math.h
's M_PI
constant.
realtime_scale
If this variable is not zero, then the transient problem is run trying to syncrhonize the problem time with realtime, up to a scale given. For example, if the scale is set to one, then wasora will advance the problem time at the same pace that the real wall time advances. If set to two, wasora's time wil advance twice as fast as real time, and so on. If the calculation time is slower than real time modified by the scale, this variable has no effect on the overall behavior and execution will proceed as quick as possible with no delays.
rel_error
Maximum allowed relative error for the solution of DAE systems. Default value is
is \( 1 \times 10^{-6} \). If a fine per-variable error control is needed, special vector
abs_error
should be used.
static_steps
Number of steps that ought to be taken during the static calculation, to be set by the user. The default value is one, meaning only one static step.
step_outer
Indicates the current step number of the iterative outer calculation (parametric, optimization or fit). Indicates the current step number of the iterative inner calculation (optimization or fit).
step_static
Indicates the current step number of the iterative static calculation.
step_transient
Indicates the current step number of the transient static calculation.
t
Actual value of the time for transient calculations. This variable is set by
wasora, but can be written by the user for example by importing it from another
transient code by means of shared-memory objects. Care should be taken when
solving DAE systems and overwriting t
.
zero
A very small positive number, which is taken to avoid roundoff
errors when comparing floating point numbers such as replacing \( a \leq a_\text{max} \)
with \( a < a_\text{max} + \) zero
. Default is \( (1/2)^{-50} \approx 9\times 10^{-16} \) .
Function names are case sensitive.
abs
Returns the absolute value of the argument \( x \).
y = abs(x)
PRINT %g sqrt(abs(-2))
# exercise: remove the absolute value from the sqrt argument
$ wasora abs.was
1.41421
$
acos
Computes arc in radians whose cosine is equal to the argument \( x \). A NaN error is raised if \( |x|>1 \).
y = acos(x)
asin
Computes arc in radians whose sine is equal to the argument \( x \). A NaN error is raised if \( |x|>1 \).
y = asin(x)
atan
Computes, in radians, the arc tangent of the argument \( x \).
atan(x)
atan2
Computes, in radians, the arc tangent of quotient \( y/x \), using the signs of the two arguments to determine the quadrant of the result, which is in the range \( [-\pi,\pi] \).
atan(y,x)
PRINT atan(-0.5) mod(atan(-0.5),2*pi)-pi
PRINT atan2(1,-2) mod(atan(-0.5),2*pi)-pi
ceil
Returns the smallest integral value not less than the argument \( x \).
ceil(x)
clock
Returns the value of a certain clock in seconds measured from a certain (but specific)
milestone. The kind of clock and the initial milestone depends on the
optional flag \( f \). It defaults to zero, meaning wall time since the UNIX Epoch.
The list and the meanings of the other available values for \( f \) can be checked
in the clock_gettime (2)
system call manual page.
clock([f])
VAR x y
t1 = clock()
y = 4*integral(integral((x^2+y^2)<1, x, 0, 1), y, 0, 1)
t2 = clock()
PRINT "approximate result = " %g y " took " %.1f t2-t1 " seconds to compute" NOSEP
# exercise: read the clock_gettime manual page and
# compute t2-t1 with other parameters to clock()
$ wasora clock.was
approximate result = 3.14167 took 0.1 seconds to compute
$
cos
Computes the cosine of the argument \( x \), where \( x \) is in radians. A cosine wave can be generated by passing as the argument \( x \) a linear function of time such as \( \omega t+\phi \), where \( \omega \) controls the frequency of the wave and \( \phi \) controls its phase.
cos(x)
cosh
Computes the hyperbolic cosine of the argument \( x \), where \( x \) is in radians.
cosh(x)
d_dt
Computes the time derivative of the signal \( x \) using the difference between the
value of the signal in the previous time step and the actual value divided by the
time step. For \( t=0 \), the return value is zero.
Unlike the functional derivative
, this function works with expressions and not
with functions. Therefore the argument \( x \) may be for example an expression
involving a variable that may be read from a shared-memory object, whose
time derivative cannot be computed with derivative
.
d_dt(x)
end_time = 5
dt = 1/10
t0 = 0.5
r = heaviside(t-t0)
PRINT t r lag(r,1) d_dt(lag(r,1)) r*exp(-(t-t0)) HEADER
# exercise: plot output for different values of dt
$ wasora d_dt.was | qdp -o d_dt
$
deadband
Filters the first argument \( x \) with a deadband centered at zero with an amplitude given by the second argument \( a \).
deadband(x, a)
equal
Checks if the two first expressions \( a \) and \( b \) are equal, up to the tolerance
given by the third optional argument \( \epsilon \). If either \( |a|>1 \) or \( |b|>1 \),
the arguments are compared using GSL's gsl_fcmp
, otherwise the
absolute value of their difference is compared against \( \epsilon \). This function
returns \textsl{exactly} zero if the arguments are not equal and one otherwise.
Default value for \( \epsilon = 10^{-16} \).
equal(a, b, [eps])
exp
Computes the exponential function the argument \( x \), i.e. the base of the natural logarithms raised to the \( x \)-th power.
exp(x)
end_time = 1
PHASE_SPACE x
CONST alpha
alpha = 1.8
x_0 = 1.2
x_dot .= -alpha*x
y = x_0*exp(-alpha*t)
PRINT t x y y-x
expint1
Computes the first exponential integral function of the argument \( x \). If \( x \) equals zero, a NaN error is issued.
expint1(x)
VAR u
E1(x) := expint1(x)
Def(x) := integral(exp(-x*u)/u,u,1,99)
PRINT_FUNCTION E1 Def MIN 1e-2 MAX 2.0 STEP 1e-2 HEADER
expint2
Computes the second exponential integral function of the argument \( x \).
expint2(x)
E2(x) := expint2(x)
guesswho(x) := exp(-x) - x * expint1(x)
PRINT_FUNCTION E2 guesswho MIN 1e-2 MAX 2.0 STEP 1e-2 HEADER
# exercise: which is the limit of guesswho(x) as x approaches to zero?
expint3
Computes the third exponential integral function of the argument \( x \).
expint3(x)
expintn
Computes the \( n \)-th exponential integral function of the argument \( x \). If \( n \) equals zero or one and \( x \) zero, a NaN error is issued.
expintn(n,x)
n = 4
En(x) := expintn(n,x)
guesswho(x) := (1/(n-1)) * (exp(-x) - x * expintn(n-1,x))
PRINT_FUNCTION En guesswho MIN 0.01 MAX 2.0 STEP 1e-2 HEADER
# Try this for different values of n > 1.
floor
Returns the largest integral value not greater than the argument \( x \).
floor(x)
heaviside
Computes the zero-centered Heaviside step function of the argument \( x \). If the optional second argument \( \epsilon \) is provided, the discontinuous step at \( x=0 \) is replaced by a ramp starting at \( x=0 \) and finishing at \( x=\epsilon \).
heaviside(x, [eps])
end_time = 1
PRINT t heaviside(t-0.5,0.25)
# exercise: what happens if the second argument is negative?
if
Performs a conditional testing of the first argument \( a \), and returns either the
second optional argument \( b \) if \( a \) is different from zero or the third optional argument \( c \)
if \( a \) evaluates to zero. The comparison of the condition \( a \) with zero is performed
within the precision given by the optional fourth argument \( \epsilon \).
If the second argument \( c \) is not given and \( a \) is not zero, the function returns one.
If the third argument \( c \) is not given and \( a \) is zero, the function returns zero.
The default precision is \( \epsilon = 10^{-16} \).
Even though if
is a logical operation, all the arguments and the returned value
are double-precision floating point numbers.
if(a, [b], [c], [eps])
integral_dt
Computes the time integral of the signal \( x \) using the trapezoidal rule
using the value of the signal in the previous time step and the current value.
At \( t = 0 \) the integral is initialized to zero.
Unlike the functional integral
, this function works with expressions and not
with functions. Therefore the argument \( x \) may be for example an expression
involving a variable that may be read from a shared-memory object, whose
time integral cannot be computed with integral
.
integral_dt(x)
end_time = 2*pi
dt = end_time/100
y = sin(t) + random_gauss(0,0.05)
PRINT t y integral_dt(y)
# exercise: compute also the instantaneous
# mean value of the signal y(t)
integral_euler_dt
Idem as integral_dt
but uses the backward Euler rule to update the
integral value.
This function is provided in case this particular way
of approximating time integrals is needed.
integral_euler_dt(x)
is_even
Returns one if the argument \( x \) rounded to the nearest integer is even.
y = is_even(x)
is_in_interval
Returns true if the argument \( x \) is in the interval \( [a,b) \), i.e. including \( a \) but excluding \( b \).
is_in_interval(x, a, b)
is_odd
Returns one if the argument \( x \) rounded to the nearest integer is odd.
y = is_odd(x)
j0
Computes the regular cylindrical Bessel function of zeroth order evaluated at the argument \( x \).
j0(x)
lag
Filters the first argument \( x(t) \) with a first-order lag of characteristic time \( \tau \), i.e. this function applies the transfer function $$ G(s) = \frac{1}{1 + s\tau} $$ to the time-dependent signal \( x(t) \), by assuming that it is constant during the time interval \( [t-\Delta t,t] \) and using the analytical solution of the differential equation for that case at \( t = \Delta t \) with the initial condition \( y(0) = y(t-\Delta t) \).
lag(x, tau)
lag_bilinear
Filters the first argument \( x(t) \) with a first-order lag of characteristic time \( \tau \), i.e. this function applies the transfer function $$ G(s) = \frac{1}{1 + s\tau} $$ to the time-dependent signal \( x(t) \) by using the bilinear transformation formula.
lag_bilinear(x, tau)
lag_euler
Filters the first argument \( x(t) \) with a first-order lag of characteristic time \( \tau \), i.e. this function applies the transfer function $$ G(s) = \frac{1}{1 + s\tau} $$ to the time-dependent signal \( x(t) \) by using the Euler forward rule.
lag_euler(x, tau)
last
Returns the value the signal \( x \) had in the previous time step.
This function is equivalent to the \( Z \)-transform operator "delay" denoted by \( z^{-1}\left[x\right] \).
For \( t=0 \) the function returns the actual value of \( x \).
The optional flag \( p \) should be set to one if the reference to last
is done in an assignment over a variable that already appears insi
expression \( x \). See example number 2.
last(x,[p])
end_time = 1
PRINT t last(t) last(last(1-t))
# exercise: plot the two signals
end_time = 1
y = y + 1
z = last(z,1) + 1
PRINT t %g y z
# exercise: compute z = last(z)+1 and see what happens
limit
Limits the first argument \( x \) to the interval \( [a,b] \). The second argument \( a \) should be less than the third argument \( b \).
limit(x, a, b)
limit_dt
Limits the value of the first argument \( x(t) \) so to that its time derivative is bounded to the interval \( [a,b] \). The second argument \( a \) should be less than the third argument \( b \).
limit_dt(x, a, b)
log
Computes the natural logarithm of the argument \( x \). If \( x \) is zero or negative, a NaN error is issued.
log(x)
end_time = 1
dt = 1e-2
x = d_dt(log(1+t))
y = 1/(1+t)
PRINT t x y y-x
# exercise: why does this example gives a bigger error than
# the exp.was example?
mark_max
Returns the integer index \( i \) of the maximum of the arguments \( x_i \) provided. Currently only maximum of ten arguments can be provided.
mark_max(x1, x2, [...], [x10])
mark_min
Returns the integer index \( i \) of the minimum of the arguments \( x_i \) provided. Currently only maximum of ten arguments can be provided.
mark_max(x1, x2, [...], [x10])
max
Returns the maximum of the arguments \( x_i \) provided. Currently only maximum of ten arguments can be provided.
max(x1, x2, [...], [x10])
min
Returns the minimum of the arguments \( x_i \) provided. Currently only maximum of ten arguments can be provided.
min(x1, x2, [...], [x10])
mod
Returns the remainder of the division between the first argument \( a \) and the second \( b \). Both arguments may be non-integral.
mod(a, b)
not
Returns one if the first argument \( x \) is zero and zero otherwise. The second optional argument \( \epsilon \) gives the precision of the "zero" evaluation. If not given, default is \( \epsilon = 10^{-16} \).
not(x, [eps])
random
Returns a random real number uniformly distributed between the first real argument \( x_1 \) and the second one \( x_2 \). If the third integer argument \( s \) is given, it is used as the seed and thus repetitive sequences can be obtained. If no seed is provided, the current time (in seconds) plus the internal address of the expression is used. Therefore, two successive calls to the function without seed (hopefully) do not give the same result. This function uses a second-order multiple recursive generator described by Knuth in Seminumerical Algorithms, 3rd Ed., Section 3.6.
random(x1, x2, [s])
random_gauss
Returns a random real number with a Gaussian distribution with a mean equal to the first argument \( x_1 \) and a standard deviation equatl to the second one \( x_2 \). If the third integer argument \( s \) is given, it is used as the seed and thus repetitive sequences can be obtained. If no seed is provided, the current time (in seconds) plus the internal address of the expression is used. Therefore, two successive calls to the function without seed (hopefully) do not give the same result. This function uses a second-order multiple recursive generator described by Knuth in Seminumerical Algorithms, 3rd Ed., Section 3.6.
random_gauss(x1, x2, [s])
round
Rounds the argument \( x \) to the nearest integer. Halfway cases are rounded away from zero.
round(x)
sawtooth_wave
Computes a sawtooth wave betwen zero and one with a period equal to one. As with the sine wave, a sawtooh wave can be generated by passing as the argument \( x \) a linear function of time such as \( \omega t+\phi \), where \( \omega \) controls the frequency of the wave and \( \phi \) controls its phase.
sawtooth_wave(x)
end_time = 10
dt = 1e-2
r = 2*sawtooth_wave(0.2*t + 0.5) - 1
y = lag(r, 0.5)
PRINT t r y
sgn
Returns minus one, zero or plus one depending on the sign of the first argument \( x \). The second optional argument \( \epsilon \) gives the precision of the "zero" evaluation. If not given, default is \( \epsilon = 10^{-16} \).
sgn(x, [eps])
sin
Computes the sine of the argument \( x \), where \( x \) is in radians. A sine wave can be generated by passing as the argument \( x \) a linear function of time such as \( \omega t+\phi \), where \( \omega \) controls the frequency of the wave and \( \phi \) controls its phase.
sin(x)
sinh
Computes the hyperbolic sine of the argument \( x \), where \( x \) is in radians.
sinh(x)
sqrt
Computes the positive square root of the argument \( x \). If \( x \) is negative, a NaN error is issued.
sqrt(x)
square_wave
Computes a square function betwen zero and one with a period equal to one. The output is one for \( 0 < x < 1/2 \) and goes to zero for \( 1/2 < x < 1 \). As with the sine wave, a square wave can be generated by passing as the argument \( x \) a linear function of time such as \( \omega t+\phi \), where \( \omega \) controls the frequency of the wave and \( \phi \) controls its phase.
square_wave(x)
end_time = 10
dt = 1e-2
r = 2*square_wave(0.2*t - 0.1) - 1
y = lag(r, 0.5)
PRINT t r y
tan
Computes the tangent of the argument \( x \), where \( x \) is in radians.
tan(x)
tanh
Computes the hyperbolic tangent of the argument \( x \), where \( x \) is in radians.
tanh(x)
threshold_max
Returns one if the first argument \( x \) is greater than the threshold given by the second argument \( a \), and \textit{exactly} zero otherwise. If the optional third argument \( b \) is provided, an hysteresis of width \( b \) is needed in order to reset the function value. Default is no hysteresis, i.e. \( b=0 \).
threshold_max(x, a, [b])
threshold_min
Returns one if the first argument \( x \) is less than the threshold given by the second argument \( a \), and \textit{exactly} zero otherwise. If the optional third argument \( b \) is provided, an hysteresis of width \( b \) is needed in order to reset the function value. Default is no hysteresis, i.e. \( b=0 \).
threshold_min(x, a, [b])
triangular_wave
Computes a triangular wave betwen zero and one with a period equal to one. As with the sine wave, a triangular wave can be generated by passing as the argument \( x \) a linear function of time such as \( \omega t+\phi \), where \( \omega \) controls the frequency of the wave and \( \phi \) controls its phase.
triangular_wave(x)
derivative
Computes the derivative of the expression \( f(x) \)
given in the first argument with respect to the variable \( x \)
given in the second argument at the point \( x=a \) given in
the third argument using an adaptive scheme.
The fourth optional argument \( h \) is the initial width
of the range the adaptive derivation method starts with.
The fifth optional argument \( p \) is a flag that indicates
whether a backward (\( p < 0 \)), centered (\( p = 0 \)) or forward (\( p > 0 \))
stencil is to be used.
This functional calls the GSL functions
gsl_deriv_central
or gsl_deriv_forward
according to the indicated flag \( p \).
Defaults are \( h = (1/2)^{-10} \approx 9.8 \times 10^{-4} \) and \( p = 0 \).
derivative(f(x), x, a, [h], [p])
VAR x
numeric = derivative(log(x^2),x,3)
exact(x) := 2/x
PRINT numeric exact(3) numeric-exact(3)
# excercise: write a functions to compute the numerical
# derivative of log(x^2) and compare it to the exact one
# for a certain range of x
func_min
Finds the value of the variable \( x \) given in the second argument
which makes the expression \( f(x) \) given in the first argument to
take local a minimum in the in the range \( [a,b] \) given by
the third and fourth arguments. If there are many local minima,
the one that is closest to \( (a+b)/2 \) is returned.
The optional fifth argument \( \epsilon \) gives a relative tolerance
for testing convergence, corresponding to GSL epsrel
(note that
epsabs
is set also to \( \epsilon) \).
The sixth optional argument is an integer which indicates the
algorithm to use:
0 (default) is quad_golden
,
1 is brent
and
2 is goldensection
.
See the GSL documentation for further information on the algorithms.
The seventh optional argument \( p \) is a flag that indicates how to proceed
if there is no local minimum in the range \( [a,b] \).
If \( p = 0 \) (default), \( a \) is returned if \( f(a) < f(b) \) and \( b \) otherwise.
If \( p = 1 \) then the local minimum algorimth is tried nevertheless.
Default is \( \epsilon = (1/2)^{-20} \approx 9.6\times 10^{-7} \).
y = func_min(f(x), x, a, b, [eps], [alg], [p])
FUNCTION f(x) INTERPOLATION spline DATA {
0 1
0.1 0.5
0.3 0.4
0.5 0.5
0.7 0.8
1 1
}
PRINT func_min(f(x),x,f_a,f_b)
# exercise: plot the interpolated f(x) in the range [0:1]
# and check that func_min returned the correct value
gauss_kronrod
Computes the integral of the expression \( f(x) \)
given in the first argument with respect to variable \( x \)
given in the second argument over the interval \( [a,b] \) given
in the third and fourth arguments respectively using a
non-adaptive procedure which uses fixed Gauss-Kronrod-Patterson
abscissae to sample the integrand at a maximum of 87 points.
It is provided for fast integration of smooth functions.
The algorithm applies the Gauss-Kronrod 10-point, 21-point,
43-point and 87-point integration rules in succession until an
estimate of the integral is achieved within the relative tolerance
given in the fifth optional argument \( \epsilon \)
It correspondes to GSL's epsrel
parameter (epsabs
is set to zero).
The rules are designed in such a way that each rule uses all
the results of its predecessors, in order to minimize the total
number of function evaluations.
Defaults are \( \epsilon = (1/2)^{-10} \approx 10^{-3} \).
See GSL reference for further information.
gauss_kronrod(f(x), x, a, b, [eps])
f(x) := exp(-x^2/2)
eps = 1e-3
a = sqrt(2*pi)
b = integral(f(x), x, -10, 10, eps)
c = gauss_kronrod(f(x), x, -10, 10, eps)
d = gauss_legendre(f(x), x, -10, 10, 24)
PRINT %.20f a %e a-a
PRINT %.20f b %e b-a
PRINT %.20f c %e c-a
PRINT %.20f d %e d-a
# exercise: study how the errors change with eps.
# Hint: define thre functions of eps
gauss_legendre
Computes the integral of the expression \( f(x) \)
given in the first argument with respect to variable \( x \)
given in the second argument over the interval \( [a,b] \) given
in the third and fourth arguments respectively using the
\( n \)-point Gauss-Legendre rule, where \( n \) is given in the
optional fourth argument.
It is provided for fast integration of smooth functions with
known polynomic order (it is exact for polynomials of order
\( 2n-1 \)).
This functional calls GSL function gsl_integration_glfixedp
.
Default is \( n = 12 \).
See GSL reference for further information.
gauss_legendre(f(x), x, a, b, [n])
f(x) := exp(-x^2/2)
eps = 1e-3
a = sqrt(2*pi)
b = integral(f(x), x, -10, 10, eps)
c = gauss_kronrod(f(x), x, -10, 10, eps)
d = gauss_legendre(f(x), x, -10, 10, 24)
PRINT %.20f a %e a-a
PRINT %.20f b %e b-a
PRINT %.20f c %e c-a
PRINT %.20f d %e d-a
# exercise: study how the errors change with eps.
# Hint: define thre functions of eps
integral
Computes the integral of the expression \( f(x) \)
given in the first argument with respect to variable \( x \)
given in the second argument over the interval \( [a,b] \) given
in the third and fourth arguments respectively using an adaptive
scheme, in which the domain is divided into a number of maximum number
of subintervals
and a fixed-point Gauss-Kronrod-Patterson scheme is applied to each
quadrature subinterval. Based on an estimation of the error commited,
one or more of these subintervals may be split to repeat
the numerical integration alogorithm with a refined division.
The fifth optional argument \( \epsilon \) is is a relative tolerance
used to check for convergence. It correspondes to GSL's epsrel
parameter (epsabs
is set to zero).
The sixth optional argument \( 1\leq k \le 6 \) is an integer key that
indicates the integration rule to apply in each interval.
It corresponds to GSL's parameter key
.
The seventh optional argument gives the maximum number of subdivisions,
which defaults to 1024.
If the integration interval \( [a,b] \) if finite, this functional calls
the GSL function gsl_integration_qag
. If \( a \) is less that minus the
internal variable infinite
, \( b \) is greater that infinite
or both
conditions hold, GSL functions gsl_integration_qagil
,
gsl_integration_qagiu
or gsl_integration_qagi
are called.
The condition of finiteness of a fixed range \( [a,b] \) can thus be
changed by modifying the internal variable infinite
.
Defaults are \( \epsilon = (1/2)^{-10} \approx 10^{-3} \) and \( k=3 \).
The maximum numbers of subintervals is limited to 1024.
Due to the adaptivity nature of the integration method, this function
gives good results with arbitrary integrands, even for
infinite and semi-infinite integration ranges. However, for certain
integrands, the adaptive algorithm may be too expensive or even fail
to converge. In these cases, non-adaptive quadrature functionals ought to
be used instead.
See GSL reference for further information.
integral(f(x), x, a, b, [eps], [k], [max_subdivisions])
VAR x
PRINT integral(x^2,x,0,1)
VAR x
intpi = 4 * integral(integral(1, y, 0, sqrt(1-x^2)), x, 0, 1)
PRINT intpi
f(x) := exp(-x^2/2)
eps = 1e-3
a = sqrt(2*pi)
b = integral(f(x), x, -10, 10, eps)
c = gauss_kronrod(f(x), x, -10, 10, eps)
d = gauss_legendre(f(x), x, -10, 10, 24)
PRINT %.20f a %e a-a
PRINT %.20f b %e b-a
PRINT %.20f c %e c-a
PRINT %.20f d %e d-a
# exercise: study how the errors change with eps.
# Hint: define thre functions of eps
prod
Computes product of the \( N=b-a \) expressions \( f(i) \) given in the first argument by varying the variable \( i \) given in the second argument between \( a \) given in the third argument and \( b \) given in the fourth argument,~\( i = a, a+1, \dots ,b-1,b \).
prod(f(i), i, a, b)
root
Computes the value of the variable \( x \) given in the second argument
which makes the expression \( f(x) \) given in the first argument to
be equal to zero by using a root bracketing algorithm.
The root should be in the range \( [a,b] \) given by the third and fourth arguments.
The optional fifth argument \( \epsilon \) gives a relative tolerance
for testing convergence, corresponding to GSL epsrel
(note that
epsabs
is set also to \( \epsilon) \).
The sixth optional argument is an integer which indicates the
algorithm to use:
0 (default) is brent
,
1 is falsepos
and
2 is bisection
.
See the GSL documentation for further information on the algorithms.
The seventh optional argument \( p \) is a flag that indicates how to proceed
if the sign of \( f(a) \) is equal to the sign of \( f(b) \).
If \( p=0 \) (default) an error is raised, otherwise it is not.
If more than one root is contained in the specified range, the first
one to be found is returned. The initial guess is \( x_0 = (a+b)/2 \).
If no roots are contained in the range and
\( p \neq 0 \), the returned value can be any value.
Default is \( \epsilon = (1/2)^{-10} \approx 10^{3} \).
root(f(x), x, a, b, [eps], [alg], [p])
VAR x
PRINT "nu0 / j0(nu0) = 0 is equal to " %.6f root(j0(x),x,2,3) NOSEP
a = 2
PRINT "cos(a*x) = x with a = " %g a " holds for x = " %.6f root(cos(a*x)-x,x,0,2*pi) NOSEP
# exercise: try to find the roots of x^2 + x + 1 and explain what happens
VAR x'
cdf(x) := 2/sqrt(2*pi) * integral(exp(-x'^2/2), x', 0, x)
sigma(x) := root(cdf(x')-x, x', 0, 5)
PRINT "within one standard deviation one has " %.2f 100*cdf(1) " percent of the samples" NOSEP
PRINT "within two standard deviations one has " %.2f 100*cdf(2) " percent of the samples" NOSEP
PRINT "to take into account 99% of cases for one needs " %.1f sigma(0.99) " standard deviations" NOSEP
# exercise: plot both cdf(x) and sigma(x) in the same figure
f(x) := sin(x)-1/2
PRINT pi/6-root(f(x),x,0,1,1e-2,2)
PRINT pi/6-root(f(x),x,0,1,1e-4,2)
PRINT pi/6-root(f(x),x,0,1,1e-6,2)
PRINT
PRINT pi/6-root(f(x),x,0,1,1e-2,1)
PRINT pi/6-root(f(x),x,0,1,1e-4,1)
PRINT pi/6-root(f(x),x,0,1,1e-6,1)
PRINT
PRINT pi/6-root(f(x),x,0,1,1e-2,0)
PRINT pi/6-root(f(x),x,0,1,1e-4,0)
PRINT pi/6-root(f(x),x,0,1,1e-6,0)
# exercice: try other combinations of tolerances and say something
# about the number of steps needed by each method to converge
FUNCTION f(x) DATA {
0 1
0.3 -1
1 1
}
PRINT root(f(x),x,0,1,,,1)
# exercise: see what happens if one sets p=1. How can one find
# the other root of f(x) located at x=0.65?
sum
Computes sum of the \( N=b-a \) expressions \( f_i \) given in the first argument by varying the variable \( i \) given in the second argument between \( a \) given in the third argument and \( b \) given in the fourth argument, \( i=a,a+1,\dots,b-1,b \).
sum(f_i, i, a, b)
f(n) := sum(i, i, 1, n)
PRINT TEXT "n" TEXT "sum" TEXT "formula"
PRINT_FUNCTION f (n*(n+1))/2 MIN 1 MAX 10 STEP 1 FORMAT %g
# exercise: do the same with the sum of the squares of
# the first n natural numbers
n = 1e5
pisum = 4*sum((-1)^i * 1/(2*i+1), i, 0, n)
PRINT "exact = " %.10f pi NOSEP
PRINT "sum = " %.10f pisum " (" %g n " terms)" NOSEP
PRINT "diff = " pi-pisum NOSEP
# exercise: investigate the rate of convergence of pisum with n.
NUMBER N 3
MATRIX A ROWS N COLS N
VECTOR b SIZE N
A(i,j) = i + 0.1*j
tr = sum(A(i,i), i, 1, N)
b(i) = sum(A(i,j), j, 1, N)
PRINT a
PRINT
PRINT tr
PRINT
PRINT_VECTOR b
# exercise: compute the matrix-product Ab
vecdot
Computes the dot product between vectors \( \vec{a} \) and \( \vec{b} \), which should have the same size.
vecdot(a,b)
NUMBER N 3
VECTOR a SIZE N DATA 0.1234 0.98765 0.5555
VECTOR b SIZE N
b(i) = 1-0.2*i
PRINT vecdot(a,b)
vecmax
Returns the biggest element of vector \( \vec{b} \), taking into account its sign (i.e. \( 1 > -2 \)).
vecmax(b)
VECTOR x SIZE 5
x(i) = (i-1.2345)^2 - i - 5.4321
PRINT %g x
PRINT "maximum is " vecmax(x)
vecmaxindex
Returns the index of the biggest element of vector \( \vec{b} \), taking into account its sign (i.e. \( 2 > -1 \)).
vecmaxindex(b)
VECTOR x SIZE 5
x(i) = (i-1.2345)^2 - i - 5.4321
PRINT %g x
PRINT "minimum is element number" %g vecminindex(x)
vecmin
Returns the smallest element of vector \( \vec{b} \), taking into account its sign (i.e. \( -2 < 1 \)).
vecmin(b)
VECTOR x SIZE 5
x(i) = (i-1.2345)^2 - i - 5.4321
PRINT %g x
PRINT "minimum is " vecmin(x)
vecminindex
Returns the index of the smallest element of vector \( \vec{b} \), taking into account its sign (i.e. \( -2 < 1 \)).
vecminindex(b)
VECTOR x SIZE 5
x(i) = (i-1.2345)^2 - i - 5.4321
PRINT %g x
PRINT "minimum is element number" %g vecminindex(x)
vecnorm
Computes euclidean norm of vector \( \vec{b} \). Other norms can be computed explicitly
using the sum
functional, as illustrated in the example.
vecnorm(b)
VECTOR x SIZE 10
x(i) = 1/(i+1)
PRINT %g x
PRINT "euclidean norm with vecnorm =" vecnorm(x)
PRINT "euclidean norm with sum =" sqrt(sum(x(i)^2,i,1,vecsize(x)))
PRINT "absolute value norm with sum = " sum(abs(x(i)),i,1,vecsize(x))
vecsize
Returns the size of vector \( \vec{b} \).
vecsize(b)
NUMBER N 6
VECTOR x SIZE 1+2*N
PRINT %g vecsize(x)
vecsum
Computes the sum of all the components of vector \( \vec{b} \).
vecsum(b)
NUMBER N 100
VECTOR x SIZE 100
x(i) = 1/i
PRINT vecsum(x) vecsum(x)+1/(N+1)