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
MusclePlotter.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 
20  :public handle {
33  public:
34 
35  GeoView = "[46 30]";
36 
37  DefaultArgs = {""};
38 
39 
40  public:
41 
43 
45 
46 
47  protected:
48 
50 
51 
52  public:
53 
55  this.System= sys;
56  this.Config= sys.Model.Config;
57  this.plotdata= this.initPlotData;
58  }
59 
60 
61  function [pm , h ] = plot(double t,y_dofs,varargin) {
62  opts = this.parsePlotArgs(varargin);
63 
64  mc = this.Config;
65 
66  if isempty(opts.PM)
67  if ~isempty(mc.Pool) && opts.Pool
68  pm = PlotManager(false,2,1);
69  else
70  pm = PlotManager;
71  end
72  pm.LeaveOpen= true;
73  else
74  pm = opts.PM;
75  end
76 
77  [pd, t] = this.updatePlotData(this.plotdata, opts, t, y_dofs);
78  this.plotdata= pd;
79 
80  if opts.Vid
81  [p,n,e] = fileparts(opts.Vid);
82  if ~isempty(p) && exist(p," file ") ~= 7
83  error(" Directory %s not found ",p);
84  end
85  if isempty(p)
86  if isa(mc," models.muscle.AExperimentModelConfig ")
87  p = mc.OutputDir;
88  else
89  p = pwd;
90  end
91  end
92  if isempty(n)
93  n = " output ";
94  end
95  if isempty(e)
96  e = " .avi ";
97  end
98  avifile = fullfile(p,[n e]);
99  vw = VideoWriter(avifile);
100  vw.FrameRate= 25;
101  vw.open;
102  end
103 
104  /* % Loop over time */
105  if ~isempty(mc.Pool) && opts.Pool
106  hf = pm.nextPlot(" force "," Activation force "," t [ms] "," alpha ");
107  axis(hf,[0 t(end) 0 1]);
108  hold(hf," on ");
109  end
110 
111  h = pm.nextPlot(" geo ",sprintf(" Deformation at t=%g ",t(end))," x [mm] "," y [mm] ");
112  zlabel(h," z [mm] ");
113  axis(h, pd.geo_plotbox);
114  daspect([1 1 1]);
115  view(h, this.GeoView);
116  hold(h," on ");
117 
118  for ts = 1:length(t)
119  /* Quit if figure has been closed */
120  if ~ishandle(h)
121  if opts.Vid
122  vw.close;
123  end
124  break;
125  end
126  this.plotGeometry(h, t(ts), pd.yfull(:,ts), ts, opts);
127 
128  if ~isempty(mc.Pool) && opts.Pool
129  times = t(1:ts);
130  alpha = mc.Pool.getActivation(times);
131  walpha = mc.FibreTypeWeights(1,:,1) * alpha;
132  cla(hf);
133  plot(hf,times,alpha);
134  plot(hf,times,walpha," LineWidth ",2);
135  end
136 
137 /* % Quit if figure has been closed (extra check - runtime
138  * % thing)
139  * if ~ishandle(h)
140  * if opts.Vid
141  * vw.close;
142  * end
143  * break;
144  * end */
145 
146  if ~isempty(opts.Vid) && ishandle(h)
147  vw.writeVideo(getframe(gcf));
148  else
149  pause(opts.Pause);
150  end
151  end
152 
153  if opts.Vid
154  vw.close;
155  end
156 
157  if isempty(opts.PM)
158  pm.done;
159  end
160  }
161 
162 
163  protected:
164 
165  function plotGeometry(h,double t,y_dofs,ts,opts) {
166  casecap = " Deformation ";
167  if opts.Stretch
168  casecap = " Lambda-stretches ";
169  end
170  title(h,sprintf(" %s at t=%g ",casecap,t));
171 
172  pd = this.plotdata;
173  sys = this.System;
174  nelem = length(opts.Elems);
175 
176  u = reshape(y_dofs(1:pd.vstart-1),3,[]);
177  v = reshape(y_dofs(pd.vstart:pd.pstart-1),3,[]);
178  cla(h);
179 
180  geo = this.Config.FEM.Geometry;
181  if opts.Skel
182  e = pd.e;
183  plot3(h,u(1,pd.no_bc),u(2,pd.no_bc),u(3,pd.no_bc)," r. "," MarkerSize ",14);
184  for k=1:size(e,1)
185  plot3(h,u(1,[e(k,1) e(k,2)]),u(2,[e(k,1) e(k,2)]),u(3,[e(k,1) e(k,2)])," r ");
186  end
187  elseif ~opts.Stretch
188  p = patch(" Faces ",geo.PatchFaces," Vertices ",u^t,...
189  " Parent ",h," FaceAlpha ",.3);
190  if sys.HasTendons
191  set(p," FaceVertexCData ",pd.vertexcol," FaceColor ",...
192  " interp "," FaceAlpha ",.5," EdgeColor "," interp ");
193  else
194  set(p," EdgeColor ",.8*pd.musclecol," FaceColor ",pd.musclecol);
195  end
196  end
197 
198  /* Velocities */
199  if opts.Velo
200  quiver3(h,u(1,:),u(2,:),u(3,:),v(1,:),v(2,:),v(3,:),1," b ", " MarkerSize ",14);
201  end
202 
203  /* % Dirichlet conditions
204  * Displacement */
205  u3dir = u(:,pd.bc_dir_3pos_applies);
206  plot3(h,u3dir(1,:),u3dir(2,:),u3dir(3,:)," . "," MarkerSize ",20," Color ",[0 0 0]);
207  u2dir = u(:,pd.bc_dir_2pos_applies);
208  plot3(h,u2dir(1,:),u2dir(2,:),u2dir(3,:)," . "," MarkerSize ",20," Color ",[.5 .5 .5]);
209  u1dir = u(:,pd.bc_dir_1pos_applies);
210  plot3(h,u1dir(1,:),u1dir(2,:),u1dir(3,:)," . "," MarkerSize ",20," Color ",[.7 .7 .7]);
211 
212  /* Velocity */
213  uvdir = u(:,pd.bool_expl_v_bc_nodes_applies);
214  plot3(h,uvdir(1,:),uvdir(2,:),uvdir(3,:)," g. "," MarkerSize ",20);
215 
216  /* % Dirichlet Forces */
217  if ~isempty(pd.DF)
218  residuals = pd.residuals;
219  have_residuals = pd.have_residuals;
220  udir = u(:,have_residuals);
221 /* residuals(pd.residuals_pos) = pd.DF(pd.sortidx,ts)/pd.maxdfval; */
222  residuals(pd.residuals_pos) = pd.DF(:,ts)/pd.maxdfval;
223  quiver3(h,udir(1,:),udir(2,:),udir(3,:),...
224  residuals(1,have_residuals),residuals(2,have_residuals),...
225  residuals(3,have_residuals),1," k ", " MarkerSize ",14);
226  end
227 
228  /* % Neumann condition forces */
229  if opts.Forces
230  /* Plot force vectors at nodes
231  * uforce = u(:,pd.forces_apply);
232  * quiver3(h,uforce(1,:),uforce(2,:),uforce(3,:),...
233  * pd.forces(1,:),pd.forces(2,:),pd.forces(3,:),0,'Color',[.8 .8 1]);
234  * Plot force vectors at face centers */
235  for k=1:pd.numfaceswithforce
236  masterfacenodeidx = geo.MasterFaces(pd.force_elem_face_idx(2,k),:);
237  facenodeidx = geo.Elements(pd.force_elem_face_idx(1,k),masterfacenodeidx);
238 
239  facecenter = mean(u(:,facenodeidx),2);
240  mf = pd.meanforces(:,k)*this.System.mu(3);
241  quiver3(h,facecenter(1),facecenter(2),facecenter(3),...
242  mf(1),mf(2),mf(3),0," LineWidth ",2," Color "," b "," MaxHeadSize ",1);
243 
244  if ~isempty(pd.NF)
245  pd.residual_neumann_forces(sys.idx_neumann_bc_glob) = pd.NF(:,ts);
246  meanforce = mean(pd.residual_neumann_forces(:,facenodeidx),2);
247  quiver3(h,facecenter(1),facecenter(2),facecenter(3),...
248  meanforce(1),meanforce(2),meanforce(3),0," LineWidth ",2," Color "," k "," MaxHeadSize ",1);
249  end
250  end
251  end
252 
253  /* % Pressure */
254  if opts.Pressure
255  p = y_dofs(pd.pstart:sys.num_uvp_glob);
256  pn = sys.idx_p_to_u_nodes;
257  pneg = p<0;
258  /* Negative pressures */
259  if any(pneg)
260  scatter3(h,u(1,pn(pneg)),u(2,pn(pneg)),u(3,pn(pneg)),...
261  -p(pneg)*10+1,[188 188 255]/255);/*
262  end
263  * Positive pressures */
264 
265  if any(~pneg)
266  scatter3(h,u(1,pn(~pneg)),u(2,pn(~pneg)),u(3,pn(~pneg)),...
267  p(~pneg)*10+1,[255 188 188]/255); /* [244 149 25]/255 */
268 
269  end
270  end
271 
272  /* % a0 fibres & gp values */
273  fibres = sys.HasFibres && opts.Fibres;
274  doI1 = any(opts.Invariants == 1);
275  doLam = opts.Lambdas;
276  doMR = opts.MR;
277  doTMR = opts.MTRatio;
278  doStr = opts.Stretch;
279  if fibres || ~isempty(opts.Invariants) || doLam || doMR || doTMR || doStr
280  for elemidx = 1:nelem
281  m = opts.Elems(elemidx);
282  u = y_dofs(1:pd.vstart-1);
283  u = u(sys.idx_u_elems_local(:,:,m));
284  gps = u*pd.Ngp;
285 
286  if doStr
287  scatter3(h,gps(1,:),gps(2,:),gps(3,:),1,pd.stretchcol(:,:,elemidx,ts)" , "." , "SizeData^t,30);
288  else
289  if fibres
290  anull = u*sys.dNa0(:,:,m);
291  quiver3(gps(1,:),gps(2,:),gps(3,:),anull(1,:),anull(2,:),anull(3,:),.5," . "," Color "," w ");
292  end
293 
294  /* % tendon ratio */
295  if ~isempty(pd.gpcol)
296  scatter3(h,gps(1,:),gps(2,:),gps(3,:),1,pd.gpcol(:,:,m)," . "," SizeData ",30);
297  end
298 
299  /* % Invariants */
300  if doI1
301  values = sprintfc(" I_1=%3.3g ",pd.I1(:,elemidx,ts));
302  text(gps(1,:),gps(2,:),gps(3,:),values," Parent ",h)
303  end
304  /* % Lambdas */
305  if doLam
306  /* values = sprintfc('\\lambda=%3.3g',pd.lambdas(:,m,ts)); */
307  values = sprintfc(" %3.4g ",pd.lambdas(:,elemidx,ts));
308  text(gps(1,:),gps(2,:),gps(3,:),values," Parent ",h)
309  end
310  /* % Mooney-Rivlin tensors */
311  if doMR
312  values = cellfun(@(v)sprintf(" %g ",diag(v)), pd.MR(:,elemidx,ts)," UniformOutput ",false);
313  text(gps(1,:),gps(2,:),gps(3,:),values," Parent ",h)
314  end
315 
316  /* % Tendon-Muscle ratio */
317  if doTMR
318  values = sprintfc(" %3.4g ",sys.MuscleTendonRatioGP(:,m,ts));
319  /* values = sprintfc('%3.4g',diags{:}); */
320  text(gps(1,:),gps(2,:),gps(3,:),values," Parent ",h)
321  end
322  end
323  end
324  if doStr
325  colormap(pd.stretchcmap);
326  colorbar(" YTickLabel ",pd.stretchcmaplbl);
327  end
328  end
329  }
330 
331 
332  function [pd , doublet , matrix<double>y ] = updatePlotData(pd,opts,double t,matrix<double> y) {
333  mc = this.Config;
334  sys = this.System;
335  dfem = mc.FEM;
336  geo = dfem.Geometry;
337 
338  pd.DF= opts.DF;
339  pd.NF= opts.NF;
340  /* % "Speedup" factor for faster plots */
341  if ~isempty(opts.F)
342  t = t(1:opts.F:end);
343  y = y(:,1:opts.F:end);
344  if ~isempty(pd.DF)
345  pd.DF= pd.DF(:,1:opts.F:end);
346  end
347  if ~isempty(pd.NF)
348  pd.NF= pd.NF(:,1:opts.F:end);
349  end
350  end
351 
352  /* % Re-add the dirichlet nodes for geometry plotting */
353  pd.yfull= sys.includeDirichletValues(t, y);
354  pd.geo_plotbox= this.getPlotBox(pd.yfull);
355 
356  /* % Dirichlet plotting */
357  if ~isempty(opts.DF)
358  pd.maxdfval= max(abs(opts.DF(:)))/10;
359  end
360 
361  /* % Forces plotting */
362  if opts.Forces
363  /* Get forces on each node in x,y,z directions
364  * This is where the connection between plane index and
365  * x,y,z coordinate is "restored" */
366  forces = zeros(size(sys.bool_u_bc_nodes));
367  forces(sys.idx_neumann_bc_glob) = sys.bc_neum_forces_val;
368 
369  /* Forces at face centers */
370  force_elem_face_idx = geo.Faces(:,sys.FacesWithForce);
371  pd.numfaceswithforce= size(force_elem_face_idx,2);
372  meanforces = zeros(3,pd.numfaceswithforce);
373  for k=1:pd.numfaceswithforce
374  masterfacenodeidx = geo.MasterFaces(force_elem_face_idx(2,k),:);
375  facenodeidx = geo.Elements(force_elem_face_idx(1,k),masterfacenodeidx);
376  meanforces(:,k) = mean(forces(:,facenodeidx),2);
377  end
378  pd.meanforces= meanforces;
379  pd.force_elem_face_idx= force_elem_face_idx;
380 
381  /* Also save forces at x,y,z nodes for plotting */
382  pd.forces_apply= sum(abs(forces),1) ~= 0;
383  pd.forces= forces(:,pd.forces_apply);
384 
385  if ~isempty(opts.NF)
386  pd.residual_neumann_forces= zeros(size(sys.bool_u_bc_nodes));
387  end
388  end
389 
390  /* % Skeleton plotting */
391  if ~opts.Skel
392  /* light('Position',[1 1 1],'Style','infinite','Parent',h); */
393  pd.musclecol= [0.854688, 0.201563, 0.217188];
394  end
395 
396  /* % Show invariants or lambda stretch values */
397  if ~isempty(opts.Invariants) || opts.Lambdas || opts.MR || opts.Stretch
398  nt = length(t);
399  nelem = length(opts.Elems);
400  doI1 = any(opts.Invariants == 1);
401  doLam = opts.Lambdas;
402  doMR = opts.MR;
403  doStr = opts.Stretch;
404  if doI1 || doMR
405  pd.I1= zeros(dfem.GaussPointsPerElem,nelem,nt);
406  end
407  if doLam || doStr
408  pd.lambdas= zeros(dfem.GaussPointsPerElem,nelem,nt);
409  if doStr
410  pd.stretchcol= zeros(3,dfem.GaussPointsPerElem,nelem,nt);
411  end
412  end
413  if doMR
414  pd.MR= cell(dfem.GaussPointsPerElem,nelem,nt);
415  c10 = sys.MuscleTendonParamc10;
416  c01 = sys.MuscleTendonParamc01;
417  end
418  num_gp = dfem.GaussPointsPerElem;
419  for elemidx = 1:nelem
420  m = opts.Elems(elemidx);
421  for gp = 1:num_gp
422  pos = 3*(gp-1)+1:3*gp;
423  dtn = dfem.transgrad(:,pos,m);
424  elemidx_u = sys.idx_u_elems_local(:,:,m);
425  for ts = 1:nt
426  /* Deformation gradient */
427  yts = pd.yfull(:,ts) ;
428  F = yts(elemidx_u) * dtn;
429  C = F^t*F;
430  if doI1 || doMR
431  pd.I1(gp,elemidx,ts) = C(1,1)+C(2,2)+C(3,3);
432  end
433  if doLam || doStr
434  fibres = sys.a0Base(:,:,(m-1)*num_gp + gp);
435  pd.lambdas(gp,elemidx,ts) = norm(F*fibres(:,1));
436  end
437  if doMR
438  pd.MR[gp,elemidx,ts] = sys.MooneyRivlinICConst(gp,m)*eye(3) ...
439  + 2*(c10(gp,m) + pd.I1(gp,elemidx,ts)*c01(gp,m))*F ...
440  - 2*c01(gp,m)*F*C;
441  end
442  end
443  end
444  end
445  if doStr
446  Mlam = max(pd.lambdas(:));
447  mlam = min(pd.lambdas(:));
448  center = (1-mlam)/(Mlam-mlam);
449  if abs(Mlam-mlam) < 1e-8
450  /* Green for lambda=1 everywhere */
451  pd.stretchcol(2,:,:,:) = 1;
452  else
453  colfun = @(x)[(x>center).*((x-center)/(1-center))
454  (x<center).*x/center + (x>=center).*(1-(x-center)/(1-center));
455  (x<center).*(1-x/center);];
456  for ts = 1:nt
457  for elemidx = 1:nelem
458  normlam = (pd.lambdas(:,elemidx,ts)-mlam) / (Mlam-mlam);
459  pd.stretchcol(:,:,elemidx,ts) = colfun(normlam^t);
460  end
461  end
462  end
463  pd.stretchcmap= colfun(linspace(0,1,125))^t;
464  pd.stretchcmaplbl= sprintfc(" %3.3g ",linspace(mlam,Mlam,12));
465  end
466  end
467  }
468 
469 
470  function opts = parsePlotArgs(args) {
471 
472  i.KeepUnmatched= true;
473  i.addParamValue('Vid',[],@(v)~isempty(v));
474  i.addParamValue('Forces',false,@(v)islogical(v));
475  i.addParamValue('Velo',false,@(v)islogical(v));
476  i.addParamValue('Pressure',false,@(v)islogical(v));
477  i.addParamValue('Fibres',true,@(v)islogical(v));
478  i.addParamValue('Skel',false,@(v)islogical(v));
479  i.addParamValue('Pool',false,@(v)islogical(v));
480  i.addParamValue('PM',[],@(v)isa(v,'PlotManager'));
481  i.addParamValue('DF',[]);
482  i.addParamValue('NF',[]);
483  i.addParamValue('F',[]);
484  i.addParamValue('Elems',1:this.Config.FEM.Geometry.NumElements);
485  i.addParamValue('Invariants',[]);
486  i.addParamValue('Lambdas',false,@(v)islogical(v));
487  i.addParamValue('MR',false);
488  i.addParamValue('MTRatio',false,@(v)islogical(v));
489  i.addParamValue('Pause',.01);
490  i.addParamValue('Stretch',false,@(v)islogical(v));
491 
492  args = [this.DefaultArgs args];
493  i.parse(args[:]);
494  opts = i.Results;
495  if ~isempty(opts.NF)
496  opts.Forces= true;
497  end
498  }
499 
500 
501  function pd = initPlotData() {
502  sys = this.System;
503  pd = struct;
504  hlp = sum(sys.bool_u_bc_nodes,1);
505  pd.bc_dir_3pos_applies= hlp == 3;
506  pd.bc_dir_2pos_applies= hlp == 2;
507  pd.bc_dir_1pos_applies= hlp == 1;
508  pd.bc_dir_pos_applies= hlp >= 1;
509  pd.bool_expl_v_bc_nodes_applies= sum(sys.bool_expl_v_bc_nodes,1) >= 1;
510  pd.no_bc= ~pd.bc_dir_pos_applies & ~pd.bool_expl_v_bc_nodes_applies;
511 
512  mc = this.Config;
513  dfem = mc.FEM;
514  geo = dfem.Geometry;
515  num_u_glob = geo.NumNodes * 3;
516  pd.vstart= num_u_glob+1;
517  pd.pstart= 2*num_u_glob+1;
518  pd.e= geo.Edges;
519 
520  /* % Dirichlet forces */
521  pd.have_residuals= pd.bc_dir_pos_applies | pd.bool_expl_v_bc_nodes_applies;
522  /* By sorting and combining the pos/velo Dir BC, the
523  * plotting of mixed BCs on one node is plotted correctly. */
524  pd.residuals_pos= sys.bool_u_bc_nodes | sys.bool_expl_v_bc_nodes;
525 /* [~, pd.sortidx] = sort([sys.idx_u_bc_glob; sys.idx_expl_v_bc_glob]);
526  * Preallocate the residuals matrix */
527  pd.residuals= zeros(size(pd.residuals_pos));
528 
529  /* % Fibres
530  *if sys.HasFibres || ~isempty(opts.Invariants) */
531  pd.Ngp= dfem.N(dfem.GaussPoints);
532  /* end */
533 
534  /* Set muscle color either way */
535  pd.musclecol= [0.854688, 0.201563, 0.217188];
536  pd.gpcol= [];
537  /* % Muscle/Tendon patch vertex colors */
538  if sys.HasTendons
539  tendoncol = [1, .8, .6]; /* Micha [.9 .7 .5]
540  * Vertex coloring */
541 
542  pd.vertexcol= ones(geo.NumNodes,1)*pd.musclecol ...
543  + sys.MuscleTendonRatioNodes^t*(tendoncol-pd.musclecol);
544  /* Gauss point coloring */
545  tmr = sys.MuscleTendonRatioGP;
546  pd.gpcol(:,:,1) = pd.musclecol(1) + tmr*(tendoncol(1)-pd.musclecol(1));
547  pd.gpcol(:,:,2) = pd.musclecol(2) + tmr*(tendoncol(2)-pd.musclecol(2));
548  pd.gpcol(:,:,3) = pd.musclecol(3) + tmr*(tendoncol(3)-pd.musclecol(3));
549  pd.gpcol= permute(pd.gpcol,[1 3 2]);/* *.8; */
550 
551  end
552  }
553 
554  function box = getPlotBox(uvw) {
555  xpos = 1:3:this.Config.FEM.Geometry.NumNodes*3;
556  box = [min(min(uvw(xpos,:))) max(max(uvw(xpos,:)))...
557  min(min(uvw(xpos+1,:))) max(max(uvw(xpos+1,:)))...
558  min(min(uvw(xpos+2,:))) max(max(uvw(xpos+2,:)))];
559  diam = diff(box)*.1;
560  box = box + [-diam(1) diam(1) -diam(3) diam(3) -diam(5) diam(5)];
561  }
573 };
574 }
575 }
576 
MuscleFibreSystem: The global dynamical system used within the MuscleFibreModel.
Definition: System.m:19
A MatLab cell array or matrix.
reshape
hanges the dimensions of the handle object array to the specified dimensions. See the MATLAB reshape ...
PlotManager: Small class that allows the same plots generated by some script to be either organized a...
Definition: PlotManager.m:17
Matlab's base handle class (documentation generation substitute)
#define F(x, y, z)
Definition: CalcMD5.c:168
logical LeaveOpen
Flag indicating if the plots should be left open once the PlotManager is deleted (as variable) ...
Definition: PlotManager.m:213
function box = getPlotBox(uvw)
end
A variable number of input arguments.
mu
The current parameter for simulations, [] is none used.
permute
Rearranges the dimensions of the handle object array. See the MATLAB permute function.
function [ pd , double t , matrix< double > y ] = updatePlotData(pd, opts,double t,matrix< double > y)
function pd = initPlotData()
function opts = parsePlotArgs(args)
function plotGeometry(h,double t, y_dofs, ts, opts)
function [ pm , h ] = plot(double t, y_dofs, varargin)
Definition: MusclePlotter.m:61