Build your own model class
Todo
Explain how to create a custom model class
When the model is created, it must be parameterized properly. It is explained here how to create your own reference model state.
The model VanOsta2023 is build following this standard. This model is constructed by the following code.
1"""
2VanOsta2023 model.
3
4"""
5
6import circadapt
7import circadapt.plot
8from circadapt.model import Model
9from circadapt.adapt import ModelAdapt
10from circadapt.plot import triseg2022, mmode
11import matplotlib.pyplot as plt
12import numpy as np
13
14class VanOsta2023(Model, ModelAdapt):
15 def __init__(self,
16 solver: str = None,
17 path_to_circadapt: str = None,
18 model_state: dict = None,
19 ):
20 if solver is None:
21 solver = 'backward_differential'
22
23 self._local_save_reference = True
24
25 ModelAdapt.__init__(self)
26 Model.__init__(self,
27 solver,
28 path_to_circadapt=path_to_circadapt,
29 model_state=model_state,
30 )
31
32 def build(self):
33 # Circulation
34 self.add_smart_component('ArtVen', build='SystemicCirculation')
35 self.add_smart_component('ArtVen', build='PulmonaryCirculation')
36 self.add_smart_component('Heart', patch_type='Patch2022')
37 self.add_smart_component('Timings')
38 self.add_smart_component('PressureFlowControl')
39
40 # manually set papillary muscles
41 self.set_component("Peri.RaRv.wPapMus", "Peri.TriSeg.wRv")
42 self.set_component("Peri.LaLv.wPapMus", "Peri.TriSeg.wLv")
43
44 def set_reference(self):
45 self['Chamber2022']['buckling'] = False
46 self['Valve2022']['soft_closure'] = True
47 self['Valve2022']['papillary_muscles'] = True
48
49 self['Solver']['dt'] = 0.001
50 self['Solver']['dt_export'] = 0.002
51 self.set('Solver.order', 2)
52
53 self.set('Model.t_cycle', 0.85)
54
55 self.set('Model.PFC.fac', 0.5)
56 self.set('Model.PFC.epsilon', 0.1)
57 self.set('Model.PFC.fac_pfc', 1)
58 self.set('Model.PFC.stable_threshold', 0.001)
59
60 # Set parameters Circulation
61 self['Tube0D']['A0'] = [0.0004982 , 0.00049959, 0.00045184, 0.00051768]
62 self['Tube0D']['A_wall'] = [1.13597208e-04, 3.79106863e-05, 8.91394588e-05, 4.26698697e-05]
63 self['Tube0D']['k'] = [1.66666667, 2.33333333, 1. , 2.33333333]
64 self['Tube0D']['l'] = [0.4, 0.4, 0.1, 0.1]
65 self['Tube0D']['p0'] = [12154.79898845, 213.26733196, 1913.05480512, 600.72294959]
66
67 self['ArtVen']['p0'] = [6345.26731406, 950. ]
68 self['ArtVen']['q0'] = [4.5e-05, 4.5e-05]
69 self['ArtVen']['k'] = [1. , 1.72]
70
71 # Set volume state variables
72 # not needed to reset, only if initial model crashes
73 if True:
74 self.set('Model.SyArt.V', 2e-4)
75 self.set('Model.PuArt.V', 1e-4)
76 self.set('Model.SyVen.V', 4e-4)
77 self.set('Model.PuVen.V', 2e-4)
78
79 self.set('Model.Peri.TriSeg.V', 56e-6)
80 self.set('Model.Peri.TriSeg.Y', 36e-3)
81
82 self.set('Model.Peri.TriSeg.cLv.V', 150e-6)
83 self.set('Model.Peri.TriSeg.cRv.V', 110e-6)
84 self.set('Model.Peri.La.V', 25e-6)
85 self.set('Model.Peri.Ra.V', 150e-6)
86
87 # all wall parameters
88 self['Patch2022']['l_se'] = 0.04
89 self['Patch2022']['l_s_ref'] = 2.0
90 self['Patch2022']['l_s0'] = 1.8
91 self['Patch2022']['dl_s_pas'] = 0.6
92 self['Patch2022']['k1'] = 10
93 self['Patch2022']['dt'] = 0
94 self['Patch2022']['C_rest'] = 0
95 self['Patch2022']['l_si0'] = 1.51
96 self['Patch2022']['LDAD'] = [1.057, 1.057, 0.64 , 0.64 , 0.64 ]
97 self['Patch2022']['ADO'] = [0.65, 0.65, 0.75, 0.75, 0.75]
98 self['Patch2022']['LDCC'] = [4. , 4. , 3.2, 3.2, 3.2]
99 self['Patch2022']['v_max'] = 7.
100 self['Patch2022']['v_max'][:2] = 14.
101
102 self['Patch2022']['tr'] = [0.4 , 0.4 , 0.24, 0.24, 0.24]
103 self['Patch2022']['td'] = [0.4 , 0.4 , 0.23, 0.23, 0.23]
104
105 # wall specific
106 self['Patch2022']['Sf_act'] = [80e3, 80e3, 120e3, 120e3, 120e3]
107 self['Patch2022']['Am_ref'] = [0.00458522, 0.00381765, 0.00806997, 0.00454307, 0.01176514]
108 self['Patch2022']['V_wall'] = [2.75050615e-05, 1.25959326e-05, 8.80910385e-05, 3.46281364e-05,
109 5.16086110e-05]
110 self['Patch2022']['Sf_pas'] = [ 16.51117993, 17.0639141 , 580.39235927, 569.67392472,
111 606.50514861]
112
113 # Valves
114 self['Valve2022']['adaptation_A_open_fac'] = [1. , 1.11, 1. , 1. , 1.11, 1. ]
115 self['Valve2022']['A_open'] = [0.00050042, 0.00050203, 0.00045228, 0.00051764, 0.00055321,
116 0.00049838]
117 self['Valve2022']['A_leak'] = [2.64705882e-04, 2.64705882e-10, 2.64705882e-10, 2.64705882e-04,
118 2.64705882e-10, 2.64705882e-10]
119 self['Valve2022']['l'] = 0.01626978
120 self['Valve2022']['rho_b'] = 1050
121 self['Valve2022']['papillary_muscles'] = True
122 self['Valve2022']['papillary_muscles_slope'] = 100
123 self['Valve2022']['papillary_muscles_min'] = 0.1
124 self['Valve2022']['papillary_muscles_A_open_fac'] = 0.1
125 self['Valve2022']['soft_closure'] = True
126
127 self['Bag']['k'] = 10
128 self['Bag']['V_ref'] = [0.00051968]
129 self['Bag']['p_ref'] = 100
130
131 self.set('Model.Peri.TriSeg.Y', 0.035)
132
133 self['Timings']['law_tauAv'] = 2
134 self['Timings']['c_tauAv0'] = 0.172
135 self['Timings']['c_tauAv1'] = -0.485*60e-3
136
137 # Adaptation
138 self['Patch2022']['adapt_gamma'] = 0.5
139 self.set('Solver.store_beats', 1)
140
141 self['PressureFlowControl']['stable_threshold'] = 1e-3
142
143 self['Patch2022']['SfPasMaxT'] = [6400., 6400., 6600., 6600., 6600.]
144 self['Patch2022']['FacSfActT'] = [0.44, 0.44, 0.61, 0.61, 0.61]
145 self['Patch2022']['SfPasActT'] = [4800., 4800., 6600., 6600., 6600.]
146 self['Patch2022']['LsPasActT'] = [3. , 3. , 2.23, 2.23, 2.23]
147
148 self.run(stable=True)
149
150 return
151
152
153 options = self.get_adapt_options()
154 self['General']['q0'] = options['exercise']['q0']
155 self['General']['t_cycle'] = options['exercise']['t_cycle']
156 self.run(stable=True)
157
158 reference_y = np.array([
159 self['Patch2022']['SfEcmMax'],
160 self['Patch2022']['SfActMax'],
161 self['Patch2022']['SfPasAct'],
162 self['Patch2022']['LsPasAct'],
163 ]).T
164
165 targets = np.array([
166 np.mean(reference_y[:2, :], axis=0),
167 np.mean(reference_y[2:, :], axis=0),
168 ])
169 targets[:, 1] /= self['Patch2022']['Sf_act'][:][[0, 2]]
170
171 # targets = np.array(
172 # [[5.5e+05, 1.9e-01, 3.5e+03, 2.2e+00],
173 # [6.0e+03, 4.9e-01, 4.0e+03, 2.3e+00],
174 # ])
175
176 self['Patch2022']['SfPasMaxT'] = targets[[0, 0, 1, 1, 1], 0]
177 self['Patch2022']['FacSfActT'] = targets[[0, 0, 1, 1, 1], 1]
178 self['Patch2022']['SfPasActT'] = targets[[0, 0, 1, 1, 1], 2]
179 self['Patch2022']['LsPasActT'] = targets[[0, 0, 1, 1, 1], 3]
180
181 self['Patch2022']['adapt_gamma'] = 0.1
182 self.adapt(verbose=True)
183 self['Patch2022']['adapt_gamma'] = 0.5
184 self.adapt(verbose=True)
185
186 # Set adaptation constants
187 self.calculate_and_set_matrix(verbose=True)
188
189 # set resting state
190 self['General']['q0'] = options['rest']['q0']
191 self['General']['t_cycle'] = options['rest']['t_cycle']
192 self.run(stable=True)
193
194 def get_unittest_targets(self):
195 """Hardcoded results after initializing and running 1 beat."""
196 return {
197 'LVEDV': 119.7,
198 'LVESV': 47.2,
199 }
200
201 def get_unittest_results(self, model):
202 """Real-time results after initializing and running 1 beat."""
203 LVEDV = np.max(model['Cavity']['V'][:, 'cLv'])*1e6
204 LVESV = np.min(model['Cavity']['V'][:, 'cLv'])*1e6
205 return {
206 'LVEDV': LVEDV,
207 'LVESV': LVESV,
208 }
209
210 def plot(self, fig=None):
211 # TODO
212 self.plot_extended(fig)
213
214 def plot_extended(self, fig=None):
215 if fig is None:
216 fig = 1
217 if isinstance(fig, int):
218 fig = plt.figure(fig, clear=True, figsize=(12, 8))
219
220 # Settings
221 grid_size = [32, 32]
222
223 def get_lim(module, signal, locs=slice(None, None, None)):
224 signal = self[module][signal][:, locs]
225 lim = np.array([np.min(signal), np.max(signal)])
226 lim += np.array([-1, 1]) * 0.1*np.diff(lim)
227 return lim
228
229 lim_V = get_lim('Cavity', 'V', ['cRv', 'Ra', 'La', 'cLv']) * 1e6
230 lim_V[0] = 0
231 lim_p = get_lim('Cavity', 'p', ['cRv', 'Ra', 'La', 'cLv']) / 133
232 lim_p[0] = np.min([lim_p[0], 0])
233 lim_Ls = get_lim('Patch2022', 'l_s')
234 lim_Sf = get_lim('Patch2022', 'Sf') * 1e-3
235 lim_q = get_lim('Valve2022', 'q',
236 ['LaLv', 'RaRv', 'LvSyArt', 'RaPuArt']) * 1e6
237
238 all_lim = [lim_V, lim_p, lim_Ls, lim_Sf, lim_q]
239 if (np.any(np.isnan(all_lim)) or np.any(np.isinf(all_lim))):
240 lim_V = [0, 200]
241 lim_p = [0, 150]
242 lim_Ls = [1.5, 2.0]
243 lim_Sf = [0, 100]
244 lim_q = [-1e-3, 1e-3]
245
246 # Pressure Volume plot
247 axPV = plt.subplot2grid(grid_size, (0, 17), rowspan=15, colspan=15, fig=fig)
248 axPV.plot(self['Cavity']['V'][:, 'cLv']*1e6, self['Cavity']['p'][:, 'cLv']/133)
249 axPV.plot(self['Cavity']['V'][:, 'cRv']*1e6, self['Cavity']['p'][:, 'cRv']/133)
250 axPV.plot(self['Cavity']['V'][:, 'La']*1e6, self['Cavity']['p'][:, 'La']/133)
251 axPV.plot(self['Cavity']['V'][:, 'Ra']*1e6, self['Cavity']['p'][:, 'Ra']/133)
252 axPV.spines[['top', 'right']].set_visible(False)
253 axPV.set_title('Pressure-Volume loop', weight='bold')
254 axPV.set_xlabel('Volume [mL]')
255 axPV.set_ylabel('Pressure [mmHg]')
256 axPV.spines[['bottom', 'left']].set_position(('outward', 5))
257
258 ylabel_x_left = -0.25
259 ylabel_x_right = 1.25
260
261 # Volumes
262 t = self['Solver']['t']*1e3
263 t -= t[0]
264
265 axVRv = plt.subplot2grid(grid_size, (0, 0), rowspan=8, colspan=6, fig=fig)
266 axVRv.plot(t, self['Cavity']['V'][:, 'cRv']*1e6)
267 axVRv.plot(t, self['Cavity']['V'][:, 'Ra']*1e6)
268 axVRv.set_ylim(lim_V)
269 axVRv.set_ylabel('Volume\n[mL]')
270 axVRv.spines[['top', 'right']].set_visible(False)
271 axVRv.set_title('Right Heart')
272 # axVRv.set_xticks([])
273 axVRv.tick_params(axis='both', direction='in')
274 axVRv.yaxis.set_label_coords(ylabel_x_left, 0.5)
275
276
277 axVLv = plt.subplot2grid(grid_size, (0, 6), rowspan=8, colspan=6, fig=fig)
278 axVLv.plot(t, self['Cavity']['V'][:, 'cLv']*1e6)
279 axVLv.plot(t, self['Cavity']['V'][:, 'La']*1e6)
280 axVLv.set_ylabel('Volume\n[mL]')
281 axVLv.set_ylim(lim_V)
282 axVLv.yaxis.set_ticks_position('right')
283 axVLv.yaxis.set_label_position('right')
284 axVLv.spines['right'].set_position(('outward', 0))
285 axVLv.spines[['top', 'left']].set_visible(False)
286 axVLv.set_title('Left Heart')
287 # axVLv.set_xticks([])
288 axVLv.tick_params(axis='both', direction='in')
289 axVLv.yaxis.set_label_coords(ylabel_x_right, 0.5)
290
291 # Pressures
292 axpRv = plt.subplot2grid(grid_size, (8, 0), rowspan=8, colspan=6, fig=fig)
293 axpRv.plot(t, self['Cavity']['p'][:, 'cRv']/133)
294 axpRv.plot(t, self['Cavity']['p'][:, 'Ra']/133)
295 axpRv.plot(t, self['Cavity']['p'][:, 'PuArt']/133)
296 axpRv.spines[['top', 'right']].set_visible(False)
297 # axpRv.set_xticks([])
298 axpRv.tick_params(axis='both', direction='in')
299 axpRv.set_ylim(lim_p)
300 axpRv.set_ylabel('Pressure\n[mmHg]')
301 axpRv.yaxis.set_label_coords(ylabel_x_left, 0.5)
302
303 axpLv = plt.subplot2grid(grid_size, (8, 6), rowspan=8, colspan=6, fig=fig)
304 axpLv.plot(t, self['Cavity']['p'][:, 'cLv']/133)
305 axpLv.plot(t, self['Cavity']['p'][:, 'La']/133)
306 axpLv.plot(t, self['Cavity']['p'][:, 'SyArt']/133)
307 axpLv.yaxis.set_ticks_position('right')
308 axpLv.yaxis.set_label_position('right')
309 axpLv.spines['right'].set_position(('outward', 0))
310 axpLv.spines[['top', 'left']].set_visible(False)
311 # axpLv.set_xticks([])
312 axpLv.tick_params(axis='both', direction='in')
313 axpLv.set_ylim(lim_p)
314 axpLv.set_ylabel('Pressure\n[mmHg]')
315 axpLv.yaxis.set_label_coords(ylabel_x_right, 0.5)
316
317 # Valves
318 ax = plt.subplot2grid(grid_size, (16, 0), rowspan=6, colspan=6, fig=fig)
319 ax.plot(t, self['Valve2022']['q'][:, 'RaRv']*1e6)
320 ax.plot(t, self['Valve2022']['q'][:, 'RvPuArt']*1e6)
321 ax.spines[['top', 'right']].set_visible(False)
322 ax.set_ylim(lim_q)
323 # ax.set_xticks([])
324 ax.set_ylabel('Flow\n[mL/s]')
325 ax.yaxis.set_label_coords(ylabel_x_left, 0.5)
326
327 ax = plt.subplot2grid(grid_size, (16, 6), rowspan=6, colspan=6, fig=fig)
328 ax.plot(t, self['Valve2022']['q'][:, 'LaLv']*1e6)
329 ax.plot(t, self['Valve2022']['q'][:, 'LvSyArt']*1e6)
330 ax.spines[['top', 'left']].set_visible(False)
331 ax.set_ylim(lim_q)
332 ax.yaxis.set_ticks_position('right')
333 ax.yaxis.set_label_position('right')
334 # ax.set_xticks([])
335 ax.set_ylabel('Flow\n[mL/s]')
336 ax.yaxis.set_label_coords(ylabel_x_right, 0.5)
337
338 # Stress
339 ax = plt.subplot2grid(grid_size, (22, 0), rowspan=4, colspan=6, fig=fig)
340 ax.plot(t, self['Patch2022']['Sf'][:, 'pRv0']*1e-3)
341 ax.plot(t, self['Patch2022']['Sf'][:, 'pRa0']*1e-3)
342 ax.spines[['top', 'right']].set_visible(False)
343 # ax.set_xticks([])
344 ax.set_ylim(lim_Sf)
345 ax.set_ylabel('Total\nstress [kPa]')
346 ax.yaxis.set_label_coords(ylabel_x_left, 0.5)
347
348 ax = plt.subplot2grid(grid_size, (22, 6), rowspan=4, colspan=6, fig=fig)
349 ax.plot(t, self['Patch2022']['Sf'][:, 'pLv0']*1e-3)
350 ax.plot(t, self['Patch2022']['Sf'][:, 'pSv0']*1e-3)
351 ax.plot(t, self['Patch2022']['Sf'][:, 'pLa0']*1e-3)
352 ax.spines[['top', 'left']].set_visible(False)
353 ax.yaxis.set_ticks_position('right')
354 ax.yaxis.set_label_position('right')
355 # ax.set_xticks([])
356 ax.set_ylim(lim_Sf)
357 ax.set_ylabel('Total\nstress [kPa]')
358 ax.yaxis.set_label_coords(ylabel_x_right, 0.5)
359
360 # Sarcomere Length
361 ax = plt.subplot2grid(grid_size, (26, 0), rowspan=6, colspan=6, fig=fig)
362 ax.plot(t, self['Patch2022']['l_s'][:, 'pRv0'])
363 ax.plot(t, self['Patch2022']['l_s'][:, 'pRa0'])
364 ax.spines[['top', 'right']].set_visible(False)
365 ax.spines['bottom'].set_position(('outward', 5))
366 ax.set_ylim(lim_Ls)
367 ax.set_ylabel('Sarcomere\nlength [$\mu$m]')
368 ax.yaxis.set_label_coords(ylabel_x_left, 0.5)
369
370 ax = plt.subplot2grid(grid_size, (26, 6), rowspan=6, colspan=6, fig=fig)
371 ax.plot(t, self['Patch2022']['l_s'][:, 'pLv0'])
372 ax.plot(t, self['Patch2022']['l_s'][:, 'pSv0'])
373 ax.plot(t, self['Patch2022']['l_s'][:, 'pLa0'])
374 ax.spines[['top', 'left']].set_visible(False)
375 ax.spines['bottom'].set_position(('outward', 5))
376 ax.yaxis.set_ticks_position('right')
377 ax.yaxis.set_label_position('right')
378 ax.set_ylim(lim_Ls)
379 ax.set_ylabel('Sarcomere\nlength [$\mu$m]')
380 ax.yaxis.set_label_coords(ylabel_x_right, 0.5)
381
382 # ax.set_xlabel('Time [ms]')
383 # ax.xaxis.set_label_coords(0, -0.3)
384
385
386 # Plot TriSeg
387 titles = ['Pre-A', 'Onset QRS', 'Peak LV \n pressure', 'AV close']
388 idx = [0,
389 np.argmax(np.diff(self['Patch2022']['C'][:, 'pLv0'])>0),
390 np.argmax(self['Cavity']['p'][:, 'cLv']),
391 len(t) - 1 - np.argmax(
392 np.diff(self['Valve2022']['q'][:, 'LvSyArt'][::-1])>0)
393 ]
394
395 for i in range(4):
396 ax = plt.subplot2grid(grid_size, (26, 16+4*i),
397 rowspan=5, colspan=4, fig=fig)
398 triseg2022(self, ax, idx[i])
399 ax.spines[['top', 'right', 'bottom', 'left']].set_visible(False)
400 ax.set_xticks([])
401 ax.set_yticks([])
402 plt.xlabel(titles[i], fontsize=12)
403
404 # Plot settings
405 plt.subplots_adjust(
406 top=0.96,
407 bottom=0.05,
408 left=0.075,
409 right=0.98,
410 hspace=5,
411 wspace=0.5)
412 plt.draw()
413
414 # Plot MMode
415 ax_mmode = plt.subplot2grid(grid_size, (17, 17),
416 rowspan=8, colspan=15, fig=fig)
417 circadapt.plot.triseg.mmode(self, ax_mmode)
418 ax_mmode.axhline(0, c='k', ls='--')
419 ax_mmode.spines[['top', 'right']].set_visible(False)
420
421 # Plot Y
422 # ax_mmode = plt.subplot2grid(grid_size, (17, 25),
423 # rowspan=8, colspan=7, fig=fig)
424 ax_mmode.plot(t, self['TriSeg2022']['Y']*1e3 * np.array([[1, -1]]), c='k')
425 ax_mmode.spines[['top', 'right']].set_visible(False)
426 plt.ylabel('MMode and Y [mm]')
427
428
429class VanOsta2023_2306(VanOsta2023):
430 def set_reference(self):
431 self['Chamber2022']['buckling'] = False
432 self['Valve2022']['soft_closure'] = True
433
434 self['Solver']['dt'] = 0.0005
435 self['Solver']['dt_export'] = self['Solver']['dt']
436
437 self.set('Model.t_cycle', 0.85)
438
439 self.set('Model.PFC.fac', 0.5)
440 self.set('Model.PFC.epsilon', 0.1)
441 self.set('Model.PFC.fac_pfc', 1)
442 self.set('Model.PFC.stable_threshold', 0.001)
443
444 # Set parameters Circulation
445 self['Tube0D']['A0'] = [
446 0.00049833,
447 0.00050034,
448 0.0004684 ,
449 0.00051849,
450 ]
451 self['Tube0D']['A_wall'] = [
452 1.14408188e-04,
453 4.81082964e-05,
454 5.19472921e-05,
455 5.79933632e-05,
456 ]
457 self['Tube0D']['k'] = np.array([ 8., 10., 8., 10.]) / 3 - 1
458 self['Tube0D']['l'] = [0.4, 0.4, 0.2, 0.2]
459 self['Tube0D']['p0'] = [
460 12161.21763497,
461 112.09788908,
462 1899.95009955,
463 572.39790382,
464 ]
465
466 self['ArtVen']['p0'] = [6395.43973044, 500.]
467 self['ArtVen']['q0'] = [4.5e-05, 4.5e-05]
468 self['ArtVen']['k'] = [1, 2]
469
470 # Set volume state variables
471 # not needed to reset, only if initial model crashes
472 if True:
473 self.set('Model.SyArt.V', 2e-4)
474 self.set('Model.PuArt.V', 1e-4)
475 self.set('Model.SyVen.V', 4e-4)
476 self.set('Model.PuVen.V', 2e-4)
477
478 self.set('Model.Peri.TriSeg.V', 44e-6)
479 self.set('Model.Peri.TriSeg.Y', 34.6e-3)
480
481 self.set('Model.Peri.TriSeg.cLv.V', 150e-6)
482 self.set('Model.Peri.TriSeg.cRv.V', 100e-6)
483 self.set('Model.Peri.La.V', 100e-6)
484 self.set('Model.Peri.Ra.V', 50e-6)
485
486 # all wall parameters
487 self['Patch2022']['l_se'] = 0.04
488 self['Patch2022']['l_s_ref'] = 2.0
489 self['Patch2022']['l_s0'] = 1.8
490 self['Patch2022']['dl_s_pas'] = 0.6
491 self['Patch2022']['k1'] = 10
492 self['Patch2022']['dt'] = 0
493 self['Patch2022']['C_rest'] = 0
494 self['Patch2022']['l_si0'] = 1.51
495 self['Patch2022']['LDAD'] = 1.057
496 self['Patch2022']['ADO'] = 0.65
497 self['Patch2022']['LDCC'] = 4.
498 self['Patch2022']['v_max'] = 7.
499 self['Patch2022']['v_max'][:2] = 14.
500
501 self['Patch2022']['tr'] = 0.25
502 self['Patch2022']['td'] = 0.25
503 self['Patch2022']['tr'][:2] = 0.4
504 self['Patch2022']['td'][:2] = 0.4
505
506 # wall specific
507 self['Patch2022']['Am_ref'] = [
508 0.00706159,
509 0.00603949,
510 0.0093191 ,
511 0.00507053,
512 0.01313792,
513 ]
514 self['Patch2022']['V_wall'] = [
515 1.86518494e-05,
516 6.12511827e-06,
517 9.51121820e-05,
518 3.74835076e-05,
519 4.97478018e-05,
520 ]
521 self['Patch2022']['Sf_pas'] = np.array([
522 51591.64007141,
523 52277.48834349,
524 22370.46712926,
525 22051.80366169,
526 23278.22158555,
527 ]) * 0.0349
528 self['Patch2022']['Sf_act'] = [84e3, 84e3, 120e3, 120e3, 120e3]
529
530 # Valves
531 self['Valve2022']['adaptation_A_open_fac'] = [
532 1.,
533 1.5,
534 1.,
535 1.,
536 1.5,
537 1.]
538 self['Valve2022']['A_open'] = [
539 0.00050078,
540 0.0007021,
541 0.00046806,
542 0.00051776,
543 0.00074755,
544 0.00049837]
545 self['Valve2022']['A_leak'] = [
546 2.64705882e-04,
547 2.64705882e-10,
548 2.64705882e-10,
549 2.64705882e-04,
550 2.64705882e-10,
551 2.64705882e-10]
552 self['Valve2022']['l'] = 0.01626978
553 self['Valve2022']['rho_b'] = 1050
554 self['Valve2022']['papillary_muscles'] = False
555 self['Valve2022']['papillary_muscles_slope'] = 100
556 self['Valve2022']['papillary_muscles_min'] = 0.1
557 self['Valve2022']['papillary_muscles_A_open_fac'] = 0.1
558 self['Valve2022']['soft_closure'] = True
559
560 self['Bag']['k'] = 10
561 self['Bag']['V_ref'] = 0.0005
562 self['Bag']['p_ref'] = 100
563
564 self.set('Model.Peri.TriSeg.Y', 0.035)
565
566 self['Timings']['law_tauAv'] = 2
567 self['Timings']['c_tauAv0'] = 0.2
568 self['Timings']['c_tauAv1'] = -0.485*60e-3
569
570 # Adaptation
571 self['Patch2022']['adapt_gamma'] = 0.75
572
573 self.run(stable=True)
574
575 def get_unittest_targets(self):
576 """Hardcoded results after initializing and running 1 beat."""
577 return {
578 'LVEDV': 141.6,
579 'LVESV': 69.4,
580 }