-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgram_schmidt_mod.m
More file actions
120 lines (110 loc) · 4.36 KB
/
gram_schmidt_mod.m
File metadata and controls
120 lines (110 loc) · 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
function Q = gram_schmidt_mod(EVS,sd)
% This file is part of GPCCA.
%
% Copyright (c) 2019, 2018, 2017 Bernhard Reuter
%
% If you use this code or parts of it, cite the following reference:
%
% Reuter, B., Weber, M., Fackeldey, K., Röblitz, S., & Garcia, M. E. (2018). Generalized
% Markov State Modeling Method for Nonequilibrium Biomolecular Dynamics: Exemplified on
% Amyloid β Conformational Dynamics Driven by an Oscillating Electric Field. Journal of
% Chemical Theory and Computation, 14(7), 3579–3594. https://doi.org/10.1021/acs.jctc.8b00079
%
% GPCCA is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published
% by the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program 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 Lesser General Public License
% along with this program. If not, see <http://www.gnu.org/licenses/>.
% -------------------------------------------------------------------------
% function to orthonormalize vectors - modified numerically stable version
%
% Q = gram_schmidt_mod( EVS, sd )
%
% Input:
% EVS (N,N)-matrix with eigen-/Schurvectors of
% Pd=diag(sqrt(sd))*P*diag(1.0./sqrt(sd))
% sd "initial distribution"
%
% Output:
% Q (N,N)-matrix with orthonormalized eigen-/Schur-
% vectors of Pd and sqrt(sd) on the first column
%
% Written by Bernhard Reuter, Theoretical Physics II,
% University of Kassel, 2017,2018,2019
% -----------------------------------------------------------------------
class_t1 = class(EVS);
class_t2 = class(sd) ;
if (strcmpi(class_t1,class_t2))
class_t = class_t1 ;
else
error('gram_schmidt_mod:EVS_sd_DataTypeError', ...
['class(EVS) is not equal class(sd)! this will lead to numeric' ...
'presicion errors!'])
end
function r = num_t(expression)
if (nargin > 0)
if(strcmpi(class_t,'mp')), r = mp(expression) ;
else
if isnumeric(expression)
r = expression ;
else
r = eval(expression) ;
end
end
else
r = class_t ;
end
end % num_t
% -----------------------------------------------------------------------
[m,n] = size(EVS) ;
assert(m > 1,'gram_schmidt_mod:MatrixShapeError1', ...
'The given matrix has only 1 row.') ;
assert(n > 1,'gram_schmidt_mod:MatrixShapeError2', ...
'The given matrix has only 1 column.') ;
Q = num_t(zeros(m,n)) ;
R = num_t(zeros(n,n)) ;
% search for the constant eigen-/Schurvector, if explicitly present
max_i = 1 ;
for i = 1:n
vsum = sum(EVS(:,i)) ;
dummy = abs(EVS(:,i) - ( ones(size(EVS(:,i))) * (vsum/m) )) ;
dummy1 = ( dummy < ( num_t('1000000') * eps(num_t) ) ) ;
if all(dummy1(:))
max_i = i ;
end
end
% keep copy of the original eigen-/Schurvectors for later sanity check
cEVS = EVS ;
% shift non-constant first eigen-/Schurvector to the right
EVS(:,max_i) = EVS(:,1) ;
% set first eigen-/Schurvector equal sqrt(sd)
% (in do_schur.m the Q-matrix, orthogonalized by gram_schmidt_mod.m,
% will be multiplied with 1.0./sqrt(sd) - so the first eigen-/Schur-
% vector will become the unit vector 1!
EVS(:,1) = sqrt(sd) ;
% assert that the subspace didn't change!
assert(subspace(EVS,cEVS) < (num_t('1000000')*eps(num_t)), ...
'gram_schmidt_mod:SubspaceError1', ...
'The derived subspace doesnt match the original one!') ;
% sd-orthogonalize
for j=1:n
v = EVS(:,j) ;
for i=1:j-1
R(i,j) = Q(:,i)' * v ;
v = v - R(i,j) * Q(:,i) ;
end
R(j,j) = norm(v) ;
Q(:,j) = v / R(j,j) ;
end
% assert that the subspace didn't change!
assert(subspace(Q,cEVS) < (num_t('1000000')*eps(num_t)), ...
'gram_schmidt_mod:SubspaceError2', ...
'The derived subspace doesnt match the original one!') ;
end