KerMor  0.9
Model order reduction for nonlinear dynamical systems and nonlinear approximation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ABlockedData.m
Go to the documentation of this file.
1 namespace data{
2 
3 
4 /* (Autoinserted by mtoc++)
5  * This source code has been filtered by the mtoc++ executable,
6  * which generates code that can be processed by the doxygen documentation tool.
7  *
8  * On the other hand, it can neither be interpreted by MATLAB, nor can it be compiled with a C++ compiler.
9  * Except for the comments, the function bodies of your M-file functions are untouched.
10  * Consequently, the FILTER_SOURCE_FILES doxygen switch (default in our Doxyfile.template) will produce
11  * attached source files that are highly readable by humans.
12  *
13  * Additionally, links in the doxygen generated documentation to the source code of functions and class members refer to
14  * the correct locations in the source code browser.
15  * However, the line numbers most likely do not correspond to the line numbers in the original MATLAB source files.
16  */
17 
19  :public handle {
40  public:
41 
53  public:
54 
55  function [matrix<double>U , matrix<double>S , matrix<double>V ] = getSVD(integer k,matrix<double> Vexclude,colvec<integer> targetdims) {
56  if nargin < 4
57  targetdims = " : ";
58  if nargin < 3
59  Vexclude = [];
60  end
61  end
62  /* Get the correct dimensions if some are to be excluded */
63  [n, m] = size(this);
64  if ~ischar(targetdims)
65  /* Use the number of target dims for n if not all are used */
66  n = length(targetdims);
67  end
68  /* Assume full size if k is not set or empty */
69  if nargin < 2 || isempty(k)
70  k = min(n,m);
71  end
72  /* Reduce target dimension if remaining dimension is smaller */
73  if ~isempty(Vexclude)
74  k = min(k, min(n,m)-size(Vexclude,2));
75  else
76  k = min(k, min(n,m));
77  end
78 
79  /* Fetch case for one block only */
80  if this.getNumBlocks == 0
81  U = [];
82  S = [];
83  elseif this.getNumBlocks == 1
84  Bl = this.getBlock(1);
85  Bl = Bl(targetdims,:);
86  /* Subtract exclude space if wanted */
87  if ~isempty(Vexclude)
88  Bl = Bl - Vexclude*(Vexclude^t*Bl);
89  end
90  [U, S] = svd(Bl," econ ");
91  U = U(:,1:k);
92  S = S(1:k,1:k);
93  else
94  /* Fully-flavoured singular value decomp using block
95  * separation */
96  opts.issym= 1;
97  if KerMor.App.Verbose > 0
98  fprintf(" ABlockedData: Computing %d-partial SVD on %dx%d matrix (%d blocks)...\n ",...
99  k,n,m,this.getNumBlocks);
100  end
101  vb = KerMor.App.Verbose > 1 && n*m > 50000 && this.getNumBlocks > 2;
102  cnt = 0;
103  /* If an exclude space is given, choose initial value outside of Vexclude */
104  if ~isempty(Vexclude)
105  v0 = rand(n,1);
106  opts.v0= v0 - Vexclude*(Vexclude^t*v0);
107  end
108  doparallel = exist(" matlabpool "," file ") == 2 && matlabpool(" size ") > 1;
109  [U,S] = eigs(@mult,n,k," la ",opts);
110  if KerMor.App.Verbose > 2, fprintf(" BlockSVD: Finished after %d multiplications.\n ",cnt); end
111  S = sqrt(S);
112  end
113  sel = sqrt(diag(S)/S(1)) >= this.MinRelSingularValueSize & diag(S)>0;
114  U = U(:,sel);
115  if size(U,2) < k
116  warning(" KerMor:ABlockedData "," Have only %d nonzero singular values instead of %d desired ones. ",...
117  size(U,2),k);
118  end
119  S = S(sel,sel);
120  if nargout > 2
121  /* Treat this special case here instead of cloning everything */
122  if ~ischar(targetdims)
123  error(" Fixme: Not correctly implemented yet. ");
124  [nfull,~] = size(this);
125  mat = eye(nfull);
126  mat(targetdims,targetdims) = (U/S)^t;
127  V = mat*this;
128  V = V(targetdims,:);
129  else
130  V = (U/S)^t*this;
131  end
132  end
133 
134  function w = mult(v)
135  w = 0;
136  nb = this.getNumBlocks;
137  if vb && ~doparallel
138  pi = ProcessIndicator(" ABlockedData: Blockwise multiplication for %d-SVD on %d blocks ",...
139  nb,false,k,nb);
140  end
141  if doparallel
142  if vb
143  fprintf(" ABlockedData: Parallel blockwise multiplication for %d-SVD on %d blocks...\n ",k,nb);
144  end
145  parfor j = 1:nb
146  B = this.getBlock(j);/* #ok */
147 
148  B = B(targetdims,:);
149  /* Subtract exclude space if wanted */
150  if ~isempty(Vexclude)
151  B = B - Vexclude*(Vexclude^t*B);
152  end
153  w = w + B*(B^t*v);
154  end
155  else
156  for j = 1:nb
157  B = this.getBlock(j);
158  B = B(targetdims,:);
159  /* Subtract exclude space if wanted */
160  if ~isempty(Vexclude)
161  B = B - Vexclude*(Vexclude^t*B);
162  end
163  w = w + B*(B^t*v);
164  if vb, pi.step; end
165  end
166  end
167  if vb, pi.stop; end
168  cnt=cnt+1;
169  end
170  }
193  function prod = mtimes() {
194  if isa(matrix," data.ABlockedData ")
195  error(" Must override in subclasses for case ABlockedData*matrix. ");
196  else
197  warning(" KerMor:ABlockedData ",...
198  " If you want the right singular values, you need to override the mtimes method of data.ABlockedData(matrix, this).\nReturning the same instance for V. ");
199  end
200  prod = this;
201  }
210  function A = toMemoryMatrix() {
211  A = zeros(size(this));
212  pos = 1;
213  for i=1:this.getNumBlocks
214  B = this.getBlock(i);
215  s = size(B,2)-1;
216  A(:,pos:pos+s) = B;
217  pos = pos + s + 1;
218  end
219  }
227  public: /* ( Abstract ) */
228 
229  virtual function varargout = size(dim) = 0;
230 
231 
232  virtual function n = getNumBlocks() = 0;
233 
234 
235  virtual function B = getBlock(nr) = 0;
236 
237 
238  public: /* ( Static ) */
239 
240  static function res = test_BlockSVD_vs_SVD() {
241  blocks = 5;
242  ns = 6;
243  an = [500 1000 700];
244  am = [500 700 1000];
245  res = true;
246  for v = 1:3
247  n = an(v);
248  m = am(v);
249  for nb=1:blocks
250  B = rand(n,m);
251  A = data.FileMatrix(n,m," BlockSize ",data.FileMatrix.blockSizeOf(B)/nb);
252  A.subsasgn(struct(" type ",[" () "]," subs ",[[" : ", " : "]]),B);
253  [ub,us] = A.getSVD(ns);
254  [u,s] = svd(B," econ ");
255  chk = norm(diag(us)-diag(s(1:ns,1:ns)));
256  res = res && chk < 1e-8;
257  /* mess with directions - so correct */
258  ubs = sign(ub(1,:));
259  us = sign(u(1,1:ns));
260  chk2 = norm(bsxfun(@times,ub,ubs)-bsxfun(@times,u(:,1:ns),us));
261  res = res & chk2 < 1e-8;
262  fprintf(" Comparison Block-SVD vs SVD (%d singular values): Singular value vector norm diff: %g, U norm diff: %g\n ",ns,chk,chk2);
263  end
264  end
265  }
266 
267 
268 };
269 }
270 
virtual function n = getNumBlocks()
ABlockedData: General abstract class that allows computation of and SVD on a large matrix that is sep...
Definition: ABlockedData.m:18
A double value.
An integer value.
Matlab's base handle class (documentation generation substitute)
virtual function B = getBlock(nr)
A matlab column vector.
function prod = mtimes()
Need left-sided matrix multiplication if RHS singular vectors V should be returned.
Definition: ABlockedData.m:193
double MinRelSingularValueSize
The minimum relative value of singular values that triggers selection of the compared to the largest ...
Definition: ABlockedData.m:42
Global configuration class for all KerMor run-time settings.
Definition: KerMor.m:17
static function KerMor theinstance = App()
The singleton KerMor instance.
Definition: KerMor.m:910
function A = toMemoryMatrix()
Converts this FileMatrix to a full double matrix.
Definition: ABlockedData.m:210
virtual function varargout = size(dim)
static function res = test_BlockSVD_vs_SVD()
Definition: ABlockedData.m:240
ProcessIndicator: A simple class that indicates process either via waitbar or text output...
function [ matrix< double > U , matrix< double > S , matrix< double > V ] = getSVD(integer k,matrix< double > Vexclude,colvec< integer > targetdims)
Computes an SVD on this blockwise matrix .
Definition: ABlockedData.m:55