Skip to content

Commit 4401437

Browse files
authored
Merge pull request #201 from KybernetikJo/add_ab04md
Add ab04md
2 parents 25fa7b0 + 118bf58 commit 4401437

File tree

5 files changed

+164
-1
lines changed

5 files changed

+164
-1
lines changed

slycot/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@
2727
# U : Utility Routines
2828

2929

30-
# Analysis routines (16/60 wrapped)
30+
# Analysis routines (17/60 wrapped)
3131
from .analysis import (ab01nd,
32+
ab04md,
3233
ab05md, ab05nd,
3334
ab07nd,
3435
ab08nd, ab08nz,

slycot/analysis.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,81 @@ def ab01nd(n, m, A, B, jobz='N', tol=0, ldwork=None):
139139
Z = None
140140
return Ac, Bc, ncont, indcon, nblk, Z, tau
141141

142+
def ab04md(type_t, n, m, p, A, B, C, D, alpha=1.0, beta=1.0, ldwork=None):
143+
""" At,Bt,Ct,Dt = ab04md(type_t, n, m, p, A, B, C, D, [alpha, beta,ldwork])
144+
145+
Parameters
146+
----------
147+
type_t : {'D','C'}
148+
Indicates the type of the original system and the
149+
transformation to be performed as follows:
150+
= 'D': discrete-time -> continuous-time;
151+
= 'C': continuous-time -> discrete-time.
152+
n : int
153+
The order of the matrix A, the number of rows of matrix B and
154+
the number of columns of matrix C. It represents the dimension of
155+
the state vector. n > 0.
156+
m : int
157+
The number of columns of matrix B. It represents the dimension of
158+
the input vector. m > 0.
159+
p : int
160+
The number of rows of matrix C. It represents the dimension of
161+
the output vector. p > 0.
162+
A : (n,n) array_like
163+
The leading n-by-n part of this array must contain the system state
164+
matrix A.
165+
B : (n,m) array_like
166+
The leading n-by-m part of this array must contain the system input
167+
matrix B.
168+
C : (p,n) array_like
169+
The leading p-by-n part of this array must contain the system output
170+
matrix C.
171+
D : (p,m) array_like
172+
The leading p-by-m part of this array must contain the system direct
173+
transmission matrix D.
174+
alpha : double, optional
175+
Parameter specifying the bilinear transformation.
176+
Recommended values for stable systems: alpha = 1, alpha != 0,
177+
Default is 1.0.
178+
beta : double, optional
179+
Parameter specifying the bilinear transformation.
180+
Recommended values for stable systems: beta = 1, beta != 0,
181+
Default is 1.0.
182+
ldwork : int, optional
183+
The length of the cache array.
184+
ldwork >= max(1, n), default is max(1, n)
185+
Returns
186+
-------
187+
At : (n,n) ndarray
188+
The state matrix At of the transformed system.
189+
Bt : (n,m) ndarray
190+
The input matrix Bt of the transformed system.
191+
Ct : (p,n) ndarray
192+
The output matrix Ct of the transformed system.
193+
Dt : (p,m) ndarray
194+
The transmission matrix Dt of the transformed system.
195+
Raises
196+
------
197+
SlycotArithmeticError
198+
:info == 1:
199+
If the matrix (ALPHA*I + A) is exactly singular
200+
:info == 2:
201+
If the matrix (BETA*I - A) is exactly singular.
202+
"""
203+
204+
hidden = ' (hidden by the wrapper)'
205+
arg_list = ['type_t', 'n', 'm', 'p', 'alpha', 'beta',
206+
'A', 'LDA'+hidden, 'B', 'LDB'+hidden, 'C', 'LDC'+hidden, 'D', 'LDD'+hidden,
207+
'IWORK'+hidden, 'DWORK'+hidden, 'ldwork', 'info'+hidden]
208+
209+
if ldwork is None:
210+
ldwork = max(1, n)
211+
212+
out = _wrapper.ab04md(type_t, n, m, p, alpha, beta, A, B, C, D, ldwork=ldwork)
213+
info=out[-1]
214+
raise_if_slycot_error(info, arg_list)
215+
216+
return out[:-1]
142217

143218
def ab05md(n1,m1,p1,n2,p2,A1,B1,C1,D1,A2,B2,C2,D2,uplo='U'):
144219
""" n,a,b,c,d = ab05md(n1,m1,p1,n2,p2,a1,b1,c1,d1,a2,b2,c2,d2,[uplo])

slycot/src/analysis.pyf

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,26 @@ subroutine ab01nd(jobz,n,m,a,lda,b,ldb,ncont,indcon,nblk,z,ldz,tau,tol,iwork,dwo
1919
integer :: ldwork = max(n,3*m)
2020
integer intent(out) :: info
2121
end subroutine ab01nd
22+
subroutine ab04md(type_t,n,m,p,alpha,beta,a,lda,b,ldb,c,ldc,d,ldd,iwork,dwork,ldwork,info) ! in AB04MD.f
23+
character :: type_t
24+
integer check(n>=0) :: n
25+
integer check(m>=0) :: m
26+
integer check(p>=0) :: p
27+
double precision intent(in) :: alpha
28+
double precision intent(in) :: beta
29+
double precision intent(in,out,copy), dimension(n,n),depend(n) :: a
30+
integer intent(hide),depend(a) :: lda = shape(a,0)
31+
double precision intent(in,out,copy), dimension(n,m),depend(n,m) :: b
32+
integer intent(hide),depend(b) :: ldb = shape(b,0)
33+
double precision intent(in,out,copy), dimension(p,n),depend(n,p) :: c
34+
integer intent(hide),depend(c) :: ldc = shape(c,0)
35+
double precision intent(in,out,copy), dimension(p,m),depend(m,p) :: d
36+
integer intent(hide),depend(d) :: ldd = shape(d,0)
37+
integer intent(hide,cache),dimension(n),depend(n) :: iwork
38+
double precision intent(hide,cache),dimension(ldwork),depend(ldwork) :: dwork
39+
integer :: ldwork = max(1,n)
40+
integer intent(out) :: info
41+
end subroutine ab04md
2242
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
2343
character :: uplo = 'U'
2444
character intent(hide) :: over = 'N' ! not sure how the overlap works

slycot/tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ set(PYSOURCE
22

33
__init__.py
44
test_ab01.py
5+
test_ab04md.py
56
test_ab08n.py
67
test_ag08bd.py
78
test_examples.py

slycot/tests/test_ab04md.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
from slycot import analysis
2+
import numpy as np
3+
4+
from numpy.testing import assert_allclose
5+
6+
7+
class test_ab04md:
8+
"""Test ab04md.
9+
10+
Example data taken from
11+
https://www.slicot.org/objects/software/shared/doc/AB04MD.html
12+
"""
13+
14+
Ac = np.array([[1.0, 0.5],
15+
[0.5, 1.0]])
16+
Bc = np.array([[0.0, -1.0],
17+
[1.0, 0.0]])
18+
Cc = np.array([[-1.0, 0.0],
19+
[0.0, 1.0]])
20+
Dc = np.array([[1.0, 0.0],
21+
[0.0, -1.0]])
22+
23+
Ad = np.array([[-1.0, -4.0],
24+
[-4.0, -1.0]])
25+
Bd = np.array([[2.8284, 0.0],
26+
[0.0, -2.8284]])
27+
Cd = np.array([[0.0, 2.8284],
28+
[-2.8284, 0.0]])
29+
Dd = np.array([[-1.0, 0.0],
30+
[0.0, -3.0]])
31+
32+
def test_ab04md_cont_disc_cont(self):
33+
"""Test transformation from continuous - to discrete - to continuous time.
34+
"""
35+
36+
n, m = self.Bc.shape
37+
p = self.Cc.shape[0]
38+
39+
Ad_t, Bd_t, Cd_t, Dd_t = analysis.ab04md(
40+
'C', n, m, p, self.Ac, self.Bc, self.Cc, self.Dc)
41+
42+
Ac_t, Bc_t, Cc_t, Dc_t = analysis.ab04md(
43+
'D', n, m, p, Ad_t, Bd_t, Cd_t, Dd_t)
44+
45+
assert_allclose(self.Ac, Ac_t)
46+
assert_allclose(self.Bc, Bc_t)
47+
assert_allclose(self.Cc, Cc_t)
48+
assert_allclose(self.Dc, Dc_t)
49+
50+
def test_ab04md_disc_cont_disc(self):
51+
"""Test transformation from discrete - to continuous - to discrete time.
52+
"""
53+
54+
n, m = self.Bc.shape
55+
p = self.Cc.shape[0]
56+
57+
Ac_t, Bc_t, Cc_t, Dc_t = analysis.ab04md(
58+
'D', n, m, p, self.Ad, self.Bd, self.Cd, self.Dd)
59+
60+
Ad_t, Bd_t, Cd_t, Dd_t = analysis.ab04md(
61+
'C', n, m, p, Ac_t, Bc_t, Cc_t, Dc_t)
62+
63+
assert_allclose(self.Ad, Ad_t)
64+
assert_allclose(self.Bd, Bd_t)
65+
assert_allclose(self.Cd, Cd_t)
66+
assert_allclose(self.Dd, Dd_t)

0 commit comments

Comments
 (0)