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
System.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 System
33  public:
34 
53  public:
54 
115 
117 
141 
143 
167 
209 
211 
212 
239 
241 
243 
244 
257 
258 
259  HasFibres = false;
270  HasFibreTypes = false;
271 
272  HasMotoPool = false;
273 
287  a0;
288 
290 
292 
294 
295 
296  HasTendons = false;
307  MuscleTendonParamMapFun = @("v,mi,ma)10.^(log10(mi) + v.*(log10(ma)-log10(mi))");
320 
322 
323 
337 
369 
370 
371  public: /* ( Dependent ) */
372 
409  private:
410 
411  fUseDirectMassInversion = false;
412 
413  fUseCrossFibreStiffness = false;
414 
415  fD;
416 
417 
418  public:
419 
421 
422 
423  private: /* ( Transient ) */
424 
425  velo_bc_fun = "[]";
437  public: /* ( Transient ) */
438 
440  this = this@models.BaseSecondOrderSystem(model);
441 
442  /* The muscle viscosity
443  * @unit [g / (mm * ms)] = [kP] (kiloPoiseulle) */
444  this.addParam(" viscosity ",.1);
445 
446  /* The amount of milliseconds over which to activate the model
447  * Set this parameter to zero to deactivate (any maybe use a
448  * custom activation ramp)
449  *
450  * @unit [ms] */
451  this.addParam(" alpha_ramp_time ",0);
452 
453  /* The pressure on the faces (neumann conditions)
454  *
455  * @unit [MPa] = [N / mm^2] */
456  this.addParam(" neumann_pressure ",0);
457 
458  /* For some variants, we have the mean input current for the
459  * motoneuron pool (generating activation) */
460  this.addParam(" mean input current ",0);
461 
462  /* anisotropic passive stiffness for muscle material
463  * markert law b1
464  *
465  * @unit [MPa]
466  * #5 */
467  this.addParam(" muscle passive b1 ",2.756e-5);
468 
469  /* anisotropic passive stiffness for muscle material
470  * markert law d1 [-]
471  * #6 */
472  this.addParam(" muscle passive d1 ",43.373);
473 
474  /* anisotropic passive stiffness for tendon material
475  * markert law
476  *
477  * @unit [MPa]
478  *
479  * -or-
480  * ideal length of sarcomere w.r.t force production [-]
481  *
482  * fit with general.functions.MarkertLaw: b1 = 1.3895e+04
483  * fit with general.functions.QuadToLinear: lam0 = 1.027
484  * fit with general.functions.CubicToLinear: lam0 = 1.0175 [26.2.15]
485  * fit with general.functions.CubicToLinear: lam0 = 1.0207 [29.4.15, after scaling fix]
486  * #7 */
487  this.addParam(" tendon passive 1 [b1/lam0] ", 1.0207); /* [MPa/-] */
488 
489 
490  /* anisotropic passive stiffness for tendon material
491  * markert law
492  *
493  * fit with general.functions.MarkertLaw: d1 = 11.1429 [-]
494  * max modulus 1.637893706954065e+05
495  * fit with general.functions.QuadToLinear: M = 1.637893706954065e+05
496  * fit with general.functions.CubicToLinear: M = 1.637893706954065e+05 [26.2.15]
497  * fit with general.functions.CubicToLinear: M = 1.637893706954065e+05 [29.4.15, after scaling fix]
498  * #8 */
499  this.addParam(" tendon passive 2 [d1/M] ", 1.637893706954065e+05);
500 
501  /* isotropic muscle material
502  * mooney-rivlin law c10
503  *
504  * from sprenger thesis: 35.6 kPa
505  *
506  * @unit [MPa]
507  *
508  * #9 */
509  this.addParam(" muscle mooney-rivlin c10 ",35.6e-3);
510 
511  /* isotropic muscle material
512  * mooney-rivlin law c01
513  *
514  * from sprenger thesis: 3.86 kPa
515  *
516  * @unit [MPa]
517  *
518  * #10 */
519  this.addParam(" muscle mooney-rivlin c01 ",3.86e-3);
520 
521  /* isotropic tendon material
522  * mooney-rivlin law c10
523  *
524  * @unit [MPa]
525  *
526  * #11 */
527  this.addParam(" tendon mooney-rivlin c10 ",2.310e3);
528 
529  /* isotropic tendon material
530  * mooney-rivlin law c01
531  *
532  * @unit [MPa]
533  *
534  * #12 */
535  this.addParam(" tendon mooney-rivlin c01 ",1.15e-3);
536 
537  /* muscle fibre maximal force
538  *
539  * @unit [MPa]
540  *
541  * #13 */
542  this.addParam(" P_max ",.3);
543 
544  /* parameter p1 for force-length curve customization.
545  *
546  * For linear curve from Gordon66 we set lambda_0 with this,
547  * i.e. the resting sarcomere length. According to literature,
548  * somewhere between 2 and 2.2 micrometer.
549  * #14 */
550  this.addParam(" force-length p1 (lam_0/width/...) ",2.05);
551 
552  /* % Set system components
553  * Core nonlinearity */
554  this.f= models.muscle.Dynamics(this);
555 
556  /* Constraint nonlinearity */
557  this.g= models.muscle.Constraint(this);
558  }
567  function rsys = buildReducedSystem(models.ReducedModel rmodel) {
568  this.D= this.fD;
569  rsys = buildReducedSystem@models.BaseSecondOrderSystem(this, rmodel);
570  this.D= [];
571  }
585  function configUpdated() {
586  mc = this.Model.Config;
587  if ~isempty(mc)
588  tq = mc.FEM;
589  geo_pos = tq.Geometry;
590  tl = mc.PressureFEM;
591  geo_p = tl.Geometry;
592 
593  /* Find the indices of the pressure nodes in the displacement
594  * nodes geometry (used for plotting) */
595  this.idx_p_to_u_nodes= geo_pos.getCommonNodesWith(geo_p);
596 
597  /* Call subroutine for boundary condition index crunching
598  * This needs to be done before we can compute the effective
599  * Dofs of the system. */
600  this.computeDirichletBC;
601 
602  /* % Get dimensions */
603  this.updateDimensions(mc);
604 
605  /* Construct B matrix */
606  this.B= this.assembleB;
607 
608  /* Set input function */
609  this.Inputs= mc.getInputs;
610 
611  /* % Tendon stuff
612  * Detect of tendons are present */
614 
615  /* Init fibre directions and precomputable values */
616  this.inita0;
617 
618  this.HasMotoPool= this.HasFibres && ~isempty(mc.Pool);
619  this.HasFibreTypes= this.HasFibres && ~isempty(mc.FibreTypeWeights);
620  this.HasForceArgument= this.HasFibreTypes && isa(this," fullmodels.muscle.System ");
621 
622  /* Construct global indices in uw from element nodes. Each dof in
623  * an element is used three times for x,y,z displacement. The
624  * "elems" matrix contains the overall DOF numbers of each
625  * element in the order of the nodes (along row) in the master
626  * element. */
627  ne = geo_pos.NumElements;
628  globalelementdofs = zeros(3,geo_pos.DofsPerElement,ne," int32 ");
629  for m = 1:ne
630  /* First index of element dof in global array */
631  hlp = (geo_pos.Elements(m,:)-1)*3+1;
632  /* Use first, second and third as positions. */
633  globalelementdofs(:,:,m) = [hlp; hlp+1; hlp+2];
634  end
635  this.idx_u_elems_local= globalelementdofs;
636 
637  /* The same for the pressure */
638  globalpressuredofs = zeros(geo_p.DofsPerElement,geo_p.NumElements," int32 ");
639  for m = 1:geo_p.NumElements
640  globalpressuredofs(:,m) = geo_p.Elements(m,:);
641  end
642  this.idx_p_elems_local= globalpressuredofs;
643 
644  /* % Compile Mass Matrix */
645  this.M= dscomponents.ConstMassMatrix(this.assembleMassMatrix);
646 
647  /* % Compile Damping Matrix */
648  this.fD= this.assembleDampingMatrix;
649 
650  /* % Tell f we have a new config */
651  this.f.configUpdated;
652 
653  /* % Initial value */
654  this.x0= dscomponents.ConstInitialValue(this.assembleX0);
655 
656  /* % Algebraic constraints function */
657  this.g.configUpdated;
658 
660  end
661  }
662 
663 
665 
666  this.D= [];
667  if mu(1) > 0
668  this.D= this.fD;
669  end
670  /* Update muscle/tendon parameters on all gauss points
671  * We have mu-dependent mooney-rivlin and markert laws, but they
672  * are constant over one simulation. So precompute here. */
673  this.updateTendonMuscleParamsGP(mu);
674 
675  /* Update the MooneyRivlinICConst to have stress-free IC
676  * This depends on the current muscle/tendon parameters for
677  * mooney-rivlin (updated one step before) */
679  -4*this.MuscleTendonParamc01;
680 
681  /* Get velocity dirichlet conditions time-function */
682  mc = this.Model.Config;
683  if ~isempty(mc.VelocityBCTimeFun)
684  this.velo_bc_fun= mc.VelocityBCTimeFun.getFunction;
685  end
686 
687  prepareSimulation@models.BaseSecondOrderSystem(this, mu, inputidx);
688  }
700  function pm = plotDiff(double t,uvw1,uvw2,fac,varargin) {
701  if nargin < 5
702  fac = 5;
703  end
704  x0 = this.x0.evaluate([]);
705  diff = repmat(x0,1,length(t)) + (uvw1-uvw2)*fac;
706  pm = this.plot(t,diff,varargin[:]);
707  }
708 
709 
710  function uvwall = includeDirichletValues(double t,uvw) {
711  if size(uvw,2) == 1
712  uvwall = zeros(this.num_uvp_glob, 1);
713  uvwall(this.idx_uv_dof_glob) = uvw;
714  uvwall(this.idx_uv_bc_glob) = this.val_uv_bc_glob;
715  if ~isempty(this.velo_bc_fun)
716  uvwall(this.idx_v_bc_glob) = uvwall(this.idx_v_bc_glob)*this.velo_bc_fun(t);
717  end
718  else
719  uvwall = zeros(this.num_uvp_glob, size(uvw,2));
720  uvwall(this.idx_uv_dof_glob,:) = uvw;
721  uvwall(this.idx_uv_bc_glob,:) = repmat(this.val_uv_bc_glob,1,size(uvw,2));
722  if ~isempty(this.velo_bc_fun)
723  uvwall(this.idx_v_bc_glob,:) = bsxfun(@times, uvwall(this.idx_v_bc_glob,:), this.velo_bc_fun(t));
724  end
725  end
726  }
737  public: /* ( Transient ) */
738 
739 
740 #if 0 //mtoc++: 'set.UseDirectMassInversion'
741 function UseDirectMassInversion(value) {
742  if ~islogical(value) || ~isscalar(value)
743  error(" UseDirectMassInversion must be true or false ");
744  end
745  if this.fUseDirectMassInversion ~= value
746  this.fUseDirectMassInversion= value;
747  this.configUpdated;
748  end
749  }
750 
751 #endif
752 
753 
754 
755 #if 0 //mtoc++: 'get.UseDirectMassInversion'
756 function value = UseDirectMassInversion() {
757  value = this.fUseDirectMassInversion;
758  }
759 
760 #endif
761 
762 
763 
764 #if 0 //mtoc++: 'set.UseCrossFibreStiffness'
765 function UseCrossFibreStiffness(value) {
766  if ~islogical(value) || ~isscalar(value)
767  error(" UseCrossFibreStiffness must be true or false ");
768  end
769  if this.fUseCrossFibreStiffness ~= value
770  this.fUseCrossFibreStiffness= value;
771  if ~isempty(this.Model.Config)
772  this.inita0;
773  end
774  end
775  }
776 
777 #endif
778 
779 
780 
781 #if 0 //mtoc++: 'get.UseCrossFibreStiffness'
782 function value = UseCrossFibreStiffness() {
783  value = this.fUseCrossFibreStiffness;
784  }
785 
786 #endif
787 
788 
789  protected: /* ( Transient ) */
790 
791 
792  function updateDimensions(mc) {
793  tl = mc.PressureFEM;
794  geo_p = tl.Geometry;
795  this.NumAlgebraicDofs= geo_p.NumNodes;
796 
797  tq = mc.FEM;
798  geo_uv = tq.Geometry;
799  this.NumStateDofs= geo_uv.NumNodes * 3 - length(this.idx_u_bc_glob);
800 
801  this.num_uvp_glob= geo_uv.NumNodes * 6 + this.NumAlgebraicDofs;
802  /* Compile the inverse addressing for inserting dofs into the
803  * full vector */
804  idx = int32(1:this.num_uvp_glob);
805  idx(this.idx_uv_bc_glob) = [];
806  this.idx_uv_dof_glob= idx;
807 
808  /* Have same number of xdot dofs than x dofs except the case
809  * that explicit velocity dirichlet conditions are provided */
810  this.NumDerivativeDofs= this.NumStateDofs - length(this.idx_expl_v_bc_local);
811 
812  updateDimensions@models.BaseSecondOrderSystem(this);
813  }
814 
815 
816  function x0 = assembleX0() {
817  mc = this.Model.Config;
818  tq = mc.FEM;
819  geo = tq.Geometry;
820 
821  /* Fill in the reference configuration positions as initial
822  * conditions */
823  x0 = geo.Nodes(:);
824  /* Remove those fixed via dirichlet conditions */
825  x0(this.idx_u_bc_local) = []; /* local=global here as is first set */
826 
827 
828  /* Give the model config a chance to mess with x0 */
829  x0 = mc.getX0(x0);
830  }
838  function Baff = assembleB() {
839  mc = this.Model.Config;
840  /* Collect neumann forces */
841  [B, this.idx_neumann_bc_glob, this.FacesWithForce] = mc.getSpatialExternalForces;
842  /* Only set up forces if present */
843  Baff = [];
844  if ~isempty(this.idx_neumann_bc_glob)
845  this.bc_neum_forces_val= B(this.idx_neumann_bc_glob);
846  /* Remove velocity dirichlet DoFs */
847  B(this.idx_v_bc_local) = [];
848  Baff = dscomponents.AffLinInputConv;
849  Baff.TimeDependent= false;
850  Baff.addMatrix(" mu(3) ",B);
851 
852  this.idx_neumann_bc_dof= find(B);
853  end
854  }
855 
856 
857  function MM = assembleMassMatrix() {
858  mc = this.Model.Config;
859  fe_pos = mc.FEM;
860  g = fe_pos.Geometry;
861 
862  /* Augment mass matrix for all 3 displacement directions */
863  nd = g.NumNodes;
864  [i, j, s] = find(fe_pos.M);
865  I = [3*(i" -1)+1; 3*(i "-1)+2; 3*(i^t-1)+3];
866  J = [3*(j" -1)+1; 3*(j "-1)+2; 3*(j^t-1)+3];
867  S = repmat(1:length(s),3,1);
868  MM = this.Model.MuscleDensity*sparse(I(:),J(:),s(S(:)),3*nd,3*nd);
869 
870  /* Strip out the entries of dirichlet nodes */
871  MM(this.idx_v_bc_local,:) = [];
872  MM(:,this.idx_v_bc_local) = [];
873 
874  /* See description of property */
875  if this.UseDirectMassInversion
876  this.Minv= inv(MM);
877  MM = speye(size(MM));
878  end
879  }
887  function Daff = assembleDampingMatrix() {
888  mc = this.Model.Config;
889  fe_pos = mc.FEM;
890  g = fe_pos.Geometry;
891 
892  /* Augment mass matrix for all 3 displacement directions */
893  nd = g.NumNodes;
894  [i, j, s] = find(fe_pos.D);
895  I = [3*(i" -1)+1; 3*(i "-1)+2; 3*(i^t-1)+3];
896  J = [3*(j" -1)+1; 3*(j "-1)+2; 3*(j^t-1)+3];
897  S = repmat(1:length(s),3,1);
898  D = sparse(I(:),J(:),s(S(:)),3*nd,3*nd);
899 
900  /* Strip out the entries of dirichlet nodes */
901  D(this.idx_v_bc_local,:) = [];
902  D(:,this.idx_v_bc_local) = [];
903 
904  Daff = dscomponents.AffLinCoreFun(this);
905  Daff.addMatrix(" mu(1) ",-D);
906  }
914  function computeDirichletBC() {
915  mc = this.Model.Config;
916  [pos_dir, velo_dir, velo_dir_val] = mc.getBC;
917 
918  fe_displ = mc.FEM;
919  geo = fe_displ.Geometry;
920 /* fe_press = mc.PressureFEM;
921  * pgeo = fe_press.Geometry; */
922 
923  /* Total number of position entries in global vector */
924  num_u_glob = geo.NumNodes * 3;
925 
926  /* % Displacement / State Dirichlet */
927  this.bool_u_bc_nodes= pos_dir;
928  /* Set values to node positions */
929  this.val_u_bc= geo.Nodes(pos_dir);
930  this.idx_u_bc_local= int32(find(pos_dir(:)));
931  /* Local = global as u is the first set of variables in the
932  * global vector */
933  this.idx_u_bc_glob= this.idx_u_bc_local;
934 
935  /* % Velocity / Derivative Dirichlet
936  * Add any user-defines values */
937  this.bool_expl_v_bc_nodes= velo_dir;
938  this.idx_expl_v_bc_local= int32(find(velo_dir(:)));
939  this.val_expl_v_bc= velo_dir_val(velo_dir);
940  this.idx_expl_v_bc_glob= this.idx_expl_v_bc_local + num_u_glob;
941 
942  /* Compute position of explicit derivative dirichlet conditions
943  * inside the state dofs */
944  pos = false(num_u_glob,1);
945  /* Mark positions of explicit conditions */
946  pos(this.idx_expl_v_bc_local) = true;
947  /* Remove implicit velocity dirichlet conditions from position
948  * dirichlet conditions */
949  pos(this.idx_u_bc_local) = [];
951 
952  /* Include the zero velocity conditions that apply for each
953  * position dirichlet condition
954  * (cannot conflict with position dirichlet conditions, this is
955  * checked in AMuscleConfig.getBC) */
956  [this.idx_v_bc_local, idx] = sort([this.idx_expl_v_bc_local; this.idx_u_bc_local]);
957  /* Here we add zero velocities for each point with fixed position, too. */
958  this.val_v_bc= [this.val_expl_v_bc; zeros(size(this.val_u_bc))];
959  this.val_v_bc= this.val_v_bc(idx);
960  this.num_v_bc= length(this.val_v_bc);
961  this.idx_v_bc_glob= this.idx_v_bc_local + num_u_glob;
962 
963  /* % Convenience index sets
964  * Compile the global dirichlet values index and value vectors.
965  * Again, we sort the index vector for easy insertion
966  * (=following matlab linear indexing) into the global arrays */
967  [this.idx_uv_bc_glob, idx] = sort([this.idx_u_bc_glob; this.idx_v_bc_glob]);
968  this.val_uv_bc_glob= [this.val_u_bc; this.val_v_bc];
969  this.val_uv_bc_glob= this.val_uv_bc_glob(idx);
970 
971  /* Compute dof positions in global state space vector
972  *
973  * pos = false(1,total);
974  * pos(1:num_u_glob) = true;
975  * pos(this.idx_uv_bc_glob) = [];
976  * this.idx_u_dof_glob = int32(find(pos)); */
977 
978 /* pos = false(1,total);
979  * pos(num_u_glob+1:num_u_glob*2) = true;
980  * pos(this.idx_uv_bc_glob) = [];
981  * this.idx_v_dof_glob = int32(find(pos)); */
982 
983 /* pos = false(1,total);
984  * pos(this.idx_v_bc_glob-num_u_glob) = true;
985  * pos(this.idx_u_bc_glob) = [];
986  * this.idx_v_bc_u_dof = int32(find(pos)); */
987 
988  /* no possible dirichlet values for p. so have all
989  * this.idx_p_dof_glob = geo.NumNodes*6-length(this.idx_uv_bc_glob) + (1:pgeo.NumNodes);
990  * this.NumAlgebraicDofs = length(this.idx_p_dof_glob);
991  * Automatically mark the pressure DoFs as algebraic condition.
992  * Important for reduction.
993  * this.AlgebraicConditionDoF = this.idx_p_dof_glob; */
994 
995 
996  }
997 
998 
999  function val = getDerivativeDirichletValues(double t) {
1000 
1001 
1002  /* Check if velocity bc's should be applied in time-dependent manner */
1003  if ~isempty(this.velo_bc_fun)
1004  val = this.velo_bc_fun(t)*this.val_expl_v_bc;
1005  else
1006  val = this.val_expl_v_bc;
1007  end
1008  }
1021  function inita0() {
1022  mc = this.Model.Config;
1023  fe = mc.FEM;
1024  geo = fe.Geometry;
1025 
1026  anull = mc.geta0;
1027  ismastercoord = strcmp(mc.a0CoordinateSystem," master ");
1028  this.HasFibres= false;
1029  if any(anull(:))
1030  this.HasFibres= true;
1031 
1032  this.a0= anull;
1033 
1034  /* Precomputations */
1035  dNgp = fe.gradN(fe.GaussPoints);
1036  Ngp = fe.N(fe.GaussPoints);
1037 
1038  anulldyadanull = zeros(3,3,fe.GaussPointsPerElem*geo.NumElements);
1039  dNanull = zeros(geo.DofsPerElement,fe.GaussPointsPerElem,geo.NumElements);
1040  if this.fUseCrossFibreStiffness
1041  a0a0n1 = anulldyadanull;
1042  a0a0n2 = anulldyadanull;
1043  a0base = anulldyadanull;
1044  end
1045  for m = 1 : geo.NumElements
1046  u = geo.Nodes(:,geo.Elements(m,:));
1047  for gp = 1 : fe.GaussPointsPerElem
1048 
1049  /* Transform a0 to local fibre direction */
1050  pos = [0 fe.GaussPointsPerElem 2*fe.GaussPointsPerElem]+gp;
1051  Jac = u*dNgp(:,pos);
1052  if ismastercoord
1053  loc_anull = Jac * anull(:,gp,m);
1054  else
1055  loc_anull = anull(:,gp,m);
1056  end
1057  loc_anull = loc_anull/norm(loc_anull);
1058 
1059  /* Compute "the" two normals (any will do) */
1060  loc_anulln1 = circshift(loc_anull,1);
1061  loc_anulln1 = loc_anulln1 - (loc_anulln1^t*loc_anull) * loc_anull;
1062  loc_anulln1 = loc_anulln1/norm(loc_anulln1);
1063 
1064  loc_anulln2 = circshift(loc_anull,2);
1065  loc_anulln2 = loc_anulln2 - (loc_anulln2" *loc_anull) * loc_anull - (loc_anulln2 "*loc_anulln1) * loc_anulln1;
1066  loc_anulln2 = loc_anulln2/norm(loc_anulln2);
1067 
1068  /* forward transformation of a0 at gauss points
1069  * (plotting only so far) */
1070  if ismastercoord
1071  dNanull(:,gp,m) = dNgp(:,pos) * anull(:,gp,m);
1072  else
1073  dNanull(:,gp,m) = dNgp(:,pos) * (Jac \ anull(:,gp,m));
1074  end
1075 
1076  /* a0 dyad a0 */
1077  pos = (m-1)*fe.GaussPointsPerElem+gp;
1078  anulldyadanull(:,:,pos) = loc_anull*loc_anull^t;
1079  a0base(:,:,pos) = [loc_anull loc_anulln1 loc_anulln2];
1080  if this.fUseCrossFibreStiffness
1081  a0a0n1(:,:,pos) = loc_anulln1*loc_anulln1^t;
1082  a0a0n2(:,:,pos) = loc_anulln2*loc_anulln2^t;
1083  end
1084  end
1085  end
1086  this.a0oa0= anulldyadanull;
1087  this.dNa0= dNanull;
1088  this.a0Base= a0base;
1089 
1090  this.a0oa0n1= [];
1091  this.a0oa0n2= [];
1092  if this.fUseCrossFibreStiffness
1093  this.a0oa0n1= a0a0n1;
1094  this.a0oa0n2= a0a0n2;
1095  end
1096  end
1097  }
1098 
1099 
1101  mc = this.Model.Config;
1102  fe = mc.FEM;
1103  this.HasTendons= ~isempty(mc.getTendonMuscleRatio(zeros(3,1)));
1104  tmr = zeros(fe.GaussPointsPerElem,fe.Geometry.NumElements);
1105  if this.HasTendons
1106  g = fe.Geometry;
1107  for m = 1:g.NumElements
1108  /* Get coordinates of gauss points in element */
1109  tmr(:,m) = mc.getTendonMuscleRatio(g.Nodes(:,g.Elements(m,:)) * fe.N(fe.GaussPoints));
1110  end
1111  this.MuscleTendonRatioNodes= mc.getTendonMuscleRatio(g.Nodes);
1112  end
1113  this.MuscleTendonRatioGP= tmr;
1114  }
1115 
1116 
1117  private: /* ( Transient ) */
1118 
1119  function updateTendonMuscleParamsGP(colvec<double> mu) {
1120 
1121  /* All muscle - set without extra computations */
1122  tmr = this.MuscleTendonRatioGP;
1123  if ~this.HasTendons
1124  tmr(:) = mu(9);
1125  this.MuscleTendonParamc10= tmr;
1126  tmr(:) = mu(10);
1127  this.MuscleTendonParamc01= tmr;
1128  else
1129  f = this.MuscleTendonParamMapFun;
1130  /* Log-interpolated MR c10 */
1131  this.MuscleTendonParamc10= f(tmr,mu(9),mu(11));
1132  /* Log-interpolated MR c01 */
1133  this.MuscleTendonParamc01= f(tmr,mu(10),mu(12));
1134  end
1135  }
1146  public: /* ( Static ) */ /* ( Transient ) */
1147 
1148  static function res = test_UnassembledEvaluation() {
1149  m = models.muscle.Model(models.muscle.examples.Cube12);
1150  /* Dont do too much steps */
1151  m.dt= m.T / 20;
1152  mu = m.DefaultMu;
1153  [t,~,~,x] = m.simulate(mu);
1154  s = m.System;
1155  K = s.f;
1156  Ku = K.evaluate(x(:,1),t(1));
1157  g = s.g;
1158  gu = g.evaluate(x(:,1),t(1));
1159 
1160  K.ComputeUnassembled= true;
1161  g.ComputeUnassembled= true;
1162  Ku_unass = K.evaluate(x(:,1),t(1));
1163  gu_unass = g.evaluate(x(:,1),t(1));
1164  Ku_ass = K.Sigma * Ku_unass;
1165  gu_ass = g.Sigma * gu_unass;
1166  res = Norm.L2(Ku - Ku_ass) < eps;
1167  res = res && Norm.L2(gu - gu_ass) < eps;
1168 
1169  /* Multi-eval */
1170  K.ComputeUnassembled= false;
1171  Ku = K.evaluateMulti(x,t,mu);
1172  K.ComputeUnassembled= true;
1173  Ku_unass = K.evaluateMulti(x,t,mu);
1174  res = res & sum(Norm.L2(Ku - s.f.Sigma*Ku_unass)) < eps;
1175  }
1176 
1177 
1187 };
1188 }
1189 }
1190 
1191 
static function res = test_UnassembledEvaluation()
Definition: System.m:1148
bool_u_bc_nodes
% Position dirichlet fields Boundary conditions: 3 times numnodes logical matrix telling which degree...
Definition: System.m:98
function Baff = assembleB()
Definition: System.m:838
MuscleFibreSystem: The global dynamical system used within the MuscleFibreModel.
Definition: System.m:19
function uvwall = includeDirichletValues(double t, uvw)
% Re-add the dirichlet nodes Efficient for single vector
Definition: System.m:710
function pm = plotDiff(double t, uvw1, uvw2, fac, varargin)
Definition: System.m:700
function inita0()
Definition: System.m:1021
logical UseDirectMassInversion
Flag to invert the velocity mass matrix before simulations.
Definition: System.m:373
idx_u_elems_local
The global index of node x,y,z positions within uvw.
Definition: System.m:35
function computeDirichletBC()
Definition: System.m:914
function updateSparsityPattern()
The state space vector (NumTotalDofs) is composed of x: Original state space of second order model...
a0oa0n1
% Cross-fibre stiffness stuff normals to a0
Definition: System.m:357
The base class for any KerMor detailed model.
Definition: BaseFullModel.m:18
dscomponents.AInputConv B
The input conversion.
Model
The Model this System is attached to.
function MM = assembleMassMatrix()
% Compile Mass Matrix
Definition: System.m:857
sort
ort the handle objects in any array in ascending or descending order.
An integer value.
HasTendons
% Tendon stuff
Definition: System.m:296
The KerMor reduced model class.
Definition: ReducedModel.m:18
virtual function x0 = evaluate(mu)
Evaluates the initial value for a given mu.
#define I(x, y, z)
Definition: CalcMD5.c:171
function initMuscleTendonRatios()
Definition: System.m:1100
MuscleTendonParamc10
Fields to contain c10/c01 values for mooney-rivlin law (muscle+tendon)
Definition: System.m:324
inputidx
The current inputindex of the function .
idx_v_bc_u_dof
Positions of velocity-bc affected DoFs in the u dofs.
Definition: System.m:178
idx_neumann_bc_dof
[N]
Definition: System.m:199
HasForceArgument
Property only useful when fullmodel.System is used.. comes due to use of inheritance. Better solutions could be thought of, but this is to get it going!
Definition: System.m:274
Base class for all KerMor second-order dynamical systems.
dscomponents.LinearCoreFun D
The damping matrix of the second order system.
A boolean value.
dscomponents.AInitialValue x0
Function handle to initial state evaluation.
A variable number of input arguments.
val_uv_bc_glob
The overall values of dirichlet conditions.
Definition: System.m:69
mu
The current parameter for simulations, [] is none used.
DerivativeDirichletPosInStateDofs
A logical column vector containing true at the locations of explicit derivative dirichlet conditions...
val_expl_v_bc
[mm/ms]
Definition: System.m:144
Inputs
The system's possible input functions. A cell array of function handles, each taking a time argument ...
idx_p_elems_local
The global index of node pressures within uvw.
Definition: System.m:45
function x0 = assembleX0()
Constant initial values as current node positions.
Definition: System.m:816
idx_p_to_u_nodes
This contains the indices of the nodes tracking pressure (linear / 8-corner elements) within the quad...
Definition: System.m:55
function fx = evaluate(x, t)
Evaluates the f-approximation. Depending on a possible projection and the CustomProjection-property t...
Definition: ACoreFun.m:296
MuscleDensity
g/mm³
Definition: Model.m:36
num_uvp_glob
Total number of discrete field points including dirichlet values.
Definition: System.m:245
HasFibres
% Fibre stuff
Definition: System.m:259
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
function val = getDerivativeDirichletValues(double t)
Computes the derivative dirichlet values dependent on the current time.
Definition: System.m:999
dscomponents.ACoreFun f
The core f function from the dynamical system.
MooneyRivlinICConst
Stress free initial condition constant for mooney-rivlin law This was "classically" done by setting t...
Definition: System.m:338
dscomponents.ACoreFun g
The system's algebraic constraints function.
val_v_bc
[mm/ms]
Definition: System.m:168
idx_uv_bc_glob
The positions of the dirichlet values within the global node/xyz state space vector.
Definition: System.m:84
System(models.BaseFullModel model)
Call superclass constructor.
Definition: System.m:439
logical TimeDependent
Flag that indicates if the AInputConv is (truly) time-dependent.
Definition: AInputConv.m:39
function bool = ne(B)
Checks if two KerMorObjects are different.
Definition: KerMorObject.m:95
static function rowvec< double > n = L2(matrix< double > x)
Returns the discrete norm for each column vector in x.
Definition: Norm.m:39
idx_u_dof_glob
The indices of u,v,p components in the effective dof vector.
Definition: System.m:228
idx_uv_dof_glob
% Convenience variables A helper array containing the indices of the actual dofs in the global indexi...
Definition: System.m:213
function rsys = buildReducedSystem(models.ReducedModel rmodel)
Overrides the default buildReducedModel method in order to temporarily set the A component used in pr...
Definition: System.m:567
MuscleTendonParamMapFun
The function used to map between muscle (mi) and tendon (ma) parameter over [0,1] (v) ...
Definition: System.m:307
logaical UseCrossFibreStiffness
Flag to indicate if this system should use stiffness terms (Markert) for cross-fibre directions...
Definition: System.m:395
dscomponents.AMassMatrix M
The system's mass matrix.
function updateDimensions(mc)
Definition: System.m:792
Norm: Static class for commonly used norms on sets of vectors.
Definition: Norm.m:17
idx_neumann_bc_glob
% Neumann fields [N]
Definition: System.m:189
u
The current input function as function handle, [] if none used.
function ModelParam p = addParam(char name, default, varargin)
Adds a parameter with the given values to the parameter collection of the current dynamical system...
function Daff = assembleDampingMatrix()
% Compile Damping/Viscosity Matrix
Definition: System.m:887
function prepareSimulation(colvec< double > mu,integer inputidx)
Check for viscosity setting.
Definition: System.m:664
Model: Model for a FEM-discretized muscle model.
Definition: Model.m:19
function configUpdated()
Definition: System.m:585