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
ACompEvalCoreFun.m
Go to the documentation of this file.
1 namespace dscomponents{
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 dscomponents.ACoreFun {
56  public: /* ( Dependent ) */
57 
59 
60 
61  private:
62 
63  pts = {""};
64 
65 
66  jrow = {""};
74  jend = {""};
75 
76  jself = {""};
77 
78  deriv = {""};
79 
80  dfxsel = {""};
81 
82  T = {""};
83 
84 
85  protected:
86 
87  matrix<double> S = {""};
105  public:
106 
107 
109  this = this@dscomponents.ACoreFun(sys);
110  }
111 
112 
113  function fx = evaluateComponentSet(integer nr,colvec<double> x,double t) {
114  fx = this.evaluateComponents(this.PointSets[nr],...
115  this.jend[nr], this.jrow[nr], this.jself[nr], this.S[nr]*x, t);
116  }
131  fx = this.evaluateComponentsMulti(this.PointSets[nr],...
132  this.jend[nr], this.jrow[nr], this.jself[nr], this.S[nr]*x, t, mu);
133  }
151  dfx = this.evaluateComponentGradientsAt(this.PointSets[nr],...
152  this.jend[nr], this.jrow[nr], this.jself[nr],...
153  this.S[nr]*x, t) * this.S[nr];
154 
155  /* the multiplication by S{nr} from the right is due to the
156  * inner derivative (chain rule).
157  * this is identity if no projection occured.
158  * If this function has been projected, the argument passed to
159  * it is Vz, so the component set gradient is right-multiplied
160  * by the components of V (which are in S in this case, see
161  * setPointSet). */
162  }
180  function J = evaluateJacobianSet(integer nr,colvec<double> x,double t) {
181 
182  J = this.evaluateComponentPartialDerivatives(this.PointSets[nr],...
183  this.jend[nr], this.jrow[nr], this.deriv[nr], ...
184  this.jself[nr], this.S[nr]*x, t, this.dfxsel[nr]);
185  /* The deriv{nr} contains only derivative indices for non-zero
186  * jacobian elements (determined in setPointSet using the
187  * JSparsityPattern). Thus, the return values of
188  * evaluateComponentPartialDerivatives only are of the size of
189  * the actually non-zero jacobian values.
190  * The T matrix is a sparse transformation, that places those
191  * values into the correct spots with all other values that have
192  * been demanded to be evaluated but are actually zero.
193  *
194  * See setPointSet */
195  J = this.T[nr] * J;
196  }
214  singlemu = size(mu,2) == 1;
215  if isempty(mu)
216  mu = [];
217  singlemu = true;
218  end
219  if singlemu
220  this.prepareSimulation(mu);
221  end
222  if isempty(t)
223  t = double.empty(0,size(x,2));
224  elseif length(t) == 1
225  t = ones(1,size(x,2))*t;
226  end
227  m = size(x,2);
228  if m == 0
229  m = length(t);
230  end
231  J = zeros(length(this.deriv[nr]), m);
232  for idx = 1:size(x,2)
233  if ~singlemu
234  this.prepareSimulation(mu(:, idx));
235  end
236  J(:,idx) = this.evaluateComponentPartialDerivatives(this.PointSets[nr],...
237  this.jend[nr], this.jrow[nr], this.deriv[nr], ...
238  this.jself[nr], this.S[nr]*x(:,idx), t(idx), this.dfxsel[nr]);
239  end
240 
241  /* The deriv{nr} contains only derivative indices for non-zero
242  * jacobian elements (determined in setPointSet using the
243  * JSparsityPattern). Thus, the return values of
244  * evaluateComponentPartialDerivatives only are of the size of
245  * the actually non-zero jacobian values.
246  * The T matrix is a sparse transformation, that places those
247  * values into the correct spots with all other values that have
248  * been demanded to be evaluated but are actually zero.
249  *
250  * See setPointSet */
251  J = this.T[nr] * J;
252  }
274  function setPointSet(nr,pts,jpd) {
275 
276  if nr > 4
277  warning(" KerMor:Devel ",[" Point set numbering seems to " ...
278  " be used in a different context. 1-4 are safe to work "...
279  " with at this stage, make sure nothing gets overridden. "]);
280  end
281  /* Ensure row vectors */
282  if size(pts,1) > 1
283  pts = reshape(pts,1,[]);
284  end
285  if length(unique(pts)) ~= length(pts)
286  error(" Points have to be unique. ");
287  end
288 
289  this.pts[nr] = pts;
290 
291  jr = []; js = logical.empty(0,1);
292  je = zeros(1,length(pts));
293  SP = this.JSparsityPattern;
294  if ~isempty(SP)
295  /* Jacobian extras */
296  if nargin == 4
297  deri = [];
298  full_mapping = [];
299  requested_len = 0;
300  dfx_sel = sparse(length(pts),0);
301  end
302  for i=1:length(pts)
303  sprow = SP(pts(i),:);
304  inew = find(sprow);
305  if isempty(inew)
306  inew = 1;
307  warning(" setPointSet: Found all-zero Jacobian row for point %d. Using first state-space dof as 'dependency' ",pts(i));
308  end
309  jr = [jr inew];/* #ok */
310 
311  js = [js inew == pts(i)];/* #ok */
312 
313  je(i) = length(jr);
314  /* Jacobian extras */
315  if nargin == 4
316  des_der = jpd[i];
317  /* Select elements of sparsity pattern that have been
318  * requested to be evaluated on evaluateJacobianSet */
319  full_mapping = [full_mapping sprow(des_der)];/* #ok
320  * deri contains the accumulated indices of
321  * jacobian entries that are nonzero and thus make sense
322  * to evaluate. */
323 
324  [~, dpos, matchidx] = intersect(des_der, inew);
325  /* Take the match indices, but sort them in the order
326  * the elements occur in jpd{i} to maintain correct
327  * ordering. */
328  [~, sidx] = sort(dpos);
329  pos = reshape(matchidx(sidx),1,[]);
330 
331  /* pos1 = jpd{i}(deriv_elem); */
332  if ~isempty(pos)
333  if i==1
334  offs = 0;
335  else
336  offs = je(i-1);
337  end
338  deri = [deri pos+offs];/* #ok */
339 
340  end
341  /* Sum up the total length for later transformation */
342  requested_len = requested_len + length(des_der);
343 
344  /* Augment dfx selection matrix (only needed for default
345  * finite differences implementation) */
346  dfx_sel(i,(end+1):(end+length(inew))) = 1;/* #ok */
347 
348  end
349  end
350  else
351  warning(" Empty JSparsityPattern. DEIM approximation will not use any state space arguments. ");
352  end
353  this.jrow[nr] = jr;
354  this.jself[nr] = js;
355  this.jend[nr] = je;
356 
357  /* Compose x-entry selection matrix */
358  len = je(end);
359  sel = jr(1:len);
360  if ~isempty(this.V)
361  this.S[nr] = this.V(sel,:);
362  else
363  this.S[nr] = sparse(1:len,sel,ones(len,1),len,this.xDim);
364  end
365 
366  /* Extras for jacobian evaluations */
367  this.deriv[nr] = [];
368  this.T[nr] = [];
369  if nargin == 4
370  this.deriv[nr] = deri^t;
371  /* Find all the indices of the full mapping record that are
372  * nonzero */
373  at = find(full_mapping);
374  /* Create a sparse transformation matrix, that assigns the
375  * possibly nonzero jacobian entries returned by
376  * evaluateComponentPartialDerivatives to their correct spot
377  * according to the initially demanded derivatives (this
378  * inserts zeros everywhere). If no zero jacobian entries
379  * have been specified in setPointSet this is the identity
380  * matrix. */
381  this.T[nr] = sparse(at,1:length(at),ones(length(at),1),...
382  requested_len,length(at));
383  /* Store convenience dfx selection matrix */
384  this.dfxsel[nr] = logical(dfx_sel);
385  end
386  }
400  function target = project(V,W,target) {
401  if nargin < 4
402  target = this.clone;
403  end
404  target = project@dscomponents.ACoreFun(this, V, W, target);
405  /* In case the point sets are not created newly: update the
406  * current selection matrices */
407  for i=1:length(this.S)
408  if ~isempty(this.S[i])
409  target.S[i] = this.S[i]*V;
410  end
411  end
412  }
413 
414 
415  function copy = clone(copy) {
416  copy = clone@dscomponents.ACoreFun(this, copy);
417  copy.pts= this.pts;
418  copy.S= this.S;
419  copy.jrow= this.jrow;
420  copy.jend= this.jend;
421  copy.jself= this.jself;
422  copy.deriv= this.deriv;
423  copy.dfxsel= this.dfxsel;
424  copy.T= this.T;
425  }
426 
427 
428 
429 #if 0 //mtoc++: 'get.PointSets'
430 function psets = PointSets() {
431  psets = this.pts;
432  }
433 
434 #endif
435 
436 
437  function res = test_ComponentEvalMatch(xsize) {
438 
439  if ~isempty(this.V)
440  error(" Cannot run test for projected ACompEvalCoreFuns. ");
441  end
442 
443  if nargin < 2
444  xsize = 5;
445  end
446  x = rand(this.xDim,xsize);
447  mu = rand(20,xsize); /* simply assume param dim<=20 */
448 
449  t = rand(1,xsize);
450  fx = this.evaluateMulti(x, t, mu);
451  oldpts = [];
452  if ~isempty(this.PointSets)
453  oldpts = this.PointSets[1];
454  end
455 
456  nsets = 3;
457  s = RandStream(" mt19937ar "," Seed ",2);
458  /* Limit set sizes to 5000
459  *setsizes = s.randi(min(size(fx,1),5000), nsets, 1); @temp */
460  setsizes = s.randi(200, nsets, 1);
461  sets = cell(nsets,1);
462  for i = 1:length(setsizes)
463  sets[i] = unique(s.randi(size(fx,1),1,setsizes(i)));
464  end
465  /* Add an extra set with full size (only for functions with dim less than 10000) */
466  if size(fx,1) <= 10000
467  sets[end+1] = 1:size(fx,1);
468  end
469  res = true;
470 
471  for idx=1:length(sets)
472  set = sets[idx];
473  this.setPointSet(1, set);
474  fxc = this.evaluateComponentSetMulti(1, x, t, mu);
475  tmp = fx(set,:);
476  err = abs((tmp-fxc)./tmp);
477  err = err(tmp ~= 0);
478  d = max(err);
479  lres = isempty(d) || d < 1e-3;
480  if ~lres || d > 10*sqrt(eps)
481  fprintf(2," Warning! ACompEvalCoreFun evaluation test: Max rel. diff. for component wise vs. full evaluation: %e\n ",full(d));
482  end
483  res = res && lres;
484  end
485  if ~isempty(oldpts)
486  this.setPointSet(1,oldpts);
487  end
488  }
498  protected:
499 
501  dt = sqrt(eps);
502  d = size(x,1);
503  X = repmat(x,1,d); T = repmat(t,1,d); MU = repmat(this.mu,1,d);
504  I = speye(d,d)*dt;
505  hlp = this.evaluateComponents(pts, ends, idx, self, x, t);
506  dfx = (this.evaluateComponentsMulti(pts, ends, idx, self, X+I, T, MU) ...
507  - repmat(hlp,1,d))/dt;
508  }
538  dt = sqrt(eps);
539  d = length(deriv);
540  xd = size(x,2);
541 
542  X = repmat(x,1,d); T = repmat(t,1,d); /* #ok<*PROP> */
543 
544  I = sparse(deriv,1:d,ones(1,d),size(x,1),d)*dt;
545  dfx = (this.evaluateComponentsMulti(pts, ends, idx, self, X+I, T, this.mu) ...
546  - this.evaluateComponentsMulti(pts, ends, idx, self, X, T, this.mu))/dt;
547  dfx = dfx(repmat(dfxsel(:,deriv),1,xd));
548  }
581  function dfx = evaluateComponentPartialDerivativesMulti(pts,ends,idx,deriv,self,colvec<double> x,double t,colvec<double> mu,dfxsel) {
582  dt = sqrt(eps);
583  d = length(deriv);
584  xd = size(x,2);
585  el = reshape(repmat(1:xd,d,1),1,[]);
586  X = x(:,el); T = t(el); MU = mu(:,el);
587  I = repmat(sparse(deriv,1:d,ones(1,d),size(x,1),d)*dt,1,xd);
588  dfx = (this.evaluateComponentsMulti(pts, ends, idx, self, X+I, T, MU) ...
589  - this.evaluateComponentsMulti(pts, ends, idx, self, X, T, MU))/dt;
590  dfx = dfx(repmat(dfxsel(:,deriv),1,xd));
591  dfx = reshape(dfx,[],xd);
592  }
607  function fx = evaluateComponentsMulti(pts,ends,idx,self,colvec<double> x,double t,colvec<double> mu) {
608  fx = zeros(length(pts),size(x,2));
609  for k=1:size(x,2)
610  this.prepareSimulation(mu(:,k));
611  fx(:,k) = this.evaluateComponents(pts, ends, idx, self, x(:,k), t(k));
612  end
613  }
625  protected: /* ( Abstract ) */
626 
656  protected: /* ( Static ) */
657 
658  static function obj = loadobj(obj,from) {
659  if nargin == 2
660  obj.pts= from.pts;
661  obj.S= from.S;
662  obj.jrow= from.jrow;
663  obj.jend= from.jend;
664  obj.jself= from.jself;
665  obj.deriv= from.deriv;
666  obj.dfxsel= from.dfxsel;
667  obj.T= from.T;
668  obj = loadobj@dscomponents.ACoreFun(obj, from);
669  else
670  obj = loadobj@dscomponents.ACoreFun(obj);
671  end
672  }
673 
680 };
681 }
682 
function res = test_ComponentEvalMatch(xsize)
Tests if the local implementation of evaluateComponents matches the full evaluation.
function J = evaluateJacobianSet(integer nr,colvec< double > x,double t)
Returns the jacobian entries of the point set that have been specified using setPointSet's argument j...
function prepareSimulation(colvec< double > mu)
A method that allows parameter-dependent computations to be performed before a simulation using this ...
Definition: ACoreFun.m:380
A MatLab cell array or matrix.
virtual function fx = evaluateComponents(rowvec< integer > pts,rowvec< integer > ends,rowvec< integer > idx,rowvec< integer > self,matrix< double > x,rowvec< double > t,colvec< double > mu)
This is the template method that actually evaluates the components at given points and values...
sort
ort the handle objects in any array in ascending or descending order.
function dfx = evaluateComponentPartialDerivatives(rowvec< integer > pts,rowvec< integer > ends,rowvec< integer > idx,rowvec< integer > deriv,rowvec< integer > self,colvec< double > x,double t, dfxsel)
Computes specified partial derivatives of of the components given by pts and the selected partial de...
reshape
hanges the dimensions of the handle object array to the specified dimensions. See the MATLAB reshape ...
An integer value.
function fx = evaluateComponentSetMulti(integer nr,matrix< double > x,rowvec< double > t,matrix< double > mu)
Computes the full component functions of the given point set.
#define I(x, y, z)
Definition: CalcMD5.c:171
matrix< double > S
The x-component selection matrices (precomputed on setting PointSet/AltPointSet). �S� is passed to ...
A boolean value.
Basic interface for all dynamical system's core functions Inherits the AProjectable interface...
Definition: ACoreFun.m:18
integer xDim
The current state space dimension of the function's argument .
Definition: ACoreFun.m:151
function copy = clone(copy)
The interface method with returns a copy of the current class instance.
V
The matrix of the biorthogonal pair .
Definition: AProjectable.m:61
colvec< double > mu
The current model parameter mu for evaluations. Will not be persisted as only valid for runtime durin...
Definition: ACoreFun.m:208
#define X(i, j)
function setPointSet(nr, pts, jpd)
Parameters: pts: A row vector with the desired points jpd: ("Jacobian Partial Derivatives") A cell ar...
function target = project(V, W, target)
function matrix< double > dfx = evaluateComponentGradientsAt(rowvec< integer > pts,rowvec< integer > ends,rowvec< integer > idx,rowvec< integer > self,colvec< double > x,double t)
Default implementation of gradient computation via finite differences.
sparse< logical > JSparsityPattern
Sparsity pattern for the jacobian matrix.
Definition: ACoreFun.m:127
function fx = evaluateComponentsMulti(pts, ends, idx, self,colvec< double > x,double t,colvec< double > mu)
ACompEvalCoreFun: A normal CoreFun which supports single-component evaluation.
function fx = evaluateMulti(colvec< double > x,double t,colvec< double > mu)
Evaluates this function on multiple locations and maybe multiple times and parameters.
Definition: ACoreFun.m:335
static function obj = loadobj(obj, from)
function J = evaluateJacobianSetMulti(integer nr,matrix< double > x,rowvec< double > t,colvec< double > mu)
Returns the jacobian entries at multiple locations/times/parameters of the point set that have been s...
W
The matrix of the biorthogonal pair .
Definition: AProjectable.m:72
function dfx = evaluateComponentSetGradientsAt(integer nr,colvec< double > x,double t)
Computes the full/reduced gradients of all component functions of the given point set...
function dfx = evaluateComponentPartialDerivativesMulti(pts, ends, idx, deriv, self,colvec< double > x,double t,colvec< double > mu, dfxsel)
Multi-argument evaluation method for partial derivatives. Not used so far in KerMor, this is "legacy code" to keep around if needed at any stage as default finite difference-implementation.
function fx = evaluateComponentSet(integer nr,colvec< double > x,double t)
Computes the full or reduced component functions of the given point set.