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
AdaptiveSemiImplicitEuler.m
Go to the documentation of this file.
1 namespace solvers{
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 solvers.BaseCustomSolver {
49  private:
50 
51  model;
52 
53 
54  public:
55 
62 q;
63 
64  h0;
65 
66 
67  public:
68 
70 
71  if nargin < 4
72  h0 = 1e-3;
73  if nargin < 3
74  q = 0.3;
75  if nargin < 2
76  epsilon = 1e-2;
77  end
78  end
79  end
80  this.h0= h0;
81  this.q= q;
82  this.epsilon= epsilon;
83  this.model= model;
84  this.Name= " adaptive semi-implicit euler method ";
85  }
86 
87 
88  protected:
89 
90  function matrix<double>x = customSolve(unused1,t,x0,unused2) {
91 
92  s = this.model.System;
93  if isempty(s.A)
94  error(" This solver requires an (affine) linear system component A. ");
95  end
96 
97  h = this.h0;
98  time = t(1);
99  t_end = t(end);
100 
101 
102  rtm = this.RealTimeMode;
103 
104  steps = 0;
105  /* Create return matrix in size of effectively desired timesteps */
106  x = zeros(size(x0,1),length(t));
107  x(:,1) = x0;
108  oldx = x0;
109  /* Initialize output index counter */
110  outidx = 2;
111 
112  oldex = []; newex = []; edim = 0; est = [];
113  if isa(this.model," models.ReducedModel ")
114  est = this.model.ErrorEstimator;
115  if ~isempty(est) && est.Enabled
116  edim = est.ExtraODEDims;
117  oldex = x0(end-edim+1:end);
118  end
119  end
120 
121  /* Check if a mass matrix is present, otherwise assume identity matrix */
122  M = speye(length(x0)-edim);
123  mdep = false;
124  if ~isempty(s.M)
125  mdep = s.M.TimeDependent;
126  if ~mdep
127  M = s.M.evaluate(0);
128  end
129  end
130 
131  fdep = s.A.TimeDependent;
132  if ~fdep
133  /* Evaluation with x=1 "extracts" the matrix A of the (affine) linear system */
134  A = s.A.evaluate(1, 0, s.mu);
135  end
136 
137  /* Precompute lu decomp for iteration steps if all components are not time-dependent */
138  if ~mdep && ~fdep
139  [l1, u1] = lu(M - h * A);
140  end
141 
142  if ~mdep && ~fdep
143  [l2, u2] = lu(M - h/2 * A);
144  end
145 
146  /* Solve for each time step
147  *oldx = x0(1:end-edim); */
148  count = 0;
149  while time < t_end;
150  delta = 0.5 * this.epsilon * (1-this.q); /* garantees that the inner while loop is entered */
151 
152  firstloop = true;
153  /* time */
154 
155  while ((delta/this.epsilon) < (1 - this.q)) || ((delta/this.epsilon) > (1 + this.q))
156  if ~firstloop
157  h = h * (this.epsilon / delta);
158  count = count +1;
159  /* h
160  *delta
161  *outidx
162  *time */
163  else
164  firstloop = false;
165  end
166  x1 = oldx;
167  x2 = oldx;
168 
169  steps = steps +1;
170 
171  RHS1 = M*x1;
172  if ~isempty(s.f)
173  RHS1 = RHS1 + h*s.f.evaluate(x1, time, s.mu);
174  end
175  if ~isempty(s.u)
176  RHS1 = RHS1 + h*s.B.evaluate(time, s.mu)*s.u(time);
177  end
178 
179  /* Time-independent case: constant */
180  if ~fdep && ~mdep
181  x1 = u1\(l1\RHS1);
182  /* Time-dependent case: compute time-dependent components with updated time */
183  else
184  if fdep
185  A = s.A.evaluate(1, time, s.mu);
186  end
187  if mdep
188  M = s.M.evaluate(time);
189  end
190  x1 = (M - h * A)\RHS1;
191  end
192 
193  /* the same for 2 steps of half size */
194  for i=1:2
195  RHS2 = M*x2;
196  if ~isempty(s.f)
197  RHS2 = RHS2 + h/2*s.f.evaluate(x2, time, s.mu);
198  end
199  if ~isempty(s.u)
200  RHS2 = RHS2 + h/2*s.B.evaluate(time, s.mu)*s.u(time);
201  end
202 
203  /* Time-independent case: constant */
204  if ~fdep && ~mdep
205  x2 = u2\(l2\RHS2);
206  /* Time-dependent case: compute time-dependent components with updated time */
207  else
208  if fdep
209  A = s.A.evaluate(1, time, s.mu);
210  end
211  if mdep
212  M = s.M.evaluate(time);
213  end
214  x2 = (M - h/2 * A)\RHS2;
215  end
216  end
217 
218  delta = norm((x1-x2)./x2)/(2*h);
219  /* delta = norm(x1-x2)/(h); */
220  end
221  time = time + h;
222  oldx = x2;
223  /* Implicit error estimation computation - not implemented
224  * if ~isempty(oldex)
225  * ut = [];
226  * if ~isempty(s.u)
227  * ut = s.u(t(idx));
228  * end
229  * al = est.getAlpha(newx, t(idx), s.mu, ut);
230  * bet = est.getBeta(newx, t(idx), s.mu);
231  *
232  * % Explicit
233  * %newex = oldex + dt * est.evalODEPart([newx; oldex], t(idx-1), s.mu, ut);
234  * newex = oldex + dt*(bet*oldex + al);
235  *
236  * % Implicit
237  * %newex = (dt*al+oldex)/(1-dt*bet);
238  *
239  * % fun = @(y)y-dt*est.evalODEPart([oldx; y], t(idx), s.mu, ut)-oldex/dt;
240  * % opts = optimset('Display','off');
241  * % newex2 = fsolve(fun, oldex, opts);
242  * end */
243 
244  /* Only produce output at wanted timesteps */
245  while time < t(end) && time > t(outidx)
246  x(:,outidx) = x2;
247  outidx = outidx + 1;
248  end
249  end
250  l = length(t) - outidx;
251  x(:,outidx:end) = repmat(x2,1,l+1);
252  steps
253  count
254  }
272 };
273 }
274 
The base class for any KerMor detailed model.
Definition: BaseFullModel.m:18
logical RealTimeMode
Determines if the solver's StepPerformed event should be used upon solving instead of returning the f...
Definition: BaseSolver.m:85
BaseCustomSolver: Base class for all self-implemented solvers.
Name
The solver's name.
Definition: BaseSolver.m:116
epsilon
(exp(L(b-a))-1)/L * epsilon (Interval (a,b), Lipschiz constant L) is upper error bound ...
function matrix< double > x = customSolve(unused1, t, x0, unused2)
Implements the actual semi-implicit solving of the given ODE system.
dscomponents.AMassMatrix M
The mass matrix of the ODE .
Definition: BaseSolver.m:101
SemiImplicitEuler: Solves ODEs in KerMor using implicit euler for the linear part and explicit euler ...
AdaptiveSemiImplicitEuler(models.BaseFullModel model, epsilon, q, h0)