56 this.
Config= sys.Model.Config;
67 if ~isempty(mc.Pool) && opts.Pool
81 [p,n,e] = fileparts(opts.Vid);
82 if ~isempty(p) && exist(p,
" file ") ~= 7
83 error(
" Directory %s not found ",p);
86 if isa(mc,
" models.muscle.AExperimentModelConfig ")
98 avifile = fullfile(p,[n e]);
99 vw = VideoWriter(avifile);
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]);
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);
128 if ~isempty(mc.Pool) && opts.Pool
130 alpha = mc.Pool.getActivation(times);
131 walpha = mc.FibreTypeWeights(1,:,1) * alpha;
133 plot(hf,times,alpha);
134 plot(hf,times,walpha,
" LineWidth ",2);
146 if ~isempty(opts.Vid) && ishandle(h)
147 vw.writeVideo(getframe(gcf));
166 casecap =
" Deformation ";
168 casecap =
" Lambda-stretches ";
170 title(h,sprintf(
" %s at t=%g ",casecap,t));
174 nelem = length(opts.Elems);
176 u =
reshape(y_dofs(1:pd.vstart-1),3,[]);
177 v =
reshape(y_dofs(pd.vstart:pd.pstart-1),3,[]);
180 geo = this.
Config.FEM.Geometry;
183 plot3(h,u(1,pd.no_bc),u(2,pd.no_bc),u(3,pd.no_bc),
" r. ",
" MarkerSize ",14);
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 ");
188 p = patch(
" Faces ",geo.PatchFaces,
" Vertices ",u^t,...
189 " Parent ",h,
" FaceAlpha ",.3);
191 set(p,
" FaceVertexCData ",pd.vertexcol,
" FaceColor ",...
192 " interp ",
" FaceAlpha ",.5,
" EdgeColor ",
" interp ");
194 set(p,
" EdgeColor ",.8*pd.musclecol,
" FaceColor ",pd.musclecol);
200 quiver3(h,u(1,:),u(2,:),u(3,:),v(1,:),v(2,:),v(3,:),1,
" b ",
" MarkerSize ",14);
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]);
213 uvdir = u(:,pd.bool_expl_v_bc_nodes_applies);
214 plot3(h,uvdir(1,:),uvdir(2,:),uvdir(3,:),
" g. ",
" MarkerSize ",20);
218 residuals = pd.residuals;
219 have_residuals = pd.have_residuals;
220 udir = u(:,have_residuals);
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);
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);
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);
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);
255 p = y_dofs(pd.pstart:sys.num_uvp_glob);
256 pn = sys.idx_p_to_u_nodes;
260 scatter3(h,u(1,pn(pneg)),u(2,pn(pneg)),u(3,pn(pneg)),...
261 -p(pneg)*10+1,[188 188 255]/255);
266 scatter3(h,u(1,pn(~pneg)),u(2,pn(~pneg)),u(3,pn(~pneg)),...
267 p(~pneg)*10+1,[255 188 188]/255);
273 fibres = sys.HasFibres && opts.Fibres;
274 doI1 = any(opts.Invariants == 1);
275 doLam = opts.Lambdas;
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));
287 scatter3(h,gps(1,:),gps(2,:),gps(3,:),1,pd.stretchcol(:,:,elemidx,ts)
" , ".
" , "SizeData^
t,30);
290 anull = u*sys.dNa0(:,:,m);
291 quiver3(gps(1,:),gps(2,:),gps(3,:),anull(1,:),anull(2,:),anull(3,:),.5,
" . ",
" Color ",
" w ");
295 if ~isempty(pd.gpcol)
296 scatter3(h,gps(1,:),gps(2,:),gps(3,:),1,pd.gpcol(:,:,m),
" . ",
" SizeData ",30);
301 values = sprintfc(
" I_1=%3.3g ",pd.I1(:,elemidx,ts));
302 text(gps(1,:),gps(2,:),gps(3,:),values,
" Parent ",h)
307 values = sprintfc(
" %3.4g ",pd.lambdas(:,elemidx,ts));
308 text(gps(1,:),gps(2,:),gps(3,:),values,
" Parent ",h)
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)
318 values = sprintfc(
" %3.4g ",sys.MuscleTendonRatioGP(:,m,ts));
320 text(gps(1,:),gps(2,:),gps(3,:),values,
" Parent ",h)
325 colormap(pd.stretchcmap);
326 colorbar(
" YTickLabel ",pd.stretchcmaplbl);
343 y = y(:,1:opts.F:end);
345 pd.DF= pd.DF(:,1:opts.F:end);
348 pd.NF= pd.NF(:,1:opts.F:end);
353 pd.yfull= sys.includeDirichletValues(t, y);
358 pd.maxdfval= max(abs(opts.DF(:)))/10;
366 forces = zeros(size(sys.bool_u_bc_nodes));
367 forces(sys.idx_neumann_bc_glob) = sys.bc_neum_forces_val;
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);
378 pd.meanforces= meanforces;
379 pd.force_elem_face_idx= force_elem_face_idx;
382 pd.forces_apply= sum(abs(forces),1) ~= 0;
383 pd.forces= forces(:,pd.forces_apply);
386 pd.residual_neumann_forces= zeros(size(sys.bool_u_bc_nodes));
393 pd.musclecol= [0.854688, 0.201563, 0.217188];
397 if ~isempty(opts.Invariants) || opts.Lambdas || opts.MR || opts.Stretch
399 nelem = length(opts.Elems);
400 doI1 = any(opts.Invariants == 1);
401 doLam = opts.Lambdas;
403 doStr = opts.Stretch;
405 pd.I1= zeros(dfem.GaussPointsPerElem,nelem,nt);
408 pd.lambdas= zeros(dfem.GaussPointsPerElem,nelem,nt);
410 pd.stretchcol= zeros(3,dfem.GaussPointsPerElem,nelem,nt);
414 pd.MR=
cell(dfem.GaussPointsPerElem,nelem,nt);
415 c10 = sys.MuscleTendonParamc10;
416 c01 = sys.MuscleTendonParamc01;
418 num_gp = dfem.GaussPointsPerElem;
419 for elemidx = 1:nelem
420 m = opts.Elems(elemidx);
422 pos = 3*(gp-1)+1:3*gp;
423 dtn = dfem.transgrad(:,pos,m);
424 elemidx_u = sys.idx_u_elems_local(:,:,m);
427 yts = pd.yfull(:,ts) ;
428 F = yts(elemidx_u) * dtn;
431 pd.I1(gp,elemidx,ts) = C(1,1)+C(2,2)+C(3,3);
434 fibres = sys.a0Base(:,:,(m-1)*num_gp + gp);
435 pd.lambdas(gp,elemidx,ts) = norm(F*fibres(:,1));
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 ...
446 Mlam = max(pd.lambdas(:));
447 mlam = min(pd.lambdas(:));
448 center = (1-mlam)/(Mlam-mlam);
449 if abs(Mlam-mlam) < 1e-8
451 pd.stretchcol(2,:,:,:) = 1;
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);];
457 for elemidx = 1:nelem
458 normlam = (pd.lambdas(:,elemidx,ts)-mlam) / (Mlam-mlam);
459 pd.stretchcol(:,:,elemidx,ts) = colfun(normlam^t);
463 pd.stretchcmap= colfun(linspace(0,1,125))^
t;
464 pd.stretchcmaplbl= sprintfc(
" %3.3g ",linspace(mlam,Mlam,12));
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));
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;
515 num_u_glob = geo.NumNodes * 3;
516 pd.vstart= num_u_glob+1;
517 pd.pstart= 2*num_u_glob+1;
521 pd.have_residuals= pd.bc_dir_pos_applies | pd.bool_expl_v_bc_nodes_applies;
524 pd.residuals_pos= sys.bool_u_bc_nodes | sys.bool_expl_v_bc_nodes;
527 pd.residuals= zeros(size(pd.residuals_pos));
531 pd.Ngp= dfem.N(dfem.GaussPoints);
535 pd.musclecol= [0.854688, 0.201563, 0.217188];
539 tendoncol = [1, .8, .6];
542 pd.vertexcol= ones(geo.NumNodes,1)*pd.musclecol ...
543 + sys.MuscleTendonRatioNodes^
t*(tendoncol-pd.musclecol);
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]);
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,:)))];
560 box = box + [-diam(1) diam(1) -diam(3) diam(3) -diam(5) diam(5)];
MuscleFibreSystem: The global dynamical system used within the MuscleFibreModel.
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...
Matlab's base handle class (documentation generation substitute)
logical LeaveOpen
Flag indicating if the plots should be left open once the PlotManager is deleted (as variable) ...
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)