LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
SecondOrderLevelDependentFluidSolve.m
1% [masses, iniF, KF, cloF, iniB, KB, cloB] = SecondOrderLevelDependentFluidSolve (Q, R, S, T, boundaryL, boundaryU, Qt, prec)
2%
3% * Q: cell of generators in the different layers/regimes
4% * R: cell of diagonal matrices of fluid rates in the different layers/regimes
5% * S: cell of diagonal matrices of fluid variances in the different layers/regimes
6% * T: vector of thresholds
7% * boundaryL/U: vector defining the lower and the upper boundary behavior
8% one item for each state of the background process
9% =0: reflective boundary (default)
10% =1: absorbing boundary
11%
12% The performance measures (pdf, cdf, etc.) can be computed by the
13% LevelDependentFluidStationaryDistr function.
14%
15function [masses, iniF, KF, cloF, iniB, KB, cloB] = SecondOrderLevelDependentFluidSolve (Q, R, S, T, boundaryL, boundaryU, Qt, prec)
16
17 K = length(T);
18 N = size(Q{1},1);
19
20 if ~exist('prec','var')
21 prec = 1e-14;
22 end
23 if ~exist('boundaryL','var')
24 % zeros(1,N), not zeros(K,N): boundaryL/U is ONE flag per background
25 % state (see the header above, "vector defining the lower and the upper
26 % boundary behavior"), and there is a single lower and a single upper
27 % boundary rather than one per regime. All four use sites below index
28 % ix = 1:N with it, so a K x N default makes the logical mask larger
29 % than the array it indexes and the function crashed on its own defaults
30 % for every K >= 2 -- that is, for every genuinely multi-regime model.
31 % K == 1 survived by accident, zeros(1,N) being the correct shape there.
32 boundaryL = zeros(1,N);
33 end
34 if ~exist('boundaryU','var')
35 boundaryU = boundaryL;
36 end
37 if ~exist('Qt','var') || isempty(Qt)
38 for k=1:K
39 Qt{k} = Q{k};
40 end
41 Qt{K+1} = Q{K};
42 elseif length(Qt)==1
43 for k=2:K+1
44 Qt{k} = Qt{1};
45 end
46 end
47
48 T = [0,T];
49
50 % preparation
51 KF = cell(1,K);
52 KB = cell(1,K);
53 cloF = cell(1,K);
54 cloB = cell(1,K);
55 Np = zeros(1,K);
56 Nn = zeros(1,K);
57 Ns = zeros(1,K);
58 NbF = zeros(1,K);
59 NbB = zeros(1,K);
60 vixp = cell(1,K);
61 vixn = cell(1,K);
62 vix0 = cell(1,K);
63 vixs = cell(1,K);
64 vixsn = cell(1,K);
65 vixsp = cell(1,K);
66 vixs0 = cell(1,K);
67 for k=1:K
68
69 S{k} = S{k}/2;
70 % collect zero states
71 ix = (1:N);
72 ix0 = ix(abs(diag(R{k}))<=prec & diag(S{k})<=prec);
73 ixn0 = setdiff(ix,ix0);
74
75 Q00 = Q{k}(ix0,ix0);
76 Q0n = Q{k}(ix0,ixn0);
77 Qn0 = Q{k}(ixn0,ix0);
78 Qnn = Q{k}(ixn0,ixn0);
79
80 Qv = Qnn + Qn0*inv(-Q00)*Q0n;
81 Rv = R{k}(ixn0,ixn0);
82 Sv = S{k}(ixn0,ixn0);
83
84 Nnz = size(Qv,1);
85
86 % partition the state space according to zero, positive and negative fluid rates
87 ix = (1:Nnz);
88 ixp = ix(diag(Rv)>prec & diag(Sv)<=prec);
89 ixn = ix(diag(Rv)<-prec & diag(Sv)<=prec);
90 ixs = ix(diag(Sv)>prec);
91 Np(k) = length(ixp);
92 Nn(k) = length(ixn);
93 Ns(k) = length(ixs);
94
95 % FORWARD parameters
96
97 % obtain "c" constant to transform matrix equations to QBD like matrix
98 % quadratic equations
99 c1 = max(-diag(Qv(ixp,ixp))./diag(Rv(ixp,ixp)));
100 discr = (diag(Rv(ixs,ixs)).^2 - 2*diag(2*Sv(ixs,ixs)).*diag(Qv(ixs,ixs)));
101 c2 = max((discr>0).*((-diag(Rv(ixs,ixs))+sqrt(discr))./diag(2*Sv(ixs,ixs))));
102 c = max([c1,c2,1]);
103
104 ixbF = [ixs,ixp];
105 NbF(k) = length(ixbF);
106
107 Bm = blkdiag(c*Sv(ixbF,ixbF),-Rv(ixn,ixn));
108 Lm = [-Rv(ixbF,ixbF)-2*c*Sv(ixbF,ixbF),zeros(NbF(k),Nn(k));Qv(ixn,ixbF)/c,Qv(ixn,ixn)/c+Rv(ixn,ixn)];
109 Fm = [Qv(ixbF,ixbF)/c+c*Sv(ixbF,ixbF)+Rv(ixbF,ixbF),Qv(ixbF,ixn)/c;zeros(Nn(k),NbF(k)+Nn(k))];
110
111 % Solve QBD for matrix R
112 [~, QBDR] = QBD_CR(Bm, Lm, Fm);
113
114 % extract K and Psi from the solution
115 KF{k} = (QBDR(1:NbF(k),1:NbF(k)) - eye(NbF(k))) * c;
116 PsiF = QBDR(1:NbF(k),NbF(k)+1:end);
117
118 % closing matrix of the stationary density of the fluid level
119
120 clovF = zeros(NbF(k),NbF(k)+Nn(k));
121 clovF(:,ixbF) = eye(NbF(k));
122 clovF(:,ixn) = PsiF;
123
124 cloF{k} = zeros(NbF(k),N);
125 cloF{k}(:,ixn0) = clovF;
126 cloF{k}(:,ix0) = clovF*Qn0*inv(-Q00);
127
128 % BACKWARD parameters
129
130 % obtain "c" constant to transform matrix equations to QBD like matrix
131 % quadratic equations
132 c1 = max(-diag(Qv(ixn,ixn))./diag(-Rv(ixn,ixn)));
133 discr = (diag(Rv(ixs,ixs)).^2 - 2*diag(2*Sv(ixs,ixs)).*diag(Qv(ixs,ixs)));
134 c2 = max((discr>0).*((diag(Rv(ixs,ixs))+sqrt(discr))./diag(2*Sv(ixs,ixs))));
135 c = max([c1,c2,1]);
136
137 ixbB = [ixs,ixn];
138 NbB(k) = length(ixbB);
139
140 Bm = blkdiag(c*Sv(ixbB,ixbB),Rv(ixp,ixp));
141 Lm = [Rv(ixbB,ixbB)-2*c*Sv(ixbB,ixbB),zeros(NbB(k),Np(k));Qv(ixp,ixbB)/c,Qv(ixp,ixp)/c-Rv(ixp,ixp)];
142 Fm = [Qv(ixbB,ixbB)/c+c*Sv(ixbB,ixbB)-Rv(ixbB,ixbB),Qv(ixbB,ixp)/c;zeros(Np(k),NbB(k)+Np(k))];
143
144 % Solve QBD for matrix R
145 [~, QBDR] = QBD_CR(Bm, Lm, Fm);
146
147 % extract K and Psi from the solution
148 KB{k} = (QBDR(1:NbB(k),1:NbB(k)) - eye(NbB(k))) * c;
149 PsiB = QBDR(1:NbB(k),NbB(k)+1:end);
150
151 % closing matrix of the stationary density of the fluid level
152 clovB = zeros(NbB(k),NbB(k)+Np(k));
153 clovB(:,ixbB) = eye(NbB(k));
154 clovB(:,ixp) = PsiB;
155
156 cloB{k} = zeros(NbB(k),N);
157 cloB{k}(:,ixn0) = clovB;
158 cloB{k}(:,ix0) = clovB*Qn0*inv(-Q00);
159
160 vixp{k} = ixn0(ixp);
161 vixn{k} = ixn0(ixn);
162 vix0{k} = ix0;
163 vixs{k} = ixn0(ixs);
164 vixsn{k} = ixn0(diag(Sv)>prec & diag(Rv)<0);
165 vixsp{k} = ixn0(diag(Sv)>prec & diag(Rv)>=0);
166 vixs0{k} = ixn0(diag(Sv)>prec & diag(Rv)==0);
167 end
168
169 % Boundary vectors
170 % ================
171
172 % Construct and solve linear set of equations for the unknows (probability
173 % masses and density parameters iniF and iniB for all regimes)
174 % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
175 Neqns = (K+1)*N + sum(Np) + sum(Nn) + 2*sum(Ns);
176
177 if Neqns>300
178 M = sparse(Neqns,Neqns);
179 else
180 M = zeros(Neqns);
181 end
182 pos = 1;
183 for k=1:K
184 pos = [pos, N, NbF(k), NbB(k)];
185 end
186 pp = cumsum(pos);
187 p = 1;
188 i = 1;
189 % equalities for flux conservation
190 for k=0:K
191 M(pp(i):pp(i)+N-1,k*N+1:(k+1)*N) = -Qt{k+1};
192 if k>0
193 M(pp(i-2):pp(i-2)+NbF(k)-1,k*N+1:(k+1)*N) = expm(KF{k}*(T(k+1)-T(k)))*(-cloF{k}*R{k} + KF{k}*cloF{k}*S{k});
194 M(pp(i-1):pp(i-1)+NbB(k)-1,k*N+1:(k+1)*N) = -cloB{k}*R{k} - KB{k}*cloB{k}*S{k};
195 end
196 if k<K
197 M(pp(i+1):pp(i+1)+NbF(k+1)-1,k*N+1:(k+1)*N) = cloF{k+1}*R{k+1}-KF{k+1}*cloF{k+1}*S{k+1};
198 M(pp(i+2):pp(i+2)+NbB(k+1)-1,k*N+1:(k+1)*N) = expm(KB{k+1}*(T(k+2)-T(k+1)))*(cloB{k+1}*R{k+1} + KB{k+1}*cloB{k+1}*S{k+1});
199 end
200 i = i + 3;
201 end
202
203 % further equations
204 col = (K+1)*N+1;
205 ix = (1:N);
206 i = 1;
207 for k=0:K
208 if k==0
209 % mass is zero in positive and in reflective states
210 ixr0 = intersect(ix(boundaryL==0), vixs{1});
211 Nr0 = length(ixr0);
212 ms0 = zeros(N,Np(1)+Nr0);
213 ms0([vixp{1},ixr0],:) = eye(Np(1)+Nr0);
214 M(pp(i):pp(i)+N-1,col:col+Np(1)+Nr0-1) = ms0;
215 col = col + Np(1)+Nr0;
216 % density is zero in absorbing states
217 ixa0 = intersect(ix(boundaryL==1), vixs{1});
218 Na0 = length(ixa0);
219 pdfF = cloF{1};
220 pdfB = expm(KB{1}*T(2))*cloB{1};
221 M(pp(i+1):pp(i+1)+NbF(k+1)-1,col:col+Na0-1) = pdfF(:,ixa0);
222 M(pp(i+2):pp(i+2)+NbB(k+1)-1,col:col+Na0-1) = pdfB(:,ixa0);
223 col = col + Na0;
224 elseif k==K
225 % mass is zero in negative and in reflective states
226 ixrB = intersect(ix(boundaryU==0), vixs{K});
227 NrB = length(ixrB);
228 ms0 = zeros(N,Nn(K)+NrB);
229 ms0([vixn{K},ixrB],:) = eye(Nn(K)+NrB);
230 M(pp(i):pp(i)+N-1,col:col+Nn(K)+NrB-1) = ms0;
231 col = col + Nn(K)+NrB;
232 % density is zero in absorbing states
233 ixaB = intersect(ix(boundaryU==1), vixs{K});
234 NaB = length(ixaB);
235 pdfF = expm(KF{K}*(T(K+1)-T(K)))*cloF{K};
236 pdfB = cloB{K};
237 M(pp(i-2):pp(i-2)+NbF(k)-1,col:col+NaB-1) = pdfF(:,ixaB);
238 M(pp(i-1):pp(i-1)+NbB(k)-1,col:col+NaB-1) = pdfB(:,ixaB);
239 col = col + NaB;
240 else
241 % there is no mass except S+(k) U S-(k+1)
242 st0 = setdiff(ix, union(intersect(vixp{k},vixn{k+1}),union(vix0{k},vix0{k+1})));
243 N0 = length(st0);
244 ms0 = zeros(N,N0);
245 ms0(st0,:) = eye(N0);
246 M(pp(i):pp(i)+N-1,col:col+N0-1) = ms0;
247 col = col + N0;
248 % equations for the second-order states
249 sts = setdiff(union(vixs{k},vixs{k+1}), union(vixn{k+1},vixp{k}));
250 Nss = length(sts);
251 BelowF = expm(KF{k}*(T(k+1)-T(k)))*-cloF{k}*sqrt(S{k});
252 BelowB = -cloB{k}*sqrt(S{k});
253 AboveF = cloF{k+1}*sqrt(S{k+1});
254 AboveB = expm(KB{k+1}*(T(k+2)-T(k+1)))*cloB{k+1}*sqrt(S{k+1});
255 M(pp(i-2):pp(i-2)+NbF(k)-1,col:col+Nss-1) = BelowF(:,sts);
256 M(pp(i-1):pp(i-1)+NbB(k)-1,col:col+Nss-1) = BelowB(:,sts);
257 M(pp(i+1):pp(i+1)+NbF(k+1)-1,col:col+Nss-1) = AboveF(:,sts);
258 M(pp(i+2):pp(i+2)+NbB(k+1)-1,col:col+Nss-1) = AboveB(:,sts);
259 col = col + Nss;
260 end
261 i = i + 3;
262 end
263
264 % this function computes the integral of a matrix exponential from 0 to
265 % L if it has a 0 eigenvalue hence can not be inverted
266 function KAi = integExp(KA,L)
267 l=CRPSolve(KA);
268 r=CRPSolve(KA')';
269 l=l/(l*r);
270 KAi = inv(-(KA-r*l)) *(eye(size(KA,1))-expm((KA-r*l)*L)) + r*l*(L+exp(-L)-1);
271 end
272
273 % this function receives two matrices and calculates the integrals of
274 % the matrix exponentials if exactly one of them has a 0 eigenvalue
275 function [KAi,KBi] = integExp2(KA,KB,L)
276 if min(abs(eig(KA))) > min(abs(eig(KB)))
277 KAi = inv(-KA)*(eye(size(KA,1))-expm(KA*L));
278 KBi = integExp(KB, L);
279 else
280 KAi = integExp(KA, L);
281 KBi = inv(-KB)*(eye(size(KB,1))-expm(KB*L));
282 end
283 end
284
285 % normalizing condition
286 h = ones(N,1);
287 Mi = cell(1,K);
288 for k=1:K
289 [sumKF, sumKB] = integExp2(KF{k}, KB{k}, T(k+1)-T(k));
290 h = [h; sum(sumKF*cloF{k},2); sum(sumKB*cloB{k},2); ones(N,1)];
291 Mi{k} = [sum(sumKF*cloF{k},2); sum(sumKB*cloB{k},2)];
292 end
293
294 % solve linear system
295 M(:,1) = h;
296 b = [1,zeros(1,length(h)-1)]/M;
297
298 % obtain solution
299 masses = cell(1,K);
300 iniF = cell(1,K);
301 iniB = cell(1,K);
302 masses{1} = b(1:N);
303 i = 2;
304 for k=1:K
305 iniF{k} = b(pp(i):pp(i)+NbF(k)-1);
306 iniB{k} = b(pp(i+1):pp(i+1)+NbB(k)-1);
307 masses{k+1} = b(pp(i+2):pp(i+2)+N-1);
308 i = i + 3;
309 end
310end
311