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
getStateJacobianImpl.m
Go to the documentation of this file.
1 #include "Dynamics.m"
2 namespace models{
3 namespace muscle{
4 
5 
6 /* (Autoinserted by mtoc++)
7  * This source code has been filtered by the mtoc++ executable,
8  * which generates code that can be processed by the doxygen documentation tool.
9  *
10  * On the other hand, it can neither be interpreted by MATLAB, nor can it be compiled with a C++ compiler.
11  * Except for the comments, the function bodies of your M-file functions are untouched.
12  * Consequently, the FILTER_SOURCE_FILES doxygen switch (default in our Doxyfile.template) will produce
13  * attached source files that are highly readable by humans.
14  *
15  * Additionally, links in the doxygen generated documentation to the source code of functions and class members refer to
16  * the correct locations in the source code browser.
17  * However, the line numbers most likely do not correspond to the line numbers in the original MATLAB source files.
18  */
19 
20 function [JK , Jalpha , JLamDot ] = models.muscle.Dynamics.getStateJacobianImpl(uvwdof,double t) {
21  this.nJevals= this.nJevals+1;
22 /* J = this.getStateJacobianFD(uvwdof,t);
23  * return; */
24 
25  sys = this.fsys;
26 
27  mc = sys.Model.Config;
28  fe_pos = mc.FEM;
29  geo = fe_pos.Geometry;
30  fe_press = mc.PressureFEM;
31  pgeo = fe_press.Geometry;
32 
33  N = geo.NumNodes;
34  size_pos_vec = 3*N;
35  dofsperelem_pos = geo.DofsPerElement;
36  dofsperelem_press = pgeo.DofsPerElement;
37  num_gausspoints = fe_pos.GaussPointsPerElem;
38  num_elements = geo.NumElements;
39 
40  /* Cache variables instead of accessing them via "this." in loops */
41  Pmax = this.mu(13);
42  c10 = sys.MuscleTendonParamc10;
43  c01 = sys.MuscleTendonParamc01;
44 
45  flfun = this.ForceLengthFun;
46  dflfun = this.ForceLengthFunDeriv;
47 
48  havefibres = sys.HasFibres;
49  havefibretypes = sys.HasFibreTypes;
50  usecrossfibres = this.crossfibres;
51  hasforceargument = sys.HasForceArgument;
52  if usecrossfibres
53  b1cf = this.b1cf;
54  d1cf = this.d1cf;
55  end
56  ldotpos = this.lambda_dot_pos;
57  haveldotpos = ~isempty(ldotpos);
58  if haveldotpos
59  ildot = [];
60  jldot = [];
61  sldot = [];
62  end
63 
64  /* % Precompute the size of i,j,s for speed */
65  numXYZDofs_pos = 3*dofsperelem_pos;
66  relidx_pos = 1:numXYZDofs_pos;
67  /* 3x for grad_u K(u,v,w), 1x for Grad_w K(u,v,w) */
68  numparts = (3+1)*numXYZDofs_pos;
69 /* if visc > 0
70  * numparts = numparts+3*numXYZDofs_pos;
71  * end */
72  totalsize = num_elements*num_gausspoints*numparts;
73  i = zeros(totalsize,1);
74  j = zeros(totalsize,1);
75  s = zeros(totalsize,1);
76 
77  /* % Extra stuff if fibres are used */
78  if havefibres
79 
80  /* Muscle/tendon material inits. Assume muscle only. */
81  musclepart = 1;
82  anisomusclefun = this.AnisoPassiveMuscle;
83  anisomuscledfun = this.AnisoPassiveMuscleDeriv;
84  hastendons = sys.HasTendons;
85  if hastendons
86  tmrgp = sys.MuscleTendonRatioGP;
87  anisotendonfun = this.AnisoPassiveTendon;
88  anisotendondfun = this.AnisoPassiveTendonDeriv;
89  end
90 
91  if havefibretypes
92  alphaconst = [];
93  fibretypeweights = mc.FibreTypeWeights;
94  nfibres = size(fibretypeweights,2);
95  if sys.HasMotoPool
96  FibreForces = mc.Pool.getActivation(t);
97  elseif hasforceargument
98  FibreForces = uvwdof(sys.NumTotalDofs+1:end) * min(1,t);
99  totalsizeS = num_elements*num_gausspoints*nfibres;
100  iS = zeros(totalsizeS,1);
101  jS = zeros(totalsizeS,1);
102  sS = zeros(totalsizeS,1);
103  cur_offS = 0;
104  columns_sarco_link = 53:56:56*nfibres;
105  else
106  error(" No implemented ");
107  end
108  /* FibreForces = this.APExp.evaluate(forceargs)'; */
109  else
110  alphaconst = this.alpha(t);
111  end
112  end
113 
114  cur_off = 0;
115 
116  globidx_pos = sys.idx_u_elems_local;
117  idx_p_elems_global = sys.idx_p_elems_local + 2*size_pos_vec;
118 
119  /* Include dirichlet values to state vector */
120  uvwcomplete = sys.includeDirichletValues(t, uvwdof);
121 
122  for m = 1:num_elements
123  elemidx_u_glob = globidx_pos(:,:,m);
124  elemidx_v_glob = elemidx_u_glob + size_pos_vec;
125  /* This jacobian is offset at the beginning of the v global states -
126  * it's computed for the changes of the RHS w.r.t the v / derivative
127  * states (second order system).
128  * Hence the elemidx_u_glob instead of elemidx_v_glob */
129  elemidx_v_out_linear = elemidx_u_glob(:);
130  elemidx_v_out_linear3 = [elemidx_v_out_linear
131  elemidx_v_out_linear
132  elemidx_v_out_linear];
133  elemidx_p_global = idx_p_elems_global(:,m);
134 
135  if havefibretypes
136  ftwelem = fibretypeweights(:,:,m)*FibreForces;
137  end
138 
139  for gp = 1:num_gausspoints
140  pos = 3*(gp-1)+1:3*gp;
141  dtn = fe_pos.transgrad(:,pos,m);
142  u = uvwcomplete(elemidx_u_glob);
143 
144  /* Deformation gradient */
145  F = u * dtn;
146 
147  Finv = inv(F);
148  C = F^t*F;
149 
150  /* Evaluate the pressure at gauss points */
151  w = uvwcomplete(elemidx_p_global);
152  p = w^t * fe_press.Ngp(:,gp,m);
153 
154  /* Invariant I1 */
155  I1 = C(1,1) + C(2,2) + C(3,3);
156 
157  if havefibres
158  /* % Anisotropic part */
159  fibrenr = (m-1)*num_gausspoints + gp;
160  fibres = sys.a0Base(:,:,fibrenr);
161  Fa0 = F*fibres(:,1);
162  lambdaf = norm(Fa0);
163 
164  /* Get weights for tendon/muscle part at current gauss point */
165  if hastendons
166  tendonpart = tmrgp(gp,m);
167  musclepart = 1-tendonpart;
168  end
169 
170  alpha = musclepart*alphaconst;
171  if havefibretypes
172  alpha = musclepart*ftwelem(gp);
173  end
174  fl = flfun(lambdaf);
175  alpha_prefactor = (Pmax/lambdaf)*fl;
176  g_value = alpha_prefactor*alpha;
177  dg_dlam = (Pmax/lambdaf^2)*alpha*(dflfun(lambdaf) - fl);
178  /* Using > 1 is deadly. All lambdas are equal to one at t=0
179  * (reference config, analytical), but numerically this is
180  * dependent on how precise F and hence lambda is computed.
181  * It is very very close to one, but sometimes 1e-7 smaller
182  * or bigger.. and that makes all the difference! */
183  if lambdaf > 1.0001
184  g_value = g_value + musclepart*anisomusclefun(lambdaf);
185  dg_dlam = dg_dlam + musclepart*anisomuscledfun(lambdaf);
186  if hastendons
187  g_value = g_value + tendonpart*anisotendonfun(lambdaf);
188  dg_dlam = dg_dlam + tendonpart*anisotendondfun(lambdaf);
189  end
190  end
191  a0 = sys.a0oa0(:,:,fibrenr);
192 
193  /* % Cross-fibre stiffness part */
194  if usecrossfibres
195  Fcrossf1 = F*fibres(:,2);
196  lambdaa0_n1 = norm(Fcrossf1);
197  if lambdaa0_n1 > .999
198  xfibre1 = (b1cf/lambdaa0_n1^2)*(lambdaa0_n1^d1cf-1);
199  dxfibre1_dlam = (b1cf/lambdaa0_n1^3)*((d1cf-2)*lambdaa0_n1^d1cf + 2);
200  end
201  Fcrossf2 = F*fibres(:,3);
202  lambdaa0_n2 = norm(Fcrossf2);
203  if lambdaa0_n2 > .999
204  xfibre2 = (b1cf/lambdaa0_n2^2)*(lambdaa0_n2^d1cf-1);
205  dxfibre2_dlam = (b1cf/lambdaa0_n2^3)*((d1cf-2)*lambdaa0_n2^d1cf + 2);
206  end
207  a0oa0_2 = sys.a0oa0n1(:,:,fibrenr);
208  a0oa0_3 = sys.a0oa0n2(:,:,fibrenr);
209  end
210 
211  /* % Check if change rate of lambda at a certain point should be tracked */
212  if haveldotpos
213  k = find(ldotpos(1,:) == m & ldotpos(2,:) == gp);
214  if ~isempty(k)
215  Fdot = uvwcomplete(elemidx_v_glob) * dtn;
216  Fdota0 = Fdot*fibres(:,1);
217  /* Also update the current lambda_dot so that
218  * further calls within the getStateJacobian of the
219  * fullmodels.muscle.Dynamics have the correct values! */
220  this.lambda_dot(k) = Fa0^t*Fdota0/lambdaf;
221 
222  /* % Assemble dLdot / du[i] and dLdot / dv[i] */
223  JLamDot = zeros(2*numXYZDofs_pos,1);
224  for eldof = 1:dofsperelem_pos
225  /* U_i^k = e_i dyad dPhik from script */
226  U1k = [dtn(eldof,:); 0 0 0; 0 0 0];
227  U2k = [0 0 0; dtn(eldof,:); 0 0 0];
228  U3k = [0 0 0; 0 0 0; dtn(eldof,:)];
229  idx = (eldof-1)*3 + (1:3);
230  idxv = idx + 3*dofsperelem_pos;
231  /* % x */
232  Ua0 = U1k*fibres(:,1);
233  /* dLdot / du[i]_x */
234  JLamDot(idx(1)) = JLamDot(idx(1)) + Ua0^t*Fdota0;
235 /* JLamDot(idx(1)) = JLamDot(idx(1)) + Ua0'*Fdota0/lambdaf ...
236  * -Fa0'*(Ua0 + Fdota0)/lambdaf^3;
237  * dLdot / dv[i]_x */
238  JLamDot(idxv(1)) = JLamDot(idxv(1)) + Fa0^t*Ua0;
239 
240  /* % y */
241  Ua0 = U2k*fibres(:,1);
242  /* dLdot / du[i]_x */
243  JLamDot(idx(2)) = JLamDot(idx(2)) + Ua0^t*Fdota0;
244 /* JLamDot(idx(2)) = JLamDot(idx(2)) + Ua0'*Fdota0/lambdaf ...
245  * -Fa0'*(Ua0 + Fdota0)/lambdaf^3;
246  * dLdot / dv[i]_x */
247  JLamDot(idxv(2)) = JLamDot(idxv(2)) + Fa0^t*Ua0;
248 
249  /* % z */
250  Ua0 = U3k*fibres(:,1);
251  /* dLdot / du[i]_x */
252  JLamDot(idx(3)) = JLamDot(idx(3)) + Ua0^t*Fdota0;
253 /* JLamDot(idx(3)) = JLamDot(idx(3)) + Ua0'*Fdota0/lambdaf...
254  * -Fa0'*(Ua0 + Fdota0)/lambdaf^3;
255  * dLdot / dv[i]_x */
256  JLamDot(idxv(3)) = JLamDot(idxv(3)) + Fa0^t*Ua0;
257  end
258  ildot = [ildot; k*ones(2*numXYZDofs_pos,1)]; /* #ok */
259 
260  jldot = [jldot; elemidx_u_glob(:); elemidx_v_glob(:)];/* #ok */
261 
262  sldot = [sldot; JLamDot];/* #ok */
263 
264  end
265  end
266  end
267 
268  /* % Main node loop
269  * Precompute weight */
270  weight = fe_pos.GaussWeights(gp) * fe_pos.elem_detjac(m, gp);
271 
272  for k = 1:dofsperelem_pos
273  /* U_i^k = e_i dyad dPhik from script */
274  U1k = [dtn(k,:); 0 0 0; 0 0 0];
275  U2k = [0 0 0; dtn(k,:); 0 0 0];
276  U3k = [0 0 0; 0 0 0; dtn(k,:)];
277 
278  dI1duk = 2*sum([1; 1; 1] * (dtn(k,:) * dtn^t) .* u, 2);
279  fac1 = 2*dI1duk*c01(gp,m);
280  fac2 = 2*(c10(gp,m) + I1*c01(gp,m));
281 
282  /* % grad_u K(u,v,w)
283  * Recall: gradients from nabla K_{u,w} are
284  * negative, as KerMor implements Mu'' = -K(u,v,w)
285  * instead of Mu'' + K(u,v,w) = 0 */
286 
287  /* Assign i index as whole for x,y,z (speed) */
288  i(cur_off + (1:3*numXYZDofs_pos)) = elemidx_v_out_linear3;
289 
290  /* xdim */
291  dFtF1 = U1k" *F + F "*U1k;
292  dPx = -p * (Finv * U1k * Finv)^t...
293  + fac1(1)*F + fac2*U1k...
294  -2*c01(gp,m) * (U1k * C + F*dFtF1);/* #ok<*MINV> */
295 
296  if havefibres
297  dlambda_dux = Fa0^t*U1k*fibres(:,1)/lambdaf;
298  dPx = dPx + (dg_dlam*dlambda_dux*F + g_value*U1k)*a0;
299  if usecrossfibres
300  if lambdaa0_n1 > .999
301  dlambda_dux = Fcrossf1^t*U1k*fibres(:,2)/lambdaa0_n1;
302  dPx = dPx + (dxfibre1_dlam*dlambda_dux*F + xfibre1*U1k)*a0oa0_2;
303  end
304  if lambdaa0_n2 > .999
305  dlambda_dux = Fcrossf2^t*U1k*fibres(:,3)/lambdaa0_n2;
306  dPx = dPx + (dxfibre2_dlam*dlambda_dux*F + xfibre2*U1k)*a0oa0_3;
307  end
308  end
309  end
310  j(cur_off + relidx_pos) = elemidx_u_glob(1,k);
311  snew = -weight * dPx * dtn^t;
312  s(cur_off + relidx_pos) = snew(:);
313  cur_off = cur_off + numXYZDofs_pos;
314 
315  /* ydim */
316  dFtF2 = U2k" *F + F "*U2k;
317  dPy = -p * (Finv * U2k * Finv)^t...
318  +fac1(2)*F + fac2*U2k...
319  -2*c01(gp,m) * (U2k * C + F*dFtF2);
320  if havefibres
321  dlambda_duy = Fa0^t*U2k*fibres(:,1)/lambdaf;
322  dPy = dPy + (dg_dlam*dlambda_duy*F + g_value*U2k)*a0;
323  if usecrossfibres
324  if lambdaa0_n1 > .999
325  dlambda_duy = Fcrossf1^t*U2k*fibres(:,2)/lambdaa0_n1;
326  dPy = dPy + (dxfibre1_dlam*dlambda_duy*F + xfibre1*U2k)*a0oa0_2;
327  end
328  if lambdaa0_n2 > .999
329  dlambda_duy = Fcrossf2^t*U2k*fibres(:,3)/lambdaa0_n2;
330  dPy = dPy + (dxfibre2_dlam*dlambda_duy*F + xfibre2*U2k)*a0oa0_3;
331  end
332  end
333  end
334  j(cur_off + relidx_pos) = elemidx_u_glob(2,k);
335  snew = -weight * dPy * dtn^t;
336  s(cur_off + relidx_pos) = snew(:);
337  cur_off = cur_off + numXYZDofs_pos;
338 
339  /* zdim */
340  dFtF3 = U3k" *F + F "*U3k;
341  dPz = -p * (Finv * U3k * Finv)^t...
342  +fac1(3)*F + fac2*U3k ...
343  - 2*c01(gp,m) * (U3k * C + F*dFtF3);
344  if havefibres
345  dlambda_duz = Fa0^t*U3k*fibres(:,1)/lambdaf;
346  dPz = dPz + (dg_dlam*dlambda_duz*F + g_value*U3k)*a0;
347  if usecrossfibres
348  if lambdaa0_n1 > .999
349  dlambda_duz = Fcrossf1^t*U3k*fibres(:,2)/lambdaa0_n1;
350  dPz = dPz + (dxfibre1_dlam*dlambda_duz*F + xfibre1*U3k)*a0oa0_2;
351  end
352  if lambdaa0_n2 > .999
353  dlambda_duz = Fcrossf2^t*U3k*fibres(:,3)/lambdaa0_n2;
354  dPz = dPz + (dxfibre2_dlam*dlambda_duz*F + xfibre2*U3k)*a0oa0_3;
355  end
356  end
357  end
358  j(cur_off + relidx_pos) = elemidx_u_glob(3,k);
359  snew = -weight * dPz * dtn^t;
360  s(cur_off + relidx_pos) = snew(:);
361  cur_off = cur_off + numXYZDofs_pos;
362 
363  /* % grad_v K(u,v,w)
364  * Viscosity part
365  * if visc > 0
366  * i(cur_off + relidx_pos) = elemidx_velo_linear;
367  * j(cur_off + relidx_pos) = elemidx_velo_XYZ(1,k);
368  * snew = -weight * visc * e1_dyad_dPhik * dtn';
369  * s(cur_off + relidx_pos) = snew(:);
370  * cur_off = cur_off + numXYZDofs_pos;
371  *
372  * % ydim
373  * i(cur_off + relidx_pos) = elemidx_velo_linear;
374  * j(cur_off + relidx_pos) = elemidx_velo_XYZ(2,k);
375  * snew = -weight * visc * e2_dyad_dPhik * dtn';
376  * s(cur_off + relidx_pos) = snew(:);
377  * cur_off = cur_off + numXYZDofs_pos;
378  *
379  * % zdim
380  * i(cur_off + relidx_pos) = elemidx_velo_linear;
381  * j(cur_off + relidx_pos) = elemidx_velo_XYZ(3,k);
382  * snew = -weight * visc * e3_dyad_dPhik * dtn';
383  * s(cur_off + relidx_pos) = snew(:);
384  * cur_off = cur_off + numXYZDofs_pos;
385  * end */
386  end
387 
388  /* % Grad_w K(u,w) */
389  for k = 1:dofsperelem_press
390  i(cur_off + relidx_pos) = elemidx_v_out_linear;
391  j(cur_off + relidx_pos) = elemidx_p_global(k);
392  snew = -weight * fe_press.Ngp(k,gp,m) * Finv" * dtn ";
393  s(cur_off + relidx_pos) = snew(:);
394  cur_off = cur_off + numXYZDofs_pos;
395  end
396 
397  /* % Grad_s K(u,w,s) */
398  if hasforceargument
399  for k = 1:nfibres
400  dPsk = alpha_prefactor * fibretypeweights(gp,k,m) * F * a0;
401  iS(cur_offS + relidx_pos) = elemidx_v_out_linear-size_pos_vec;
402  jS(cur_offS + relidx_pos) = columns_sarco_link(k);
403  snew = -weight * dPsk * dtn^t;
404  sS(cur_offS + relidx_pos) = snew(:);
405  cur_offS = cur_offS + numXYZDofs_pos;
406  end
407  end
408  end
409  end
410  /* Assemble jacobian matrix */
411  JK = sparse(i,j,s,3*N,6*N+pgeo.NumNodes);
412  /* Remove values at dirichlet nodes */
413  JK(:,sys.idx_uv_bc_glob) = [];
414  JK(sys.idx_v_bc_local,:) = [];
415 
416  if this.usemassinv
417  /* Multiply with inverse of Mass matrix! */
418  JK = sys.Minv*JK;
419  end
420 
421  Jalpha = [];
422  if hasforceargument
423  Jalpha = sparse(iS,jS,sS,3*N,nfibres*56);
424  /* Remove those that are connected to dirichlet values */
425  Jalpha([sys.idx_u_bc_glob; sys.idx_v_bc_glob],:) = [];
426  end
427 
428  JLamDot = [];
429  if haveldotpos
430  JLamDot = sparse(ildot,double(jldot),sldot,this.nfibres,6*N);
431  JLamDot(:,sys.idx_uv_bc_glob) = [];
432  end
433 end
434 }
435 
436 };
437 };
* fl(l)
#define F(x, y, z)
Definition: CalcMD5.c:168
function J = getStateJacobianImpl(colvec< double > x,double t)
Default implementation of state jacobians. uses finite differences.
Definition: ACoreFun.m:424