Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ab04md #201

Merged
merged 8 commits into from
Aug 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion slycot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@
# U : Utility Routines


# Analysis routines (16/60 wrapped)
# Analysis routines (17/60 wrapped)
from .analysis import (ab01nd,
ab04md,
ab05md, ab05nd,
ab07nd,
ab08nd, ab08nz,
Expand Down
75 changes: 75 additions & 0 deletions slycot/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,81 @@ def ab01nd(n, m, A, B, jobz='N', tol=0, ldwork=None):
Z = None
return Ac, Bc, ncont, indcon, nblk, Z, tau

def ab04md(type_t, n, m, p, A, B, C, D, alpha=1.0, beta=1.0, ldwork=None):
""" At,Bt,Ct,Dt = ab04md(type_t, n, m, p, A, B, C, D, [alpha, beta,ldwork])

Parameters
----------
type_t : {'D','C'}
Indicates the type of the original system and the
transformation to be performed as follows:
= 'D': discrete-time -> continuous-time;
= 'C': continuous-time -> discrete-time.
n : int
The order of the matrix A, the number of rows of matrix B and
the number of columns of matrix C. It represents the dimension of
the state vector. n > 0.
m : int
The number of columns of matrix B. It represents the dimension of
the input vector. m > 0.
p : int
The number of rows of matrix C. It represents the dimension of
the output vector. p > 0.
A : (n,n) array_like
The leading n-by-n part of this array must contain the system state
matrix A.
B : (n,m) array_like
The leading n-by-m part of this array must contain the system input
matrix B.
C : (p,n) array_like
The leading p-by-n part of this array must contain the system output
matrix C.
D : (p,m) array_like
The leading p-by-m part of this array must contain the system direct
transmission matrix D.
alpha : double, optional
Parameter specifying the bilinear transformation.
Recommended values for stable systems: alpha = 1, alpha != 0,
Default is 1.0.
beta : double, optional
Parameter specifying the bilinear transformation.
Recommended values for stable systems: beta = 1, beta != 0,
Default is 1.0.
ldwork : int, optional
The length of the cache array.
ldwork >= max(1, n), default is max(1, n)
Returns
-------
At : (n,n) ndarray
The state matrix At of the transformed system.
Bt : (n,m) ndarray
The input matrix Bt of the transformed system.
Ct : (p,n) ndarray
The output matrix Ct of the transformed system.
Dt : (p,m) ndarray
The transmission matrix Dt of the transformed system.
Raises
------
SlycotArithmeticError
:info == 1:
If the matrix (ALPHA*I + A) is exactly singular
:info == 2:
If the matrix (BETA*I - A) is exactly singular.
"""

hidden = ' (hidden by the wrapper)'
arg_list = ['type_t', 'n', 'm', 'p', 'alpha', 'beta',
'A', 'LDA'+hidden, 'B', 'LDB'+hidden, 'C', 'LDC'+hidden, 'D', 'LDD'+hidden,
'IWORK'+hidden, 'DWORK'+hidden, 'ldwork', 'info'+hidden]

if ldwork is None:
ldwork = max(1, n)

out = _wrapper.ab04md(type_t, n, m, p, alpha, beta, A, B, C, D, ldwork=ldwork)
info=out[-1]
raise_if_slycot_error(info, arg_list)

return out[:-1]

def ab05md(n1,m1,p1,n2,p2,A1,B1,C1,D1,A2,B2,C2,D2,uplo='U'):
""" n,a,b,c,d = ab05md(n1,m1,p1,n2,p2,a1,b1,c1,d1,a2,b2,c2,d2,[uplo])
Expand Down
20 changes: 20 additions & 0 deletions slycot/src/analysis.pyf
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,26 @@ subroutine ab01nd(jobz,n,m,a,lda,b,ldb,ncont,indcon,nblk,z,ldz,tau,tol,iwork,dwo
integer :: ldwork = max(n,3*m)
integer intent(out) :: info
end subroutine ab01nd
subroutine ab04md(type_t,n,m,p,alpha,beta,a,lda,b,ldb,c,ldc,d,ldd,iwork,dwork,ldwork,info) ! in AB04MD.f
character :: type_t
integer check(n>=0) :: n
integer check(m>=0) :: m
integer check(p>=0) :: p
double precision intent(in) :: alpha
double precision intent(in) :: beta
double precision intent(in,out,copy), dimension(n,n),depend(n) :: a
integer intent(hide),depend(a) :: lda = shape(a,0)
double precision intent(in,out,copy), dimension(n,m),depend(n,m) :: b
integer intent(hide),depend(b) :: ldb = shape(b,0)
double precision intent(in,out,copy), dimension(p,n),depend(n,p) :: c
integer intent(hide),depend(c) :: ldc = shape(c,0)
double precision intent(in,out,copy), dimension(p,m),depend(m,p) :: d
integer intent(hide),depend(d) :: ldd = shape(d,0)
integer intent(hide,cache),dimension(n),depend(n) :: iwork
double precision intent(hide,cache),dimension(ldwork),depend(ldwork) :: dwork
integer :: ldwork = max(1,n)
integer intent(out) :: info
end subroutine ab04md
subroutine ab05md(uplo,over,n1,m1,p1,n2,p2,a1,lda1,b1,ldb1,c1,ldc1,d1,ldd1,a2,lda2,b2,ldb2,c2,ldc2,d2,ldd2,n,a,lda,b,ldb,c,ldc,d,ldd,dwork,ldwork,info) ! in AB05MD.f
character :: uplo = 'U'
character intent(hide) :: over = 'N' ! not sure how the overlap works
Expand Down
1 change: 1 addition & 0 deletions slycot/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ set(PYSOURCE

__init__.py
test_ab01.py
test_ab04md.py
test_ab08n.py
test_ag08bd.py
test_examples.py
Expand Down
66 changes: 66 additions & 0 deletions slycot/tests/test_ab04md.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from slycot import analysis
import numpy as np

from numpy.testing import assert_allclose


class test_ab04md:
"""Test ab04md.

Example data taken from
https://www.slicot.org/objects/software/shared/doc/AB04MD.html
"""

Ac = np.array([[1.0, 0.5],
[0.5, 1.0]])
Bc = np.array([[0.0, -1.0],
[1.0, 0.0]])
Cc = np.array([[-1.0, 0.0],
[0.0, 1.0]])
Dc = np.array([[1.0, 0.0],
[0.0, -1.0]])

Ad = np.array([[-1.0, -4.0],
[-4.0, -1.0]])
Bd = np.array([[2.8284, 0.0],
[0.0, -2.8284]])
Cd = np.array([[0.0, 2.8284],
[-2.8284, 0.0]])
Dd = np.array([[-1.0, 0.0],
[0.0, -3.0]])

def test_ab04md_cont_disc_cont(self):
"""Test transformation from continuous - to discrete - to continuous time.
"""

n, m = self.Bc.shape
p = self.Cc.shape[0]

Ad_t, Bd_t, Cd_t, Dd_t = analysis.ab04md(
'C', n, m, p, self.Ac, self.Bc, self.Cc, self.Dc)

Ac_t, Bc_t, Cc_t, Dc_t = analysis.ab04md(
'D', n, m, p, Ad_t, Bd_t, Cd_t, Dd_t)

assert_allclose(self.Ac, Ac_t)
assert_allclose(self.Bc, Bc_t)
assert_allclose(self.Cc, Cc_t)
assert_allclose(self.Dc, Dc_t)

def test_ab04md_disc_cont_disc(self):
"""Test transformation from discrete - to continuous - to discrete time.
"""

n, m = self.Bc.shape
p = self.Cc.shape[0]

Ac_t, Bc_t, Cc_t, Dc_t = analysis.ab04md(
'D', n, m, p, self.Ad, self.Bd, self.Cd, self.Dd)

Ad_t, Bd_t, Cd_t, Dd_t = analysis.ab04md(
'C', n, m, p, Ac_t, Bc_t, Cc_t, Dc_t)

assert_allclose(self.Ad, Ad_t)
assert_allclose(self.Bd, Bd_t)
assert_allclose(self.Cd, Cd_t)
assert_allclose(self.Dd, Dd_t)
Loading