#! /bin/sh
######################################
##### Model Transformation Tools #####
######################################
###############################################################
## Version control history
###############################################################
## $Id$
## $Log$
## Revision 1.89 2004/08/29 16:04:44 geraint
## Fixed ae for non-sorted code.
##
## Revision 1.88 2004/08/29 13:15:28 geraint
## Uses sys_sae instead of sys_ae if sorted equations are being used.
##
## Revision 1.87 2004/08/29 01:46:56 geraint
## Added rules to create ode2odes for sorted system: sesx and sesy.
##
## Revision 1.86 2004/08/29 00:19:49 geraint
## Defaults to noAlgebraicSolver.
##
## Revision 1.85 2003/06/25 12:46:06 gawthrop
## Input only changed one per print interval
## No effect if stepfactor=1
## Fixes bug when _input.m is compiled using -stdin option
## and stepfactor>1
##
## Revision 1.84 2003/04/17 20:57:29 geraint
## Added -sort option to allow direct generation of ode2odes.m using sese.m
## instead of ode/csex.
##
## "mtt -sort rc odeso view" works without Reduce installed!!!
##
## Revision 1.83 2002/08/07 14:27:14 geraint
## Changes to make "-i dassl" work again.
##
## Revision 1.82 2002/07/24 14:00:12 geraint
## Corrected arguments passed to mtt_write when dumping data (sigint).
##
## Revision 1.81 2002/07/11 13:00:23 geraint
## Declared more function arguments to be "const" - improves compiler optimisation.
##
## Revision 1.80 2002/05/22 09:35:49 geraint
## Added insertor variable to stop sh-mode font-lock from getting hopelessly confused by embedded C++.
##
## Revision 1.79 2002/05/20 13:42:31 gawthrop
## Uses simpar.first for first printed output
##
## Revision 1.78 2002/05/11 01:14:17 geraint
## Fix for [ 553218 ] simpar.oct and simpar.m different.
## Translation added between ColumnVector in base .cc and Octave_map in .oct.
##
## Revision 1.77 2002/05/08 16:03:32 geraint
## Added mex support for ode2odes: mtt sys ode2odes mexglx.
## This mex stuff seems to require octave2.1-headers.
##
## Revision 1.76 2002/05/08 14:14:55 geraint
## Tidied up ode2odes code - reduced interweaving of STANDALONE/OCTAVEDLD sections
##
## Revision 1.75 2002/05/07 13:48:42 geraint
## Improved clarity of code generated for -cc and -oct (except ode2odes).
## Octave DEFUN_DLDs now call (rather than replace) their .cc equivalents.
##
## Revision 1.74 2002/05/01 17:30:56 geraint
## Improved pre-processor directives to better accommodate future alternatives (matlab)
## if necessary.
##
## Revision 1.73 2002/05/01 12:24:41 geraint
## Removed unnecessary inclusion of load-save.h.
##
## Revision 1.72 2002/05/01 12:21:29 geraint
## No longer uses save_ascii_data_for_plotting function to write data
## - eliminates dependence on liboctinterp (and libncurses) for .cc.
##
## Revision 1.71 2002/04/30 23:27:00 geraint
## Replaced octave_map with columnvector in simpar.cc. Not quite as descriptive but
## standardises the interfaces somewhat and reduces the dependency on liboctinterp
## (and thus libreadline, libkpathsea, libncurses, etc).
##
## Revision 1.70 2002/04/28 18:41:27 geraint
## Fixed [ 549658 ] awk should be gawk.
## Replaced calls to awk with call to gawk.
##
## Revision 1.69 2002/04/17 13:46:58 geraint
## #include <fstream> for -oct as well as -cc.
##
## Revision 1.68 2002/04/15 10:54:31 geraint
## Statically declare outputs and initialise to zero.
## This is necessary to prevent spurious values from being output when no assignments are made (i.e. when "y(i) := 0 for all u" (Reduce:see NERO)).
##
## Revision 1.67 2002/04/09 12:04:21 geraint
## Replaced ios:: with std::ios:: for g++-3.0 compatability.
##
## Revision 1.66 2002/03/26 11:58:58 geraint
## Added cputime monitoring.
##
## Revision 1.65 2001/11/15 06:24:11 geraint
## Updated (-i dassl) residual function to use new DAEFunc (octave-2.1.35).
## YZ residual dependency on Ui still requires some work.
##
## Revision 1.64 2001/08/08 02:15:00 geraint
## Rationalisation of solver code, beginning with algebraic solvers.
##
## Revision 1.63 2001/08/07 04:39:24 geraint
## Consolidated dassl and residual functions.
##
## Revision 1.62 2001/08/01 22:14:32 geraint
## Bug fix for dassl.
##
## Revision 1.61 2001/08/01 04:06:07 geraint
## Added -i dassl for -cc and -oct.
##
## Revision 1.60 2001/07/16 22:23:00 geraint
## Fixed misleading variable name in .cc rep.
##
## Revision 1.59 2001/07/13 04:54:04 geraint
## Branch merge: numerical-algebraic-solution back to main.
##
## Revision 1.58 2001/07/13 00:51:39 geraint
## Fixed generation of odes.sg from .m and .oct simulations.
## .cc, .m and .oct simulations now all write mtt_data (lower case).
##
## Revision 1.57.2.5 2001/07/13 04:02:31 geraint
## Implemented numerical algebraic solution for _ode2odes.oct.
##
## Revision 1.57.2.4 2001/07/02 00:34:56 geraint
## gcc-3.0 compatibility.
##
## Revision 1.57.2.3 2001/06/25 23:28:29 geraint
## Generic mtt_rate and mtt_output - allows method independent calls.
##
## Revision 1.57.2.2 2001/06/05 03:20:40 geraint
## added -ae option to select algebraic equation solution method.
##
## Revision 1.57.2.1 2001/05/04 04:07:24 geraint
## Numerical solution of algebraic equations.
## sys_ae.cc written for unsolved inputs.
## Solution of equations using hybrd from MINPACK (as used by Octave fsolve).
##
## Revision 1.57 2001/04/01 03:38:54 geraint
## Reset row to zero after write to file, ready for subsequent runs.
## Eliminates SIGSEGV in Octave when _ode2odes called multiple times.
##
## Revision 1.56 2001/03/30 15:13:58 gawthrop
## Rationalised simulation modes to each return mtt_data
##
## Revision 1.55 2001/03/27 13:21:59 geraint
## Octave version compatibility for save_ascii_data(_for_plotting).
##
## Revision 1.54 2001/03/27 01:14:27 geraint
## Improved determination of Octave version.
##
## Revision 1.53 2001/03/21 03:24:59 geraint
## Calculate inputs before outputs (.cc).
##
## Revision 1.52 2001/03/19 02:28:52 geraint
## Branch merge: merging-ode2odes-exe back to MAIN.
##
## Revision 1.51.2.7 2001/03/17 09:51:07 geraint
## Implemented Runge-Kutta IV fixed-step method (-i rk4).
##
## Revision 1.51.2.6 2001/03/16 03:56:13 geraint
## Removed psignal/siginfo.h - problematic and unnecessary.
##
## Revision 1.51.2.5 2001/03/12 23:16:37 geraint
## Minor improvements to signal handling (.exe).
##
## Revision 1.51.2.4 2001/03/12 03:59:30 geraint
## SIGINT (C-c C-c) now causes simulation data to be dumped to MTT.core.
## SIGQUIT (C-c C-\) as for SIGINT, then raises default SIGQUIT.
## SIGFPE as for SIGINT, then raises default SIGABRT.
##
## Revision 1.51.2.3 2001/03/07 04:06:55 geraint
## Irix: catch SIGFPE and write data before aborting (.exe).
## GNU/Linux: nada.
##
## Revision 1.51.2.2 2001/03/02 00:45:21 geraint
## Separated Euler and Implicit methods in .cc code and dependencies.
##
## Revision 1.51.2.1 2001/03/01 05:05:53 geraint
## Minor revisions.
##
## Revision 1.51 2001/02/19 06:33:19 geraint
## Removed operation form loop.
##
## Revision 1.50 2001/02/18 09:18:49 geraint
## Removed temporary Matrices from mtt_implicit.cc
##
## Revision 1.49 2001/02/14 06:06:34 geraint
## Removed octave_value_list wrappers from standalone.exe - speed improvements
##
## Revision 1.48 2001/02/11 07:08:59 geraint
## Static declarations of octave_value_lists: small .exe speed improvement
##
## Revision 1.47 2001/02/11 05:25:52 geraint
## Reduced number of matrix operations during .oct simulation data write
##
## Revision 1.46 2001/02/05 08:32:31 geraint
## typo
##
## Revision 1.45 2001/02/05 04:32:35 geraint
## Octave version 2.1.x compatability and #ifdef statements for standalone rep
##
## Revision 1.46 2001/01/08 06:21:59 geraint
## #ifdef STANDALONE stuff
##
## Revision 1.45 2001/01/07 01:25:49 geraint
## Compatibility with Octave 2.1.33
##
## Revision 1.44 2000/12/05 12:11:45 peterg
## Changed function name to name()
##
## Revision 1.43 2000/12/04 10:59:40 peterg
## *** empty log message ***
##
## Revision 1.42 2000/11/10 14:19:50 peterg
## Corrected the csex and cseo functions
##
## Revision 1.41 2000/11/09 17:06:39 peterg
## Now does euler for cc
##
## Revision 1.40 2000/10/17 09:55:00 peterg
## Replaced switchopen by logic
##
## Revision 1.39 2000/10/14 08:04:40 peterg
## Changed arguments to _inout for consistency
##
## Revision 1.38 2000/10/11 09:08:08 peterg
## cse --> csex
##
## Revision 1.37 2000/08/01 12:25:06 peterg
## Now includes euler
##
## Revision 1.36 2000/05/19 17:48:16 peterg
## Argument to state
##
## Revision 1.35 2000/05/18 18:59:40 peterg
## Removed the First time stuff
##
## Revision 1.34 2000/05/16 18:56:14 peterg
## *** empty log message ***
##
## Revision 1.33 2000/05/11 19:33:18 peterg
## Uniform version for _sim.m
##
## Revision 1.32 2000/05/11 08:30:00 peterg
##
## Revision 1.31 2000/05/10 18:33:25 peterg
## Use smxa and smxax in place of smx
##
## Revision 1.30 2000/04/18 11:24:19 peterg
## Removed _numpar.
##
## Revision 1.29 2000/04/07 19:10:57 peterg
## *** empty log message ***
##
## Revision 1.28 1999/12/08 05:56:52 peterg
## Reordered the writing of the input and output.
## Note that last value now discarded.
##
## Revision 1.27 1999/11/15 22:47:53 peterg
## Generates method-specific code.
##
## Revision 1.26 1999/10/20 01:31:43 peterg
## *** empty log message ***
##
## Revision 1.25 1999/08/29 06:55:26 peterg
## Removed [MTTu] = zero_input($Nu); # Zero the input
## to avoide the p2c bug ????
##
## Revision 1.24 1999/08/27 06:02:16 peterg
## removed zero_input to avoid p2c bug
##
## Revision 1.23 1999/08/02 13:39:19 peterg
## Replaced zero_vector by zero_input
##
## Revision 1.22 1999/04/20 06:16:07 peterg
## Removed initialisation of AA and AAx
## Remove _switch calls -- uses _switchopen exclusively
##
## Revision 1.21 1999/04/02 06:29:25 peterg
## New implicit method - solves numerical prob with ISW
##
## Revision 1.20 1999/04/02 02:13:58 peterg
## Back to RCS
##
## Revision 1.19 1999/03/30 21:39:25 peterg
## In implicit approach, set derivatives to zero (when switch is off)
## before update. This seems to stop numerical leakage though non-return
## switches.
##
## Revision 1.18 1999/03/15 01:17:07 peterg
## Removed some spurious debugging code
##
## Revision 1.17 1999/03/15 01:09:15 peterg
## Fixed bugs when Nx=0 (no state)
##
## Revision 1.16 1999/03/06 02:28:38 peterg
## Rearranged evaluation to: state - input - output - write
##
## Revision 1.15 1999/03/06 02:19:43 peterg
## Changed args to _input
##
## Revision 1.14 1998/10/01 16:02:01 peterg
## Integration with switches handled separately fro Euler and Implicit.
##
## Revision 1.13 1998/09/30 17:41:24 peterg
## Implicit method now allows for switches via _switchA
##
## Revision 1.12 1998/08/27 08:55:18 peterg
## Mods to integration methods
##
## Revision 1.11 1998/08/25 12:28:31 peterg
## Move initila switch to after initial input
##
## Revision 1.10 1998/08/25 12:22:45 peterg
## Put _switch after update and also at initilisation
##
## Revision 1.9 1998/08/15 13:46:59 peterg
## New versions of integration routines
##
## Revision 1.8 1998/08/11 13:28:03 peterg
## Lowercase mttLAST etc
##
## Revision 1.7 1998/07/30 11:29:54 peterg
## Added implicit integration stuff
##
## Revision 1.6 1998/07/30 10:44:37 peterg
## INcluded othe integration methods.
##
## Revision 1.5 1998/07/26 11:02:20 peterg
## Put mtt or MTT in front of variable names to avoid clashes with
## globals
##
## Revision 1.4 1998/07/25 20:14:00 peterg
## update code added for flexibility and octave efficiency
##
###############################################################
# Bourne shell script: make_ode2odes
# Copyright (c) P.J.Gawthrop July 1998.
# Tell user
sys=$1
lang=$2
filename=${sys}_ode2odes.${lang}
if [ -n "$3" ]; then
method=$3
else
method=implicit
fi
if [ -n "$4" ]; then
algebraic_solver=$4
else
algebraic_solver="noAlgebraicSolver"
fi
if [ -n "$5" ]; then
sorted_equations=$5
else
sorted_equations="no"
fi
insertor=\<\< # help emacs sh-mode handle C++ lines
echo Creating $filename with $method integration method
# Find system constants
Nx=`mtt_getsize $sys x` # States
Nu=`mtt_getsize $sys u` # Inputs
Ny=`mtt_getsize $sys y` # Outputs
case "$method" in
"implicit")
ae=ae
ode=csex
odeo=cseo
algorithm="mtt_implicit(x,dx,AA,AAx,ddt,$Nx,open_switches)"
;;
"dassl")
case "$sorted_equations" in
"make") # used by sese generated by make
ae=sae
ode=sesx
odeo=sesy
;;
"seqn") # shouldn't be here unless mtt has changed
ae=ae
ode=sese
odeo=sese
;;
"no" | *)
ae=ae
ode=ode
odeo=odeo
;;
esac
algorithm="mtt_dassl(x,u,t,par,dx,ddt,MTTNX,MTTNYZ,open_switches)"
;;
"sorted_euler") # used by sese generated from seqn
algorithm="mtt_euler(x,dx,ddt,$Nx,open_switches)"
;;
"euler" | "rk4" | *)
case "$sorted_equations" in
"make") # used by sese generated by make
ae=sae
ode=sesx
odeo=sesy
;;
"seqn") # shouldn't be here unless mtt has changed
ae=ae
ode=sese
odeo=sese
;;
"no" | *)
ae=ae
ode=ode
odeo=odeo
;;
esac
algorithm="mtt_euler(x,dx,ddt,$Nx,open_switches)"
;;
esac
make_m()
{
#lang_header $1 ode2odes m 'x,par,simpar' '[Y,X,t]' > $filename
mtt_header ${sys} ode2odes m > $filename
cat <<EOF >> $filename
global MTT_data
if nargin<3
simpar = ${sys}_simpar();
[simpar.dt] = mtt_simpar_update;
endif
if nargin<2
par = ${sys}_numpar();
[par] = mtt_numpar_update(par);
endif
if nargin<1
[x0] = ${sys}_state(par);
[x0] = mtt_state_update(x);
endif
## Initialise
t = 0.0;
ddt = simpar.dt/simpar.stepfactor;
ilast = round(simpar.last/ddt)+1; # Total number of steps
x = x0;
## Following removed due to p2c bug
## [u] = zero_input($Nu); # Zero the input
for MTTi=1:$Ny
y(MTTi) = 0;
endfor;
mttj = 0;
for it = 1:ilast #Integration loop
EOF
cat <<EOF >> $filename
if mttj==0
[u] = ${sys}_input(x,y,t,par); # Input
EOF
if [ "$method" = "sorted_euler" ]; then
cat <<EOF >> $filename
[dx,y] = ${sys}_sese(x,u,t,par); # Output
EOF
else
cat <<EOF >> $filename
[y] = ${sys}_$odeo(x,u,t,par); # Output
EOF
fi
cat <<EOF >> $filename
mtt_write(t,x,y,$Nx,$Ny,simpar.first); # Write it out
endif
EOF
if [ "$method" = "rk4" ]; then
cat << EOF >> $filename
[k1] = ddt * ${sys}_${ode}(x,u,t,par);
[k2] = ddt * ${sys}_${ode}(x+k1/2,u,t+ddt/2,par);
[k3] = ddt * ${sys}_${ode}(x+k2/2,u,t+ddt/2,par);
[k4] = ddt * ${sys}_${ode}(x+k3,u,t+ddt,par);
[dx] = [k1 + 2.0 * [k2 + k3] + k4] / (6.0 * ddt);
EOF
elif [ "$method" = "sorted_euler" ]; then
cat <<EOF >> $filename
[dx,y] = ${sys}_sese(x,u,t,par); # State derivative and Output
EOF
else
cat << EOF >> $filename
[dx] = ${sys}_$ode(x,u,t,par); # State derivative
EOF
fi
if [ "$method" = "implicit" ]; then
cat<< EOF >> $filename
[AA] = ${sys}_smxa(x,u,ddt,par); # (I-Adt) and (I-Adt)x
[AAx] = ${sys}_smxax(x,u,ddt,par); # (I-Adt) and (I-Adt)x
EOF
fi
cat <<EOF >> $filename
[open_switches] = ${sys}_logic(x,u,t,par); # Switch logic
[x] = $algorithm; # Integration update
[open_switches] = ${sys}_logic(x,u,t,par); # Switch logic
[x] = mtt_zeroswitches(x,$Nx,open_switches);
t = t + ddt; # Time update
mttj = mttj+1; # Increment counter
if mttj==simpar.stepfactor
mttj = 0; # Reset counter
endif
endfor; # Integration loop
## Create the output data
mtt_data = MTT_data;
endfunction
EOF
} # make_m
make_cc()
{
# get octave version
case `$MATRIX --version | gawk -F\. '{print $2}'` in
0) # stable
vector_value=vector_value
feval_header=toplev.h
;;
1) # development
vector_value=column_vector_value
feval_header=parse.h
;;
*)
vector_value=column_vector_value
feval_header=parse.h
;;
esac
cat <<EOF > $filename
// Code generation directives
#define STANDALONE 0
#define OCTAVEDLD 1
#define MATLABMEX 2
#if (! defined (CODEGENTARGET))
#define CODEGENTARGET STANDALONE
#endif // (! defined (CODEGENTARGET))
#include <octave/oct.h>
#include <octave/lo-mappers.h>
#include <octave/variables.h>
#if (CODEGENTARGET == OCTAVEDLD)
#include <octave/${feval_header}>
#endif // (CODEGENTARGET == OCTAVEDLD)
#include "${sys}_def.h"
#include "${sys}_sympar.h"
#include "mtt_${algebraic_solver}.hh"
#include <fstream>
#if ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
extern ColumnVector ${sys}_${ae} (
const ColumnVector &x,
const ColumnVector &u,
const double &t,
const ColumnVector &par);
extern ColumnVector ${sys}_input (
const ColumnVector &x,
const ColumnVector &y,
const double &t,
const ColumnVector &par);
extern ColumnVector ${sys}_logic (
const ColumnVector &x,
const ColumnVector &u,
const double &t,
const ColumnVector &par);
extern ColumnVector ${sys}_numpar (
void);
extern ColumnVector ${sys}_simpar (
void);
extern ColumnVector ${sys}_state (
const ColumnVector &par);
extern ColumnVector ${sys}_${ode} (
const ColumnVector &x,
const ColumnVector &u,
const double &t,
const ColumnVector &par);
extern ColumnVector ${sys}_${odeo} (
const ColumnVector &x,
const ColumnVector &u,
const double &t,
const ColumnVector &par);
EOF
case "$method" in
"implicit")
cat <<EOF >> $filename
extern ColumnVector Fmtt_implicit (
ColumnVector &x,
ColumnVector &dx,
Matrix &AA,
ColumnVector &AAx,
const double &ddt,
const int &nx,
const ColumnVector &open_switches);
extern Matrix ${sys}_smxa (
const ColumnVector &x,
const ColumnVector &u,
const double &t,
const ColumnVector &par);
extern ColumnVector ${sys}_smxax (
const ColumnVector &x,
const ColumnVector &u,
const double &t,
const ColumnVector &par);
EOF
;;
"dassl")
cat <<EOF >> $filename
extern ColumnVector Fmtt_dassl (
ColumnVector &x,
const ColumnVector &u,
const double &t,
const ColumnVector &par,
const ColumnVector &dx,
const double &ddt,
const int nx,
const int nyz,
const ColumnVector &open_switches);
EOF
;;
"euler" | "rk4" | *)
cat <<EOF >> $filename
extern ColumnVector Fmtt_euler (
ColumnVector &x,
const ColumnVector &dx,
const double &ddt,
const int &nx,
const ColumnVector &open_switches);
EOF
;;
esac
cat <<EOF >> $filename
#endif // ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
ColumnVector
mtt_ae (const ColumnVector &x,
const ColumnVector &u,
const double &t,
const ColumnVector &par)
{
#if ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
return ${sys}_${ae}(x,u,t,par);
#elif (CODEGENTARGET == OCTAVEDLD)
static octave_value_list args, f;
args (0) = octave_value (x);
args (1) = octave_value (u);
args (2) = octave_value (t);
args (3) = octave_value (par);
f = feval ("${sys}_${ae}", args, 1);
return f(0).${vector_value} ();
#endif // ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
}
inline ColumnVector
mtt_input (const ColumnVector &x,
const ColumnVector &y,
const double &t,
const ColumnVector &par)
{
static MTT::${algebraic_solver} ae(MTTNPAR,MTTNU,MTTNX,MTTNY,MTTNYZ);
static ColumnVector u (MTTNU);
#if ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
u = ${sys}_input (x, y, t, par);
#elif (CODEGENTARGET == OCTAVEDLD)
static octave_value_list args, f;
args (0) = octave_value (x);
args (1) = octave_value (y);
args (2) = octave_value (t);
args (3) = octave_value (par);
f = feval ("${sys}_input", args, 1);
u = f(0).${vector_value} ();
#endif // ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
if (MTTNYZ == 0)
{
return u;
}
else
{
return ae.solve(x,u,t,par);
}
}
inline ColumnVector
mtt_logic (const ColumnVector &x,
const ColumnVector &u,
const double &t,
const ColumnVector &par)
{
#if ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
return ${sys}_logic (x, u, t, par);
#elif (CODEGENTARGET == OCTAVEDLD)
static octave_value_list args, f;
args (0) = octave_value (x);
args (1) = octave_value (u);
args (2) = octave_value (t);
args (3) = octave_value (par);
f = feval ("${sys}_logic", args, 1);
return f(0).${vector_value} ();
#endif // ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
}
inline ColumnVector
mtt_numpar (void)
{
#if ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
return ${sys}_numpar ();
#elif (CODEGENTARGET == OCTAVEDLD)
static octave_value_list args, f;
f = feval ("${sys}_numpar", args, 1);
return f(0).${vector_value} ();
#endif // ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
}
inline ColumnVector
mtt_simpar (void)
{
#if ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
return ${sys}_simpar ();
#elif (CODEGENTARGET == OCTAVEDLD)
static octave_value_list args, f;
f = feval ("${sys}_simpar", args, 1);
return f(0).${vector_value} ();
#endif // ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
}
inline ColumnVector
mtt_state (const ColumnVector &par)
{
#if ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
return ${sys}_state (par);
#elif (CODEGENTARGET == OCTAVEDLD)
static octave_value_list args, f;
args (0) = octave_value (par);
f = feval ("${sys}_state", args, 1);
return f(0).${vector_value} ();
#endif // ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
}
inline ColumnVector
mtt_rate (const ColumnVector &x,
const ColumnVector &u,
const double &t,
const ColumnVector &par)
{
#if ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
return ${sys}_${ode} (x, u, t, par);
#elif (CODEGENTARGET == OCTAVEDLD)
static octave_value_list args, f;
args (0) = octave_value (x);
args (1) = octave_value (u);
args (2) = octave_value (t);
args (3) = octave_value (par);
f = feval ("${sys}_${ode}", args, 1);
return f(0).${vector_value} ();
#endif // ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
}
inline ColumnVector
mtt_output (const ColumnVector &x,
const ColumnVector &u,
const double &t,
const ColumnVector &par)
{
#if ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
return ${sys}_${odeo} (x, u, t, par);
#elif (CODEGENTARGET == OCTAVEDLD)
static octave_value_list args, f;
args (0) = octave_value (x);
args (1) = octave_value (u);
args (2) = octave_value (t);
args (3) = octave_value (par);
f = feval ("${sys}_${odeo}", args, 1);
return f(0).${vector_value} ();
#endif // ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
}
inline ColumnVector
mtt_zeroswitches (ColumnVector &x,
const int Nx,
const ColumnVector &openx)
{
for (register int i = 0; i < Nx; i++) {
if (0 != openx (i)) {
x(i) = 0.0;
}
}
return x;
}
EOF
case "$method" in
"implicit")
cat <<EOF >> $filename
inline ColumnVector
mtt_implicit (ColumnVector &x,
ColumnVector &dx,
Matrix &AA,
ColumnVector &AAx,
const double &ddt,
const int &nx,
const ColumnVector &open_switches)
{
#if ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
return Fmtt_implicit (x, dx, AA, AAx, ddt, nx, open_switches);
#elif (CODEGENTARGET == OCTAVEDLD)
static octave_value_list args, f;
args (0) = octave_value (x);
args (1) = octave_value (dx);
args (2) = octave_value (AA);
args (3) = octave_value (AAx);
args (4) = octave_value (ddt);
args (5) = octave_value ((double)nx);
args (6) = octave_value (open_switches);
f = feval ("mtt_implicit", args, 1);
return f(0).${vector_value} ();
#endif // ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
}
inline Matrix
mtt_smxa (const ColumnVector &x,
const ColumnVector &u,
const double &t,
const ColumnVector &par)
{
#if ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
return ${sys}_smxa (x, u, t, par);
#elif (CODEGENTARGET == OCTAVEDLD)
static octave_value_list args, f;
args (0) = octave_value (x);
args (1) = octave_value (u);
args (2) = octave_value (t);
args (3) = octave_value (par);
f = feval ("${sys}_smxa", args, 1);
return f(0).matrix_value ();
#endif // ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
}
inline ColumnVector
mtt_smxax (const ColumnVector &x,
const ColumnVector &u,
const double &t,
const ColumnVector &par)
{
#if ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
return ${sys}_smxax (x, u, t, par);
#elif (CODEGENTARGET == OCTAVEDLD)
static octave_value_list args, f;
args (0) = octave_value (x);
args (1) = octave_value (u);
args (2) = octave_value (t);
args (3) = octave_value (par);
f = feval ("${sys}_smxax", args, 1);
return f(0).${vector_value} ();
#endif // ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
}
EOF
;;
"dassl")
cat <<EOF >> $filename
inline ColumnVector
mtt_dassl (ColumnVector &x,
const ColumnVector &u,
const double &t,
const ColumnVector &par,
const ColumnVector &dx,
const double &ddt,
const int &nx,
const int &nyz,
const ColumnVector &open_switches)
{
#if ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
return Fmtt_dassl (x, u, t, par, dx, ddt, nx, nyz, open_switches);
#elif (CODEGENTARGET == OCTAVEDLD)
static octave_value_list args, f;
args (0) = octave_value (x);
args (1) = octave_value (u);
args (2) = octave_value (t);
args (3) = octave_value (par);
args (4) = octave_value (dx);
args (5) = octave_value (ddt);
args (6) = octave_value (static_cast<double> (nx));
args (7) = octave_value (static_cast<double> (nyz));
args (8) = octave_value (open_switches);
f = feval ("mtt_dassl", args, 1);
return f(0).${vector_value} ();
#endif // ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
}
#if ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
ColumnVector
Fmtt_residual (const ColumnVector &X,
const ColumnVector &DX,
double t,
int &ires)
{
#elif (CODEGENTARGET == OCTAVEDLD)
DEFUN_DLD (mtt_residual, args, , "mtt_residual")
{
static ColumnVector X (MTTNX+MTTNYZ);
static ColumnVector DX (MTTNX+MTTNYZ);
static double t;
static int ires;
X = args(0).${vector_value} ();
DX = args(1).${vector_value} ();
t = args(2).double_value ();
ires = static_cast<int>(args(3).double_value ());
#endif // ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
static ColumnVector residual (MTTNX+MTTNYZ);
static ColumnVector U (MTTNU+MTTNYZ);
static ColumnVector u (MTTNU);
static ColumnVector y (MTTNY,0.0);
static ColumnVector par (MTTNPAR);
static ColumnVector dx(MTTNX);
static ColumnVector yz(MTTNYZ);
static ColumnVector x (MTTNX);
static ColumnVector ui (MTTNYZ);
static octave_value_list new_args;
x = X.extract (0,MTTNX-1);
if (MTTNYZ > 0)
ui = X.extract (MTTNX,MTTNX+MTTNYZ-1);
#if ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
par = ${sys}_numpar();
u = ${sys}_input(x,y,t,par);
#elif (CODEGENTARGET == OCTAVEDLD)
par = feval ("${sys}_numpar", new_args, 1)(0).${vector_value} ();
new_args(0) = octave_value (x);
new_args(1) = octave_value (u);
new_args(2) = octave_value (t);
new_args(3) = octave_value (par);
u = feval ("${sys}_input", new_args, 1)(0).${vector_value} ();
#endif // ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
U.insert (u,0);
if (MTTNYZ > 0)
U.insert (ui,MTTNU);
#if ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
dx = ${sys}_${ode} (x,U,t,par);
yz = ${sys}_${ae} (x,U,t,par);
#elif (CODEGENTARGET == OCTAVEDLD)
new_args(1) = octave_value (U);
dx = feval ("${sys}_${ode}", new_args, 1)(0).${vector_value} ();
yz = feval ("${sys}_${ae}", new_args, 1)(0).${vector_value} ();
#endif // ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
for (register int i = 0; i < MTTNX; i++)
residual (i) = dx(i) - DX(i);
if (MTTNYZ > 0)
{
residual.insert (yz,MTTNX);
// XXX:
// DASSL needs residual to be dependent on Ui and Uidot
// mtt_dassl always sets the initial Ui to zero, so
// Ui - h*Uidot should equal zero BUT, we don't know h
static double t_old;
double step;
if (t != t_old)
{
step = t - t_old;
t = t_old;
}
else
step = t;
for (register int i = MTTNX; i < MTTNX+MTTNYZ; i++)
residual(i) += X(i) - DX(i)*step;
}
#if ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
return residual;
#elif (CODEGENTARGET == OCTAVEDLD)
return octave_value (residual);
#endif // ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
}
EOF
;;
"euler" | "rk4" | *)
cat <<EOF >> $filename
inline ColumnVector
mtt_euler (ColumnVector &x,
const ColumnVector &dx,
const double &ddt,
const int &nx,
const ColumnVector &open_switches)
{
#if ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
return Fmtt_euler (x, dx, ddt, nx, open_switches);
#elif (CODEGENTARGET == OCTAVEDLD)
static octave_value_list args, f;
args (0) = octave_value (x);
args (1) = octave_value (dx);
args (2) = octave_value (ddt);
args (3) = octave_value ((double)nx);
args (4) = octave_value (open_switches);
f = feval ("mtt_euler", args, 1);
return f(0).${vector_value} ();
#endif // ((CODEGENTARGET == STANDALONE) || (CODEGENTARGET == MATLABMEX))
}
EOF
;;
esac
cat <<EOF >> $filename
inline void
mtt_write (const double &t,
const ColumnVector &x,
const ColumnVector &y,
const double &first,
const int &nrows,
const bool dump_data = false,
std::ostream &file = std::cout)
{
static Matrix data;
static int row;
if (dump_data)
{
if (row > 0)
{
Matrix written_data = data.extract (0, 0, row-1, data.cols ()-1);
file $insertor "# name: mtt_dump" $insertor std::endl
$insertor "# type: matrix" $insertor std::endl
$insertor "# rows: " $insertor written_data.rows () $insertor std::endl
$insertor "# columns: " $insertor written_data.columns () $insertor std::endl
$insertor written_data;
file.flush ();
}
return;
}
const int nx = x.length (), ny = y.length ();
register int col = 0;
if (0 == row)
data = Matrix (nrows, 1+ny+1+nx, 0.0);
if (t >= first) {
data.elem (row, col) = t;
for (register int i = 0; i < ny; i++)
data.elem (row, ++col) = y.elem (i);
data.elem (row, ++col) = t;
for (register int i = 0; i < nx; i++)
data.elem (row, ++col) = x.elem (i);
row++;
};
static std::fstream fcputime ("MTT.cputime", std::ios::out | std::ios::trunc | std::ios::app);
static clock_t cputime0 = clock();
static clock_t cputime1 = cputime0;
clock_t cputime = clock();
fcputime $insertor t $insertor '\t'
$insertor static_cast <double> (cputime - cputime0) / CLOCKS_PER_SEC $insertor '\t'
$insertor static_cast <double> (cputime - cputime1) / CLOCKS_PER_SEC $insertor std::endl;
cputime1 = cputime;
if (nrows == row)
{
#if (CODEGENTARGET == STANDALONE)
file $insertor "# name: mtt_dump" $insertor std::endl
$insertor "# type: matrix" $insertor std::endl
$insertor "# rows: " $insertor data.rows () $insertor std::endl
$insertor "# columns: " $insertor data.columns () $insertor std::endl
$insertor data;
file.flush ();
#elif ((CODEGENTARGET == OCTAVEDLD) || (CODEGENTARGET == MATLABMEX))
set_global_value ("MTT_data", data);
#endif // (CODEGENTARGET == STANDALONE)
row = 0;
fcputime.close();
}
}
void
${sys}_ode2odes (const ColumnVector &state0,
const ColumnVector &par,
const ColumnVector &simpar)
{
static double first, dt, last, stepfactor;
first = simpar (0);
last = simpar (1);
dt = simpar (2);
stepfactor = simpar (3);
static ColumnVector dx (MTTNX, 0.0);
static ColumnVector x (MTTNX, 0.0);
static ColumnVector u (MTTNU, 0.0);
static ColumnVector y (MTTNY, 0.0);
static Matrix AA (MTTNX, MTTNX, 0.0);
static ColumnVector AAx (MTTNX, 0.0);
static ColumnVector open_switches (MTTNX, 0.0);
register double t = 0.0;
const double ddt = dt / stepfactor;
const int ilast = static_cast<int> (round ( last / ddt)) + 1;
const int nrows = static_cast<int> (round ((last - first) / dt)) + 1;
for (register int i = 0; i < MTTNY; i++)
{
y (i) = 0.0;
}
for (register int i = 0; i < MTTNX; i++)
{
x (i) = state0 (i);
}
for (register int j = 0, i = 1; i <= ilast; i++)
{
u = mtt_input (x, y, t, par);
y = mtt_output (x, u, t, par);
if (0 == j)
{
mtt_write (t, x, y, first, nrows);
}
EOF
case "$method" in
"rk4")
cat << EOF >> $filename
{
static ColumnVector
k1 (MTTNX,0.0),
k2 (MTTNX,0.0),
k3 (MTTNX,0.0),
k4 (MTTNX,0.0);
const double
t1 = t + ddt/2.0,
t2 = t + ddt;
ColumnVector
x1 (x),
x2 (x),
x3 (x);
k1 = ddt * mtt_rate (x , u, t , par); x1 += k1 * 0.5;
k2 = ddt * mtt_rate (x1, u, t1, par); x2 += k2 * 0.5;
k3 = ddt * mtt_rate (x2, u, t1, par); x3 += k3;
k4 = ddt * mtt_rate (x3, u, t2, par);
dx = (k1 + 2.0 * (k2 + k3) + k4) / (6.0 * ddt);
}
EOF
;;
"dassl")
;;
"implicit")
cat << EOF >> $filename
dx = mtt_rate (x, u, t, par);
AA = mtt_smxa (x, u, ddt, par);
AAx = mtt_smxax (x, u, ddt, par);
EOF
;;
"euler" | *)
cat << EOF >> $filename
dx = mtt_rate (x, u, t, par);
EOF
;;
esac
## Common stuff
cat <<EOF >> $filename
open_switches = mtt_logic (x, u, t, par);
x = $algorithm;
open_switches = mtt_logic (x, u, t, par);
x = mtt_zeroswitches (x, $Nx, open_switches);
t += ddt;
j++;
j = (j == static_cast<int> (stepfactor)) ? 0 : j;
}
}
#if (CODEGENTARGET == STANDALONE)
#include <csignal>
void set_signal_handlers (void);
void dump_data (std::ostream &file)
{
ColumnVector null (0);
mtt_write (0.0, null, null, 0, 0, true, file);
}
void handle_signal (int signum)
{
// handle some signals to ensure data is written.
std::cerr $insertor "# Writing data to MTT.core (signal " $insertor signum $insertor ")" $insertor std::endl;
std::ofstream corefile ("MTT.core");
dump_data (corefile);
switch (signum)
{
case SIGFPE:
// Intel chips do not raise SIGFPE for DIVZERO :-(
// raise (SIGABRT);
break;
case SIGINT:
break;
case SIGQUIT:
signal (SIGQUIT, SIG_DFL);
raise (SIGQUIT);
break;
default:
std::cerr $insertor "# Warning: make_ode2odes needs updating!" $insertor std::endl;
signal (signum, SIG_DFL);
raise (signum);
break;
}
corefile.close ();
set_signal_handlers ();
}
void set_signal_handlers (void)
{
signal (SIGFPE, handle_signal);
signal (SIGINT, handle_signal);
signal (SIGQUIT, handle_signal);
}
int
main (void)
{
set_signal_handlers ();
static ColumnVector simpar (8), numpar (MTTNPAR), state0 (MTTNX);
simpar = mtt_simpar ();
numpar = mtt_numpar ();
state0 = mtt_state (numpar);
${sys}_ode2odes (state0, numpar, simpar);
return 0;
}
#elif (CODEGENTARGET == OCTAVEDLD)
#include <mtt_simpar.hh>
DEFUN_DLD (${sys}_ode2odes, args, ,
"Octave ode2odes representation of system with $method integration method\nUsage: mtt_data = ${sys}_ode2odes (state0, numpar, simpar)\n")
{
static octave_value_list retval;
static ColumnVector state0 (MTTNX);
static ColumnVector numpar (MTTNPAR);
static ColumnVector simpar (8);
int nargin = args.length ();
switch (nargin)
{
case 3:
simpar = mtt_simpar (args(2).map_value ());
numpar = args(1).${vector_value} ();
state0 = args(0).${vector_value} ();
break;
case 2:
simpar = mtt_simpar ();
numpar = args(1).${vector_value} ();
state0 = args(0).${vector_value} ();
break;
case 1:
simpar = mtt_simpar ();
numpar = mtt_numpar ();
state0 = args(0).${vector_value} ();
break;
case 0:
simpar = mtt_simpar ();
numpar = mtt_numpar ();
state0 = mtt_state (numpar);
break;
default:
usage("${sys}_ode2odes (x par simpar)", nargin);
error("aborting.");
}
${sys}_ode2odes (state0, numpar, simpar);
retval = octave_value (get_global_value ("MTT_data"));
return (retval);
}
#elif (CODEGENTARGET == MATLABMEX)
#include <mtt_matlab_octave.hh>
extern "C" {
void
mexFunction (int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
static ColumnVector state0 (MTTNX);
static ColumnVector numpar (MTTNPAR);
static ColumnVector simpar (8);
initialize_symbol_tables ();
switch (nrhs)
{
case 3:
simpar = mtt_ColumnVector (prhs[2]);
numpar = mtt_ColumnVector (prhs[1]);
state0 = mtt_ColumnVector (prhs[0]);
break;
case 2:
simpar = mtt_simpar ();
numpar = mtt_ColumnVector (prhs[1]);
state0 = mtt_ColumnVector (prhs[0]);
break;
case 1:
simpar = mtt_simpar ();
numpar = mtt_numpar ();
state0 = mtt_ColumnVector (prhs[0]);
break;
case 0:
simpar = mtt_simpar ();
numpar = mtt_numpar ();
state0 = mtt_state (numpar);
break;
default:
std::cerr $insertor "usage: ${sys}_ode2odes (x par simpar)" $insertor std::endl;
return;
}
${sys}_ode2odes (state0, numpar, simpar);
plhs[0] = mtt_mxArray (get_global_value ("MTT_data").matrix_value ());
}
}
#endif // (CODEGENTARGET == STANDALONE)
EOF
}
case ${lang} in
m)
make_m
;;
cc)
make_cc
;;
*)
echo Language ${lang} is not supported
esac