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
Model.m
Go to the documentation of this file.
1 namespace models{
2 namespace muscle{
3 
4 
5 /* (Autoinserted by mtoc++)
6  * This source code has been filtered by the mtoc++ executable,
7  * which generates code that can be processed by the doxygen documentation tool.
8  *
9  * On the other hand, it can neither be interpreted by MATLAB, nor can it be compiled with a C++ compiler.
10  * Except for the comments, the function bodies of your M-file functions are untouched.
11  * Consequently, the FILTER_SOURCE_FILES doxygen switch (default in our Doxyfile.template) will produce
12  * attached source files that are highly readable by humans.
13  *
14  * Additionally, links in the doxygen generated documentation to the source code of functions and class members refer to
15  * the correct locations in the source code browser.
16  * However, the line numbers most likely do not correspond to the line numbers in the original MATLAB source files.
17  */
18 
19 class Model
20  :public models.BaseFullModel {
34  public:
35 
36  MuscleDensity = 1.1e-3;
52  public:
53 
54  .int RandSeed = 1;
69 
70 
71  Gravity = 9.80665e-3;
82  public: /* ( Dependent ) */
83 
84  Geo;
85 
86 
87  public: /* ( Dependent ) */
88 
89  Model(conf,basedir) {
90  if nargin < 2
91  basedir = KerMor.App.DataDirectory;
92  if nargin < 1
93  conf = Debug;
94  end
95  end
96  /* Creates a new muscle model */
97  name = sprintf(" FEM Muscle model %s ",class(conf));
98  this = this@models.BaseFullModel(name);
99 
100  this.SaveTag= sprintf(" musclemodel_%s ",class(conf));
101  this.Data= data.ModelData(this,basedir);
102 
103  this.System= models.muscle.System(this);
104  /* Sets DefaultMu */
106 
107  this.TrainingParams= [1 2];
108 
109  this.T= 10; /* [ms] */
110 
111  this.dt= .01; /* [ms] */
112 
113  s = solvers.MLode15i;
114  /* Use relatively coarse precision settings. This skips fine
115  * oscillations but yields the correct long time results. */
116  s.RelTol= 1e-1;
117  s.AbsTol= 1e-1;
118  this.ODESolver= s;
119  this.System.MaxTimestep= []; /* model.dt; */
120 
121 
122  /* MOR pre-setup.
123  * If you assign a new SpaceReducer instance, dont forget to set
124  * the TargetDimensions property accordingly (is now
125  * automatically set within the configureModel base routine)
126  *s = spacereduction.PODGreedy;
127  *s.Eps = 1e-9;
128  *s.MaxSubspaceSize = 500; */
129  s = spacereduction.PODReducer;
130  s.IncludeInitialSpace= true;
131  s.Mode= " abs ";
132  this.SpaceReducer= s;
133 
134  /* Call the config-specific model configuration */
135  conf.configureModel(this);
136 
137  /* Set the config to the model, triggering geometry related
138  * pre-computations */
139  this.setConfig(conf);
140 
141  conf.configureModelFinal;
142 
143  /* % Health tests
144  * Propagate the current default param */
146 
147 /* fprintf('Running Jacobian health check..');
148  * res = this.System.f.test_Jacobian;
149  * fprintf('Done. Success=%d\n',res);
150  * chk = this.Config.FEM.test_JacobiansDefaultGeo;
151  * % chk = chk && this.Config.FEM.test_QuadraticBasisFun;
152  * chk = chk && this.Config.PressureFEM.test_JacobiansDefaultGeo;
153  * if ~chk
154  * error('Health tests failed!');
155  * end */
156  }
157 
158 
159  function [doublet , matrix<double>y ] = simulateAndPlot(withResForce,varargin) {
160  if nargin < 2
161  withResForce = true;
162  end
163  [t,y] = this.simulate(varargin[:]);
164  xargs = [];
165  if (withResForce)
166  [df,nf] = this.getResidualForces(t,y);
167  xargs = [" NF ",nf," DF ",df];
168  end
169  this.plot(t,y,xargs[:]);
170  }
171 
172 
173  function [doublet , colvec<double>x , time , cache ] = computeTrajectory(colvec<double> mu,integer inputidx) {
174  this.Config.prepareSimulation(mu, inputidx);
175  [t, x, time, cache] = computeTrajectory@models.BaseFullModel(this, mu, inputidx);
176  f = this.System.f;
177  fprintf(" Finished after %gs (fevals:%d, Jacobians: %d)\n ",time,f.nfevals,f.nJevals);
178  }
190  function doublet = getConfigTable(colvec<double> mu) {
191  if nargin < 2
192  mu = this.DefaultMu;
193  end
194  f = this.System.f;
195  t = PrintTable(" Configuration of Model %s ",this.Name);
196  t.HasHeader= true;
197  t.addRow(" \rho_0 ", " c_{10} [MPa] "," c_{01} [MPa] "," b_1 [MPa] "," d_1 [-] "," P_{max} [MPa] "," \lambda_f^{opt} ");
198  t.addRow(this.MuscleDensity, mu(9),mu(10),mu(5),mu(6),mu(13),mu(14));
199  t.Format= " tex ";
200  }
201 
202 
204  if nargin < 3
205  pm = PlotManager(false,2,2);
206  pm.LeaveOpen= true;
207  if nargin < 2
208  mu = this.DefaultMu;
209  end
210  end
211  sys = this.System;
212  f = sys.f;
213  sys.prepareSimulation(mu,this.DefaultInput);
214  this.Config.setForceLengthFun(f);
215 
216  lambda = .2:.005:2;
217 
218  /* % Plain Force-length function */
219  fl = f.ForceLengthFun(lambda);
220  h = pm.nextPlot(" force_length_plain "," Direct force-length curve of muscle/sarcomere ",...
221  sprintf(" \\lambda [-], fl_p1=%g ",mu(14)),...
222  " force-length relation [-] ");
223  plot(h,lambda,fl," r ");
224 
225  /* % Effective force-length function for muscle tissue
226  * effective signal from active part */
227  fl_eff = (mu(13)./lambda) .* fl;
228  /* Passive markert laws */
229  aniso_passive_muscle = f.AnisoPassiveMuscle(lambda);
230 
231  /* Find a suitable position to stop plotting (otherwise the
232  * passive part will steal the show) */
233  pos = find(aniso_passive_muscle > max(fl_eff)*1.4,1," first ");
234  if ~isempty(pos)
235  lambda = lambda(1:pos);
236  fl_eff = fl_eff(1:pos);
237  aniso_passive_muscle = aniso_passive_muscle(1:pos);
238  end
239 
240  h = pm.nextPlot(" force_length_eff ",...
241  " Effective force-length curve of muscle material ",...
242  " \lambda [-] "," pressure [MPa] ");
243  plot(h,lambda,fl_eff," r ",lambda,aniso_passive_muscle," g ",lambda,fl_eff+aniso_passive_muscle," b ");
244  legend(h," Active "," Passive "," Total "," Location "," NorthWest ");
245 
246 /* %% Effective force-length function derivative for muscle tissue
247  * dfl = (mu(13)./lambda) .* f.ForceLengthFunDeriv(lambda);
248  * dmarkertf = (lambda>=1).*(b1./lambda.^3).*((d1-2)*lambda.^d1 + 2);
249  * h = pm.nextPlot('force_length_eff_deriv',...
250  * 'Effective force-length curve derivative of muscle material',...
251  * '\lambda','deriv [MPa/ms]');
252  * plot(h,lambda,dfl,'r',lambda,dmarkertf,'g',lambda,dfl + dmarkertf,'b'); */
253 
254 /* %% Cross fibre stuff
255  * if this.System.UseCrossFibreStiffness
256  * error('fixme');
257  * markertf = max(0,(f.b1cf./lambda.^2).*(lambda.^f.d1cf-1));
258  * h = pm.nextPlot('force_length_xfibre',sprintf('Force-Length curve in cross-fibre direction for model %s',this.Name),'\lambda [-]','pressure [MPa]');
259  * plot(h,lambda,markertf,'r');
260  * axis(h,[0 2 0 150]);
261  * legend(h,'Passive cross-fibre pressure','Location','NorthWest');
262  *
263  * dmarkertf = (lambda >= 1).*(f.b1cf./lambda.^3).*((f.d1cf-2)*lambda.^f.d1cf + 2);
264  * h = pm.nextPlot('force_length_xfibre_deriv',sprintf('Derivative of Force-Length curve in cross-fibre direction for model %s',this.Name),'\lambda [-]','pressure [MPa]');
265  * plot(h,lambda,dmarkertf,'r');
266  * end */
267 
268  /* % Passive force-length function for 100% tendon tissue
269  * Passive markert law */
270  if sys.HasTendons
271  aniso_passive_tendon = f.AnisoPassiveTendon(lambda);
272  h = pm.nextPlot(" force_length_tendon ",...
273  " Effective force-length curve of tendon material (=passive) ",...
274  " \lambda [-] "," pressure [MPa] ");
275  plot(h,lambda,aniso_passive_tendon," g ");
276 
277  /* % Effective force-length surface for muscle-tendon tissue
278  * Sampled ratios */
279  tmr = 0:.03:1;
280  /* tmrlog = [0 logspace(-4,0,length(tmr)-1)]; */
281  tmrlog = tmr;
282 
283  /* % Passive part */
284  [LAM,TMR] = meshgrid(lambda,tmr);
285  passive = repmat(aniso_passive_muscle,length(tmr),1) ...
286  + tmrlog^t*(aniso_passive_tendon-aniso_passive_muscle);
287 
288  /* % Active part */
289  FL = (1-tmr)^t*fl_eff;
290 
291  /* % Plot dat stuff! */
292  h = pm.nextPlot(" force_length_muscle_tendon ",...
293  " Effective force-length curve between muscle/tendon material ",...
294  " \lambda [-] "," muscle/tendon ratio [m=0,t=1] ");
295  surfc(LAM,TMR,passive+FL," Parent ",h," EdgeColor "," interp ");
296  zlabel(" pressure [MPa] ");
297  zlim([0, 3*max(fl_eff(:))]);
298  end
299 
300  if nargin < 2
301  pm.done;
302  end
303  }
304 
305 
307  if nargin < 2
308  mu = this.DefaultMu;
309  end
310 /* pm = PlotManager(false,1,2); */
311  pm = PlotManager;
312  pm.LeaveOpen= true;
313  f = this.System.f;
314 
315  /* Simply use muscle parameter values */
316  b1 = mu(1);
317  d1 = mu(2);
318  warning(" Using muscle parameters only (ignoring tendon) ");
319 
320  [lambda, alpha] = meshgrid(.02:.02:1.5,0:.01:1);
321 
322  fl = f.ForceLengthFun(lambda/mu(14));
323  active = mu(13)./lambda.*fl.*alpha;/* + 1*max(0,(lambda-1)).*alpha; */
324 
325  passive = max(0,(b1./lambda.^2).*(lambda.^d1-1));
326 
327  h = pm.nextPlot(" aniso_pressure ",sprintf(" Pressure in fibre direction for model %s ",this.Name)," Stretch \lambda "," Activation \alpha ");
328  surf(h,lambda,alpha,active+passive," EdgeColor "," k "," FaceColor "," interp ");
329 
330  pm.done;
331  }
332 
333 
334  function plotActivation() {
335  pm = PlotManager;
336  pm.LeaveOpen= true;
337  f = this.System.f;
338 
339  h = pm.nextPlot(" activation ",sprintf(" Activation curve for model %s ",this.Name)," time [ms] "," alpha [-] ");
340  plot(h,this.Times,f.alpha(this.scaledTimes)," r ");
341  pm.done;
342  }
343 
344 
345  function varargout = plotGeometrySetup(varargin) {
346  if isempty(this.System.mu)
348  end
349  if ~isempty(varargin) && isa(varargin[1]," PlotManager ")
350  varargin = [[" PM "] varargin];
351  end
352  x0 = this.System.getX0(this.System.mu);
353  [~, nf] = this.getResidualForces(0, x0);
354  if ~isempty(nf)
355  varargin(end+1:end+2) = [" NF ",nf];
356  end
357  varargin(end+1:end+2) = [" Velo ",true];
358  /* Plot without default args (time-plotting might want to
359  * suppress fibres for speed, but we want them here) */
360  old = this.Plotter.DefaultArgs;
361  this.Plotter.DefaultArgs= [];
362  [varargout[1:nargout]] = this.plot(0,x0,varargin[:]);
363  this.Plotter.DefaultArgs= old;
364  }
365 
366 
368  this.Config.plotGeometryInfo(varargin[:]);
369  }
370 
371 
372  function [residuals_dirichlet , residuals_neumann ] = getResidualForces(double t,uvw) {
373  sys = this.System;
374  num_bc = length(sys.idx_u_bc_glob)+length(sys.idx_expl_v_bc_glob);
375  residuals_dirichlet = zeros(num_bc,length(t));
376  residuals_neumann = zeros(length(sys.idx_neumann_bc_glob),length(t));
377  for k=1:length(t)
378  dy = sys.f.evaluate(uvw(:,k),t(k));
379  if ~isempty(residuals_neumann)
380  residuals_neumann(:,k) = dy(sys.idx_neumann_bc_dof);
381  end
382  residuals_dirichlet(:,k) = sys.f.LastBCResiduals;
383  end
384  }
385 
386 
387  function colvec<integer>idx = getFaceDofsGlobal(integer elem,rowvec<integer> faces,rowvec<integer> dim) {
388  if nargin < 4
389  dim = 1:3;
390  end
391  geo = this.Config.FEM.Geometry;
392  idxXYZ = false(3,geo.NumNodes);
393  for k=1:length(faces)
394  idxXYZ(dim,geo.Elements(elem,geo.MasterFaces(faces(k),:))) = true;
395  end
396  idx = find(idxXYZ(:));
397  }
414  if nargin < 4
415  dim = 1:3;
416  end
417  geo = this.Config.FEM.Geometry;
418  idx_face = false(size(this.System.bool_u_bc_nodes));
419  idx_face(dim,geo.Elements(elem,geo.MasterFaces(face,:))) = true;
420  fidx = find(this.System.bool_u_bc_nodes & idx_face);
421  [~, idx] = intersect(this.System.idx_u_bc_glob, fidx);
422  }
439  if nargin < 4
440  dim = 1:3;
441  end
442  geo = this.Config.FEM.Geometry;
443  idx_face = false(size(this.System.bool_u_bc_nodes));
444  idx_face(dim,geo.Elements(elem,geo.MasterFaces(face,:))) = true;
445  fidx = find(this.System.bool_expl_v_bc_nodes & idx_face);
446  /* Include the offset to the indices for velocity dofs */
447  fidx = fidx + geo.NumNodes*3;
448  [~, idx] = intersect(this.System.idx_v_bc_glob, fidx);
449  /* Also include the offset of velocity components within the
450  * dirichlet force vector */
451  idx = idx + length(this.System.val_u_bc);
452  }
468  function setConfig(value) {
469  if ~isa(value, " models.muscle.AMuscleConfig ")
470  error(" Config must be a models.muscle.AMuscleConfig instance ");
471  end
472  this.Config= value;
473  this.System.configUpdated;
474  this.Plotter= models.muscle.MusclePlotter(this.System);
475  }
476 
477 
478  function setGaussIntegrationRule(value) {
479  mc = this.Config;
480  mc.FEM.GaussPointRule= value;
481  mc.PressureFEM.GaussPointRule= value;
482  this.setConfig(mc);
483  s = this.System;
484  mu = s.mu;
485  if isempty(mu)
486  mu = this.DefaultMu;
487  end
488  in = s.inputidx;
489  if isempty(in)
490  in = this.DefaultInput;
491  end
492  s.prepareSimulation(mu,in);
493  }
504  function varargout = plot(varargin) {
505  [varargout[1:nargout]] = this.Plotter.plot(varargin[:]);
506  }
507 
508 
509 
510 #if 0 //mtoc++: 'get.Geo'
511 function value = Geo() {
512  value = this.Config.Geometry;
513  }
514 
515 #endif
516 
517 
518 
519  public: /* ( Static ) */ /* ( Dependent ) */
520 
521  static function res = test_ModelVersions() {
522  res = true;
523  try
524  m = models.muscle.Model(models.muscle.examples.Debug);
525  mu = m.getRandomParam;
526  [t,y] = m.simulate(mu);
527  m.System.UseDirectMassInversion= true;
528  [t,y] = m.simulate(mu);
529 
530  /* Version with "constant" fibre activation forces */
531  m = models.muscle.Model(models.muscle.examples.Debug(2));
532  [t,y] = m.simulate(mu);
533  m.System.UseDirectMassInversion= true;
534  [t,y] = m.simulate(mu);
535 
536  /* Version with "neurophysiological" fibre activation forces */
537  m = models.muscle.Model(models.muscle.examples.Debug(3));
538  [t,y] = m.simulate(mu);
539  m.System.UseDirectMassInversion= true;
540  [t,y] = m.simulate(mu);
541  m.System.UseDirectMassInversion= false;
542 
543  /* "Disable" viscosity */
544  m.DefaultMu(1) = 0;
545  [t,y] = m.simulate(mu);
546  m.System.UseDirectMassInversion= true;
547  [t,y] = m.simulate(mu);
548  catch ME
549  ME.getReport(" extended ");
550  res = false;
551  end
552  }
553 
554 
555  static function res = test_JacobianApproxGaussRules() {
556  m = models.muscle.Model(models.muscle.examples.Debug(2));
557  m.simulate;
558  f = m.System.f;
559  m.dt= .2;
560  m.T= 1;
561  res = f.test_Jacobian;
562  m.setGaussIntegrationRule(4);
563  res = res && f.test_Jacobian;
564  m.setGaussIntegrationRule(5);
565  res = res && f.test_Jacobian;
566  }
575  protected: /* ( Static ) */ /* ( Dependent ) */
576 
577  static function this = loadobj() {
578  if ~isa(this, " models.muscle.Model ")
579  sobj = this;
580  this = models.muscle.Model;
581  this.RandSeed= sobj.RandSeed;
582  this.Config= sobj.Config;
583  this = loadobj@models.BaseFullModel(this, sobj);
584  else
585  this = loadobj@models.BaseFullModel(this);
586  end
587  }
588 
595 };
596 }
597 }
598 
char Name
The name of the Model.
Definition: BaseModel.m:117
bool_u_bc_nodes
% Position dirichlet fields Boundary conditions: 3 times numnodes logical matrix telling which degree...
Definition: System.m:98
MuscleFibreSystem: The global dynamical system used within the MuscleFibreModel.
Definition: System.m:19
static function res = test_ModelVersions()
Definition: Model.m:521
function setConfig(value)
Definition: Model.m:468
Gravity
[mm/ms²]
Definition: Model.m:71
The base class for any KerMor detailed model.
Definition: BaseFullModel.m:18
double dt
The desired time-stepsize for simulations.
Definition: BaseModel.m:291
models.BaseFirstOrderSystem System
The actual dynamical system used in the model.
Definition: BaseModel.m:102
function varargout = plotGeometrySetup(varargin)
Definition: Model.m:345
Times
Evaluation points of the model.
Definition: BaseModel.m:206
function prepareSimulation(colvec< double > mu)
A method that allows parameter-dependent computations to be performed before a simulation using this ...
Definition: ACoreFun.m:380
Model(conf, basedir)
Definition: Model.m:89
function plotAnisotropicPressure(colvec< double > mu)
Definition: Model.m:306
An integer value.
PlotManager: Small class that allows the same plots generated by some script to be either organized a...
Definition: PlotManager.m:17
* fl(l)
function idx = getPositionDirichletBCFaceIdx(integer elem,integer face,rowvec< integer > dim)
Returns the positions of dofs of a specified face within the boundary conditions residual vector...
Definition: Model.m:413
function setGaussIntegrationRule(value)
Sets the gauss integration rule for the model.
Definition: Model.m:478
int RandSeed
Seed that can be used by random number generator instances in order to enable result reproduction...
Definition: Model.m:54
logical LeaveOpen
Flag indicating if the plots should be left open once the PlotManager is deleted (as variable) ...
Definition: PlotManager.m:213
function varargout = plot(varargin)
Definition: Model.m:504
function idx = getVelocityDirichletBCFaceIdx(integer elem,integer face,rowvec< integer > dim)
Returns the positions of dofs of a specified face within the boundary conditions residual vector...
Definition: Model.m:438
A variable number of input arguments.
function plotForceLengthCurve(colvec< double > mu, pm)
Definition: Model.m:203
function [ residuals_dirichlet , residuals_neumann ] = getResidualForces(double t, uvw)
Definition: Model.m:372
Plotter
The plotter class for visualization.
Definition: Model.m:44
solvers.BaseSolver ODESolver
The solver to use for the ODE. Must be an instance of any solvers.BaseSolver subclass.
Definition: BaseModel.m:315
mu
The current parameter for simulations, [] is none used.
integer DefaultInput
The default input to use if none is given.
Definition: BaseModel.m:189
rowvec< integer > TrainingParams
The indices of the model parameters to use for training data generation.
function [ double t , colvec< double > x , time , cache ] = computeTrajectory(colvec< double > mu,integer inputidx)
Allows to also call prepareSimulation for any quantities set by the AMuscleConfig class...
Definition: Model.m:173
double T
The final timestep up to which to simulate.
Definition: BaseModel.m:271
data.ModelData Data
The full model's data container. Defaults to an empty container.
MuscleDensity
g/mm³
Definition: Model.m:36
static function this = loadobj()
Definition: Model.m:577
spacereduction.BaseSpaceReducer SpaceReducer
The reduction algorithm for subspaces.
PrintTable: Class that allows table-like output spaced by tabs for multiple rows. ...
Definition: PrintTable.m:17
idx_v_bc_glob
This set comprises both the explicit velocity conditions and the implicit zero velocity conditions th...
Definition: System.m:154
bool_expl_v_bc_nodes
% Velocity dirichlet fields This set comprises the explicitly/directly set velocity boundary conditio...
Definition: System.m:128
ModelData(varargin)
Creates a new container for large full model data.
Definition: ModelData.m:180
function double t = getConfigTable(colvec< double > mu)
Definition: Model.m:190
colvec< double > DefaultMu
The default parameter value if none is given.
Definition: BaseModel.m:355
dscomponents.ACoreFun f
The core f function from the dynamical system.
function x_xdot_c0 = getX0(colvec< double > mu)
Compiles the global x0 vector of the global dof vector.
function colvec< integer > idx = getFaceDofsGlobal(integer elem,rowvec< integer > faces,rowvec< integer > dim)
Returns the indices in the global uvw vector (including dirichlet values) of the given faces in the g...
Definition: Model.m:387
System(models.BaseFullModel model)
Call superclass constructor.
Definition: System.m:439
Global configuration class for all KerMor run-time settings.
Definition: KerMor.m:17
function initDefaultParameter()
Reads the default values of the System's ModelParam list and initializes the BaseModel.DefaultMu with it.
Definition: BaseModel.m:459
static function res = test_JacobianApproxGaussRules()
Tests the precision of the analytical jacobian computation using different gauss integration rules...
Definition: Model.m:555
function [ double t , matrix< double > y ] = simulateAndPlot(withResForce, varargin)
Definition: Model.m:159
static function KerMor theinstance = App()
The singleton KerMor instance.
Definition: KerMor.m:910
double MaxTimestep
The maximum timestep allowed for any ODE solvers.
function prepareSimulation(colvec< double > mu,integer inputidx)
Check for viscosity setting.
Definition: System.m:664
function plotActivation()
Definition: Model.m:334
function plotGeometryInfo(varargin)
Definition: Model.m:367
function [ rowvec< double > t , matrix< double > y , double sec , x ] = simulate(colvec< double > mu,integer inputidx)
Simulates the system and produces the system's output.
Definition: BaseModel.m:477
char SaveTag
A custom tag that can be used as a prefix to files for corresponding model identification.
A variable number of output arguments.
Model: Model for a FEM-discretized muscle model.
Definition: Model.m:19
function configUpdated()
Definition: System.m:585