pyfebio 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pyfebio might be problematic. Click here for more details.

pyfebio/material.py ADDED
@@ -0,0 +1,1191 @@
1
+ from typing import Annotated, Literal, TypeAlias
2
+
3
+ from pydantic import AfterValidator, Field, PositiveInt
4
+ from pydantic.types import NonNegativeFloat
5
+ from pydantic_xml import BaseXmlModel, attr, element
6
+
7
+ from ._types import StringFloatVec3, StringFloatVec9
8
+
9
+
10
+ class MaterialAxisVector(BaseXmlModel, validate_assignment=True, extra="forbid"):
11
+ type: Literal["vector"] = attr(default="vector", frozen=True)
12
+ a: StringFloatVec3 = element(default="1.0,0.0,0.0")
13
+ d: StringFloatVec3 = element(default="0.0,1.0,0.0")
14
+
15
+
16
+ class FiberVector(BaseXmlModel, validate_assignment=True, extra="forbid"):
17
+ type: Literal["vector"] = attr(default="vector", frozen=True)
18
+ text: StringFloatVec3 = "1.0,0.0,0.0"
19
+
20
+
21
+ class MaterialParameter(BaseXmlModel, validate_assignment=True, extra="forbid"):
22
+ type: Literal["map", "math"] | None = attr(default=None)
23
+ text: float | int | str = Field(union_mode="left_to_right")
24
+
25
+
26
+ class DynamicMaterialParameter(BaseXmlModel, validate_assignment=True, extra="forbid"):
27
+ type: Literal["map", "math"] | None = attr(default=None)
28
+ lc: int = attr(default=1, ge=1)
29
+ text: float | int | str = Field(union_mode="left_to_right")
30
+
31
+
32
+ # Material Paramter Validators
33
+ def mat_is_positive_float(parameter: MaterialParameter) -> MaterialParameter:
34
+ if parameter.type == "map" or parameter.type == "math":
35
+ if not isinstance(parameter.text, str):
36
+ raise ValueError(
37
+ f"MaterialParameter {parameter.type=}, which requires parameter.text to be of type(str), but {parameter.text=}."
38
+ )
39
+ return parameter
40
+ elif isinstance(parameter.text, float | int):
41
+ if parameter.text <= 0.0:
42
+ raise ValueError(f"{parameter.text=} must be greater than 0.0")
43
+ return parameter
44
+ else:
45
+ raise ValueError(f"{parameter.text=} of type(str) but {parameter.type=} when it must be 'map' or 'math'")
46
+
47
+
48
+ def mat_is_non_negative_float(parameter: MaterialParameter) -> MaterialParameter:
49
+ if parameter.type == "map" or parameter.type == "math":
50
+ if not isinstance(parameter.text, str):
51
+ raise ValueError(
52
+ f"MaterialParameter {parameter.type=}, which requires parameter.text to be of type(str), but {parameter.text=}."
53
+ )
54
+ return parameter
55
+ elif isinstance(parameter.text, float | int):
56
+ if parameter.text < 0.0:
57
+ raise ValueError(f"{parameter.text=} must be greater than or equal to 0.0")
58
+ return parameter
59
+ else:
60
+ raise ValueError(f"{parameter.text=} of type(str) but {parameter.type=} when it must be 'map' or 'math'")
61
+
62
+
63
+ def mat_is_gte_one_float(parameter: MaterialParameter) -> MaterialParameter:
64
+ if parameter.type == "map" or parameter.type == "math":
65
+ if not isinstance(parameter.text, str):
66
+ raise ValueError(
67
+ f"MaterialParameter {parameter.type=}, which requires parameter.text to be of type(str), but {parameter.text=}."
68
+ )
69
+ return parameter
70
+ elif isinstance(parameter.text, float | int):
71
+ if parameter.text < 1.0:
72
+ raise ValueError(f"{parameter.text=} must be greater than or equal to 1.0")
73
+ return parameter
74
+ else:
75
+ raise ValueError(f"{parameter.text=} of type(str) but {parameter.type=} when it must be 'map' or 'math'")
76
+
77
+
78
+ def mat_is_gt_one_float(parameter: MaterialParameter) -> MaterialParameter:
79
+ if parameter.type == "map" or parameter.type == "math":
80
+ if not isinstance(parameter.text, str):
81
+ raise ValueError(
82
+ f"MaterialParameter {parameter.type=}, which requires parameter.text to be of type(str), but {parameter.text=}."
83
+ )
84
+ return parameter
85
+ elif isinstance(parameter.text, float | int):
86
+ if parameter.text <= 1.0:
87
+ raise ValueError(f"{parameter.text=} must be greater than 1.0")
88
+ return parameter
89
+ else:
90
+ raise ValueError(f"{parameter.text=} of type(str) but {parameter.type=} when it must be 'map' or 'math'")
91
+
92
+
93
+ def mat_is_gte_two_float(parameter: MaterialParameter) -> MaterialParameter:
94
+ if parameter.type == "map" or parameter.type == "math":
95
+ if not isinstance(parameter.text, str):
96
+ raise ValueError(
97
+ f"MaterialParameter {parameter.type=}, which requires parameter.text to be of type(str), but {parameter.text=}."
98
+ )
99
+ return parameter
100
+ elif isinstance(parameter.text, float | int):
101
+ if parameter.text < 2.0:
102
+ raise ValueError(f"{parameter.text=} must be greater than or equal to 2.0")
103
+ return parameter
104
+ else:
105
+ raise ValueError(f"{parameter.text=} of type(str) but {parameter.type=} when it must be 'map' or 'math'")
106
+
107
+
108
+ def mat_is_lte_onethird_gte_zero(parameter: MaterialParameter) -> MaterialParameter:
109
+ if parameter.type == "map" or parameter.type == "math":
110
+ if not isinstance(parameter.text, str):
111
+ raise ValueError(
112
+ f"MaterialParameter {parameter.type=}, which requires parameter.text to be of type(str), but {parameter.text=}."
113
+ )
114
+ return parameter
115
+ elif isinstance(parameter.text, float | int):
116
+ if parameter.text < 0.0 or parameter.text > 1.0 / 3.0:
117
+ raise ValueError(f"{parameter.text=} must be in domain [0.0, 1./3.]")
118
+ return parameter
119
+ else:
120
+ raise ValueError(f"{parameter.text=} of type(str) but {parameter.type=} when it must be 'map' or 'math'")
121
+
122
+
123
+ def mat_is_lte_90_gte_0(parameter: MaterialParameter) -> MaterialParameter:
124
+ if parameter.type == "map" or parameter.type == "math":
125
+ if not isinstance(parameter.text, str):
126
+ raise ValueError(
127
+ f"MaterialParameter {parameter.type=}, which requires parameter.text to be of type(str), but {parameter.text=}."
128
+ )
129
+ return parameter
130
+ elif isinstance(parameter.text, float | int):
131
+ if parameter.text < 0.0 or parameter.text > 90.0:
132
+ raise ValueError(f"{parameter.text=} must be in domain [0.0, 90.0]")
133
+ return parameter
134
+ else:
135
+ raise ValueError(f"{parameter.text=} of type(str) but {parameter.type=} when it must be 'map' or 'math'")
136
+
137
+
138
+ def mat_is_positive_int(parameter: MaterialParameter) -> MaterialParameter:
139
+ if parameter.type == "map" or parameter.type == "math":
140
+ if not isinstance(parameter.text, str):
141
+ raise ValueError(
142
+ f"MaterialParameter {parameter.type=}, which requires parameter.text to be of type(str), but {parameter.text=}."
143
+ )
144
+ return parameter
145
+ elif isinstance(parameter.text, float):
146
+ raise ValueError(f"{parameter.text=} must be type(int)")
147
+ elif isinstance(parameter.text, int):
148
+ if parameter.text < 1:
149
+ raise ValueError(f"{parameter.text=} must be greater than 0")
150
+ return parameter
151
+ else:
152
+ raise ValueError(f"{parameter.text=} of type(str) but {parameter.type=} when it must be 'map' or 'math'")
153
+
154
+
155
+ def mat_is_positive_int_mult10(parameter: MaterialParameter) -> MaterialParameter:
156
+ if parameter.type == "map" or parameter.type == "math":
157
+ if not isinstance(parameter.text, str):
158
+ raise ValueError(
159
+ f"MaterialParameter {parameter.type=}, which requires parameter.text to be of type(str), but {parameter.text=}."
160
+ )
161
+ return parameter
162
+ elif isinstance(parameter.text, float):
163
+ raise ValueError(f"{parameter.text=} must be type(int)")
164
+ elif isinstance(parameter.text, int):
165
+ if parameter.text % 10 != 0 and parameter.text > 0:
166
+ raise ValueError(f"{parameter.text=} must be a multiple of 10 and greater than 0")
167
+ return parameter
168
+ else:
169
+ raise ValueError(f"{parameter.text=} of type(str) but {parameter.type=} when it must be 'map' or 'math'")
170
+
171
+
172
+ def mat_is_string_float_vec3(parameter: MaterialParameter) -> MaterialParameter:
173
+ if parameter.type == "map" or parameter.type == "math":
174
+ if not isinstance(parameter.text, str):
175
+ raise ValueError(
176
+ f"MaterialParameter {parameter.type=}, which requires parameter.text to be of type(str), but {parameter.text=}."
177
+ )
178
+ return parameter
179
+ elif parameter.text is StringFloatVec3:
180
+ return parameter
181
+ else:
182
+ raise ValueError(f"{parameter.text=} must be of type(StringFloatVec3)")
183
+
184
+
185
+ def mat_is_string_float_vec9(parameter: MaterialParameter) -> MaterialParameter:
186
+ if parameter.type == "map" or parameter.type == "math":
187
+ if not isinstance(parameter.text, str):
188
+ raise ValueError(
189
+ f"MaterialParameter {parameter.type=}, which requires parameter.text to be of type(str), but {parameter.text=}."
190
+ )
191
+ return parameter
192
+ elif parameter.text is StringFloatVec9:
193
+ return parameter
194
+ else:
195
+ raise ValueError(f"{parameter.text=} must be of type(StringFloatVec9)")
196
+
197
+
198
+ MatPositiveFloat: TypeAlias = Annotated[MaterialParameter, AfterValidator(mat_is_positive_float)]
199
+ MatNonNegativeFloat: TypeAlias = Annotated[MaterialParameter, AfterValidator(mat_is_non_negative_float)]
200
+ MatGTEOneFloat: TypeAlias = Annotated[MaterialParameter, AfterValidator(mat_is_gte_one_float)]
201
+ MatGTOneFloat: TypeAlias = Annotated[MaterialParameter, AfterValidator(mat_is_gt_one_float)]
202
+ MatGTETwoFloat: TypeAlias = Annotated[MaterialParameter, AfterValidator(mat_is_gte_two_float)]
203
+ MatLTE_OneThird_GTE_Zero: TypeAlias = Annotated[MaterialParameter, AfterValidator(mat_is_lte_onethird_gte_zero)]
204
+ MatLTE_90_GTE_0: TypeAlias = Annotated[MaterialParameter, AfterValidator(mat_is_lte_90_gte_0)]
205
+ MatPositiveInt: TypeAlias = Annotated[MaterialParameter, AfterValidator(mat_is_positive_int)]
206
+ MatPositiveIntMult10: TypeAlias = Annotated[MaterialParameter, AfterValidator(mat_is_positive_int_mult10)]
207
+ MatStringFloatVec3: TypeAlias = Annotated[MaterialParameter, AfterValidator(mat_is_string_float_vec3)]
208
+ MatStringFloatVec9: TypeAlias = Annotated[MaterialParameter, AfterValidator(mat_is_string_float_vec9)]
209
+
210
+
211
+ class MaterialBase(BaseXmlModel, tag="material", extra="forbid"):
212
+ name: str | None = attr(default=None)
213
+ id: int | None = attr(default=None)
214
+ density: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
215
+
216
+
217
+ class MaterialBaseNoDensity(BaseXmlModel, tag="solid", extra="forbid"):
218
+ name: str | None = attr(default=None)
219
+ id: int | None = attr(default=None)
220
+
221
+
222
+ class ActiveContraction(BaseXmlModel, tag="active_contraction", extra="forbid"):
223
+ type: Literal["active contraction"] = attr(default="active contraction", frozen=True)
224
+ ascl: DynamicMaterialParameter = element(default=DynamicMaterialParameter(text=1.0))
225
+ ca0: MatPositiveFloat = element(default=MaterialParameter(text=4.35))
226
+ beta: MatPositiveFloat = element(default=MaterialParameter(text=4.75))
227
+ l0: MatPositiveFloat = element(default=MaterialParameter(text=1.58))
228
+ refl: MatPositiveFloat = element(default=MaterialParameter(text=2.04))
229
+
230
+
231
+ class SolidBoundMolecule(BaseXmlModel, tag="solid_bound", extra="forbid"):
232
+ sbm: int = attr(default=1)
233
+ rho0: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
234
+ rhomin: MatPositiveFloat = element(default=MaterialParameter(text=0.1))
235
+ rhomax: MatPositiveFloat = element(default=MaterialParameter(text=5.0))
236
+
237
+
238
+ class ArrudaBoyce(MaterialBase, tag="material", extra="forbid"):
239
+ type: Literal["Arruda-Boyce unconstrained"] = attr(default="Arruda-Boyce unconstrained", frozen=True)
240
+ ksi: MatPositiveFloat = element(default=MaterialParameter(text=10.0))
241
+ N: MatPositiveInt = element(default=MaterialParameter(text=5))
242
+ n_term: int = element(default=3, ge=3, le=30)
243
+ kappa: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
244
+
245
+
246
+ class CarterHayes(MaterialBase, tag="solid", extra="forbid"):
247
+ type: Literal["Carter-Hayes"] = attr(default="Carter-Hayes", frozen=True)
248
+ E0: MatPositiveFloat = element(default=MaterialParameter(text=10000.0))
249
+ rho0: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
250
+ gamma: MatPositiveFloat = element(default=MaterialParameter(text=2.0))
251
+ v: MatNonNegativeFloat = element(default=MaterialParameter(text=0.3))
252
+ sbm: MatPositiveInt = element(default=MaterialParameter(text=1))
253
+
254
+
255
+ class CellGrowth(MaterialBase, tag="material", extra="forbid"):
256
+ type: Literal["cell growth"] = attr(default="cell growth", frozen=True)
257
+ phir: MatPositiveFloat = element(default=DynamicMaterialParameter(text=10000.0))
258
+ cr: MatPositiveFloat = element(default=DynamicMaterialParameter(text=1.0))
259
+ ce: MatPositiveFloat = element(default=MaterialParameter(text=300.0))
260
+
261
+
262
+ class CubicCLE(MaterialBase, tag="material", extra="forbid"):
263
+ type: Literal["cubic CLE"] = attr(default="cubic CLE", frozen=True)
264
+ lp1: MatPositiveFloat = element(default=MaterialParameter(text=13.01))
265
+ lm1: MatPositiveFloat = element(default=MaterialParameter(text=0.49))
266
+ l2: MatPositiveFloat = element(default=MaterialParameter(text=0.66))
267
+ mu: MatPositiveFloat = element(default=MaterialParameter(text=0.16))
268
+
269
+
270
+ class CoupledMooneyRivlin(MaterialBase, tag="material", extra="forbid"):
271
+ type: Literal["coupled Mooney-Rivlin"] = attr(default="coupled Mooney-Rivlin", frozen=True)
272
+ c1: MatPositiveFloat = element(default=MaterialParameter(text=10.0))
273
+ c2: MatNonNegativeFloat = element(default=MaterialParameter(text=1.0))
274
+ k: MatPositiveFloat = element(default=MaterialParameter(text=100.0))
275
+
276
+
277
+ class CoupledVerondaWestmann(MaterialBase, tag="material", extra="forbid"):
278
+ type: Literal["coupled Veronda-Westmann"] = attr(default="coupled Veronda-Westmann", frozen=True)
279
+ c1: MatPositiveFloat = element(default=MaterialParameter(text=10.0))
280
+ c2: MatNonNegativeFloat = element(default=MaterialParameter(text=1.0))
281
+ k: MatPositiveFloat = element(default=MaterialParameter(text=100.0))
282
+
283
+
284
+ class DonnanEquilibrium(BaseXmlModel, tag="solid", extra="forbid"):
285
+ type: Literal["Donnan equilibrium"] = attr(default="Donnan equilibrium", frozen=True)
286
+ phiw0: MatPositiveFloat = element(default=MaterialParameter(text=0.8))
287
+ cF0: MatPositiveFloat = element(default=DynamicMaterialParameter(text=1.0))
288
+ bosm: MatPositiveFloat = element(default=MaterialParameter(text=0.8))
289
+
290
+
291
+ class EllipsoidalFiberDistribution(BaseXmlModel, tag="solid", extra="forbid"):
292
+ type: Literal["ellipsoidal fiber distribution"] = attr(default="ellipsoidal fiber distribution", frozen=True)
293
+ ksi: MatStringFloatVec3 = element(default=MaterialParameter(text="10,12,15"))
294
+ beta: MatStringFloatVec3 = element(default=MaterialParameter(text="2.5,3,3"))
295
+
296
+
297
+ class EllipsoidalFiberDistributionNeoHookean(MaterialBase, tag="material", extra="forbid"):
298
+ type: Literal["EFD neo-Hookean"] = attr(default="EFD neo-Hookean", frozen=True)
299
+ E: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
300
+ v: MatPositiveFloat = element(default=MaterialParameter(text=0.3))
301
+ beta: MatStringFloatVec3 = element(default=MaterialParameter(text="2.5,3.0,3.0"))
302
+ ksi: MatStringFloatVec3 = element(default=MaterialParameter(text="1.0,1.0,1.0"))
303
+
304
+
305
+ class EllipsoidalFiberDistributionDonnanEquilibrium(MaterialBase, tag="material", extra="forbid"):
306
+ type: Literal["EFD Donnan equilibrium"] = attr(default="EFD Donnan equilibrium", frozen=True)
307
+ phiw0: MatPositiveFloat = element(default=MaterialParameter(text=0.8))
308
+ cF0: DynamicMaterialParameter = element(default=DynamicMaterialParameter(text=0.3))
309
+ bosm: MaterialParameter = element(default=MaterialParameter(text=300))
310
+ beta: MatStringFloatVec3 = element(default=MaterialParameter(text="2.5,3.0,3.0"))
311
+ ksi: MatStringFloatVec3 = element(default=MaterialParameter(text="1.0,1.0,1.0"))
312
+
313
+
314
+ class FungOrthotropicCompressible(MaterialBase, tag="material", extra="forbid"):
315
+ type: Literal["Fung-ortho-compressible"] = attr(default="Fung-ortho-compressible", frozen=True)
316
+ E1: MatPositiveFloat = element(default=MaterialParameter(text=124.0))
317
+ E2: MatPositiveFloat = element(default=MaterialParameter(text=124.0))
318
+ E3: MatPositiveFloat = element(default=MaterialParameter(text=36.0))
319
+ G12: MatPositiveFloat = element(default=MaterialParameter(text=67.0))
320
+ G23: MatPositiveFloat = element(default=MaterialParameter(text=40.0))
321
+ G31: MatPositiveFloat = element(default=MaterialParameter(text=40.0))
322
+ v12: MatPositiveFloat = element(default=MaterialParameter(text=0.075))
323
+ v23: MatPositiveFloat = element(default=MaterialParameter(text=0.87))
324
+ v31: MatPositiveFloat = element(default=MaterialParameter(text=0.26))
325
+ c: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
326
+ k: MatPositiveFloat = element(default=MaterialParameter(text=120.0))
327
+
328
+
329
+ class GentCompressible(MaterialBase, tag="material", extra="forbid"):
330
+ type: Literal["compressible Gent"] = attr(default="compressible Gent", frozen=True)
331
+ G: MatPositiveFloat = element(default=MaterialParameter(text=3.14))
332
+ Jm: MatPositiveFloat = element(default=MaterialParameter(text=1.5))
333
+ K: MatPositiveFloat = element(default=MaterialParameter(text=1e5))
334
+
335
+
336
+ class HolmesMow(MaterialBase, tag="material", extra="forbid"):
337
+ type: Literal["Holmes-Mow"] = attr(default="Holmes-Mow", frozen=True)
338
+ E: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
339
+ v: MatPositiveFloat = element(default=MaterialParameter(text=0.35))
340
+ beta: MatPositiveFloat = element(default=MaterialParameter(text=0.25))
341
+
342
+
343
+ class HolzapfelGasserOgdenUnconstrained(MaterialBase, tag="material", extra="forbid"):
344
+ type: Literal["HGO unconstrained"] = attr(default="HGO unconstrained", frozen=True)
345
+ c: MatPositiveFloat = element(default=MaterialParameter(text=7.64))
346
+ k1: MatPositiveFloat = element(default=MaterialParameter(text=996.6))
347
+ k2: MatPositiveFloat = element(default=MaterialParameter(text=524.6))
348
+ gamma: MatLTE_90_GTE_0 = element(default=MaterialParameter(text=49.98))
349
+ kappa: MatLTE_OneThird_GTE_Zero = element(default=MaterialParameter(text=0.226))
350
+ k: MatPositiveFloat = element(default=MaterialParameter(text=7.64e3))
351
+ mat_axis: MaterialAxisVector | None = element(default=None)
352
+ fiber: FiberVector | None = element(default=None)
353
+
354
+
355
+ class IsotropicElastic(MaterialBase, tag="material", extra="forbid"):
356
+ type: Literal["isotropic elastic"] = attr(default="isotropic elastic", frozen=True)
357
+ E: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
358
+ v: MatNonNegativeFloat = element(default=MaterialParameter(text=0.3))
359
+
360
+
361
+ class IsotropicHencky(MaterialBase, tag="material", extra="forbid"):
362
+ type: Literal["isotropic Hencky"] = attr(default="isotropic Hencky", frozen=True)
363
+ E: MatPositiveFloat = element(default=MaterialParameter(text=1000.0))
364
+ v: MatPositiveFloat = element(default=MaterialParameter(text=0.45))
365
+
366
+
367
+ class KinematicGrowth(MaterialBase, tag="material", extra="forbid"):
368
+ elastic: str = element()
369
+ growth: Literal["volume", "growth", "area growth", "fiber growth"] = element(default="volume")
370
+
371
+
372
+ class LargePoissonRatioLigament(MaterialBase, tag="material", extra="forbid"):
373
+ type: Literal["PRLig"] = attr(default="PRLig", frozen=True)
374
+ c1: MatPositiveFloat = element(default=MaterialParameter(text=90.0))
375
+ c2: MatPositiveFloat = element(default=MaterialParameter(text=160.0))
376
+ mu: MatPositiveFloat = element(default=MaterialParameter(text=0.025))
377
+ v0: MatPositiveFloat = element(default=MaterialParameter(text=5.85))
378
+ m: MatPositiveFloat = element(default=MaterialParameter(text=100.0))
379
+ k: MatPositiveFloat = element(default=MaterialParameter(text=1.55))
380
+
381
+
382
+ class Lung(MaterialBase, tag="material", extra="forbid"):
383
+ type: Literal["lung"] = attr(default="lung", frozen=True)
384
+ E: MatPositiveFloat = element(default=MaterialParameter(text=1913.7))
385
+ v: MatPositiveFloat = element(default=MaterialParameter(text=0.3413))
386
+ c1: MatPositiveFloat = element(default=MaterialParameter(text=278.2))
387
+ c3: MatPositiveFloat = element(default=MaterialParameter(text=5.766))
388
+ d1: MatPositiveFloat = element(default=MaterialParameter(text=3.0))
389
+ d3: MatPositiveFloat = element(default=MaterialParameter(text=6.0))
390
+
391
+
392
+ class NaturalNeoHookean(MaterialBase, tag="material", extra="forbid"):
393
+ type: Literal["natural neo-Hookean"] = attr(default="natural neo-Hookean", frozen=True)
394
+ E: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
395
+ v: MatNonNegativeFloat = element(default=MaterialParameter(text=0.3))
396
+
397
+
398
+ class NeoHookean(MaterialBase, tag="material", extra="forbid"):
399
+ type: Literal["neo-Hookean"] = attr(default="neo-Hookean", frozen=True)
400
+ E: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
401
+ v: MatNonNegativeFloat = element(default=MaterialParameter(text=0.3))
402
+
403
+
404
+ class OrthotropicElastic(MaterialBase, tag="material", extra="forbid"):
405
+ type: Literal["orthotropic elastic"] = attr(default="orthotropic elastic", frozen=True)
406
+ E1: MatPositiveFloat = element(default=MaterialParameter(text=13.4))
407
+ E2: MatPositiveFloat = element(default=MaterialParameter(text=14.1))
408
+ E3: MatPositiveFloat = element(default=MaterialParameter(text=22.9))
409
+ v12: MatNonNegativeFloat = element(default=MaterialParameter(text=0.42))
410
+ v23: MatNonNegativeFloat = element(default=MaterialParameter(text=0.23))
411
+ v31: MatNonNegativeFloat = element(default=MaterialParameter(text=0.38))
412
+ G12: MatPositiveFloat = element(default=MaterialParameter(text=4.6))
413
+ G23: MatPositiveFloat = element(default=MaterialParameter(text=6.2))
414
+ G31: MatPositiveFloat = element(default=MaterialParameter(text=5.8))
415
+ mat_axis: MaterialAxisVector | None = element(default=None)
416
+
417
+
418
+ class OrthotropicCLE(MaterialBase, tag="material", extra="forbid"):
419
+ type: Literal["orthotropic CLE"] = attr(default="orthotropic CLE", frozen=True)
420
+ lp11: MatPositiveFloat = element(default=MaterialParameter(text=13.01))
421
+ lp22: MatPositiveFloat = element(default=MaterialParameter(text=13.01))
422
+ lp33: MatPositiveFloat = element(default=MaterialParameter(text=13.01))
423
+ lm11: MatPositiveFloat = element(default=MaterialParameter(text=0.49))
424
+ lm22: MatPositiveFloat = element(default=MaterialParameter(text=0.49))
425
+ lm33: MatPositiveFloat = element(default=MaterialParameter(text=0.49))
426
+ l12: MatPositiveFloat = element(default=MaterialParameter(text=0.66))
427
+ l23: MatPositiveFloat = element(default=MaterialParameter(text=0.66))
428
+ l31: MatPositiveFloat = element(default=MaterialParameter(text=0.66))
429
+ mu1: MatPositiveFloat = element(default=MaterialParameter(text=0.16))
430
+ mu2: MatPositiveFloat = element(default=MaterialParameter(text=0.16))
431
+ mu3: MatPositiveFloat = element(default=MaterialParameter(text=0.16))
432
+
433
+
434
+ class OsmoticVirialPressure(MaterialBaseNoDensity, tag="solid", extra="forbid"):
435
+ type: Literal["osmotic virial expansion"] = attr(default="osmotic virial expansion", frozen=True)
436
+ phiw0: MaterialParameter = element(default=MaterialParameter(text=0.8))
437
+ cr: DynamicMaterialParameter = element(default=DynamicMaterialParameter(text=100.0))
438
+ c1: MaterialParameter = element(default=MaterialParameter(text=2.436e-6))
439
+ c2: MaterialParameter = element(default=MaterialParameter(text=0.0))
440
+ c3: MaterialParameter = element(default=MaterialParameter(text=0.0))
441
+
442
+
443
+ class PerfectOsmometer(MaterialBaseNoDensity, tag="solid", extra="forbid"):
444
+ type: Literal["perfect osmometer"] = attr(default="perfect osmometer", frozen=True)
445
+ phiw0: MatPositiveFloat = element(default=MaterialParameter(text=0.8))
446
+ iosm: MatPositiveFloat = element(default=MaterialParameter(text=300.0))
447
+ bosm: DynamicMaterialParameter = element(default=DynamicMaterialParameter(text=1.0))
448
+
449
+
450
+ class PorousNeoHookean(MaterialBase, tag="material", extra="forbid"):
451
+ type: Literal["porous neo-Hookean"] = attr(default="porous neo-Hookean", frozen=True)
452
+ E: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
453
+ phi0: MatPositiveFloat = element(default=MaterialParameter(text=0.5))
454
+
455
+
456
+ class ShenoyWang(MaterialBase, tag="material", extra="forbid"):
457
+ type: Literal["Shenoy"] = attr(default="Shenoy", frozen=True)
458
+ mu: MatPositiveFloat = element(default=MaterialParameter(text=0.7692))
459
+ k: MatPositiveFloat = element(default=MaterialParameter(text=1.667))
460
+ Ef: MatPositiveFloat = element(default=MaterialParameter(text=134.6))
461
+ lam_c: MatPositiveFloat = element(default=MaterialParameter(text=1.02))
462
+ lam_t: MatPositiveFloat = element(default=MaterialParameter(text=0.255))
463
+ n: MatPositiveFloat = element(default=MaterialParameter(text=5))
464
+ m: MatPositiveFloat = element(default=MaterialParameter(text=30))
465
+
466
+
467
+ class SphericalFiberDistribution(MaterialBaseNoDensity, tag="solid", extra="forbid"):
468
+ type: Literal["spherical fiber distribution"] = attr(default="spherical fiber distribution", frozen=True)
469
+ ksi: MatPositiveFloat = element(default=MaterialParameter(text=10.0))
470
+ alpha: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
471
+ beta: MatGTETwoFloat = element(default=MaterialParameter(text=2.5))
472
+
473
+
474
+ class SphericalFiberDistributionSBM(MaterialBaseNoDensity, tag="solid", extra="forbid"):
475
+ type: Literal["spherical fiber distribution"] = attr(default="spherical fiber distribution sbm", frozen=True)
476
+ alpha: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
477
+ beta: MatGTETwoFloat = element(default=MaterialParameter(text=2.5))
478
+ ksi0: MatPositiveFloat = element(default=MaterialParameter(text=10.0))
479
+ gamma: MatPositiveFloat = element(default=MaterialParameter(text=2.0))
480
+ rho0: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
481
+ sbm: MatPositiveInt = element(default=MaterialParameter(text=1))
482
+
483
+
484
+ class TransIsoMooneyRivlin(MaterialBase, tag="material", extra="forbid"):
485
+ type: Literal["coupled trans-iso Mooney-Rivlin"] = attr(default="coupled trans-iso Mooney-Rivlin", frozen=True)
486
+ c1: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
487
+ c2: MatNonNegativeFloat = element(default=MaterialParameter(text=0.1))
488
+ c3: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
489
+ c4: MatPositiveFloat = element(default=MaterialParameter(text=43.0))
490
+ c5: MatPositiveFloat = element(default=MaterialParameter(text=3.0))
491
+ lam_max: MatGTOneFloat = element(default=MaterialParameter(text=1.05))
492
+ k: MatPositiveFloat = element(default=MaterialParameter(text=10.0))
493
+ fiber: FiberVector | None = element(default=None)
494
+
495
+
496
+ class TransIsoVerondaWestmann(MaterialBase, tag="material", extra="forbid"):
497
+ type: Literal["coupled trans-iso Veronda-Westmann"] = attr(default="coupled trans-iso Veronda-Westmann", frozen=True)
498
+ c1: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
499
+ c2: MatNonNegativeFloat = element(default=MaterialParameter(text=0.1))
500
+ c3: MatNonNegativeFloat = element(default=MaterialParameter(text=1.0))
501
+ c4: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
502
+ c5: MatPositiveFloat = element(default=MaterialParameter(text=1.34))
503
+ lam_max: MatGTOneFloat = element(default=MaterialParameter(text=1.3), alias="lambda")
504
+ k: MatPositiveFloat = element(default=MaterialParameter(text=100.0))
505
+ fiber: FiberVector | None = element(default=None)
506
+
507
+
508
+ class UnconstrainedOgden(MaterialBase, tag="material", extra="forbid"):
509
+ type: Literal["Ogden unconstrained"] = attr(default="Ogden unconstrained", frozen=True)
510
+ m1: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
511
+ c1: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
512
+ m2: MatPositiveFloat | None = element(default=None)
513
+ c2: MatPositiveFloat | None = element(default=None)
514
+ m3: MatPositiveFloat | None = element(default=None)
515
+ c3: MatPositiveFloat | None = element(default=None)
516
+ m4: MatPositiveFloat | None = element(default=None)
517
+ c4: MatPositiveFloat | None = element(default=None)
518
+ m5: MatPositiveFloat | None = element(default=None)
519
+ c5: MatPositiveFloat | None = element(default=None)
520
+ m6: MatPositiveFloat | None = element(default=None)
521
+ c6: MatPositiveFloat | None = element(default=None)
522
+
523
+
524
+ UnconstrainedMaterials: TypeAlias = (
525
+ ArrudaBoyce
526
+ | CoupledMooneyRivlin
527
+ | CoupledVerondaWestmann
528
+ | CubicCLE
529
+ | EllipsoidalFiberDistributionNeoHookean
530
+ | FungOrthotropicCompressible
531
+ | GentCompressible
532
+ | HolmesMow
533
+ | HolzapfelGasserOgdenUnconstrained
534
+ | IsotropicElastic
535
+ | IsotropicHencky
536
+ | LargePoissonRatioLigament
537
+ | Lung
538
+ | NaturalNeoHookean
539
+ | NeoHookean
540
+ | PorousNeoHookean
541
+ | OrthotropicElastic
542
+ | OrthotropicCLE
543
+ | ShenoyWang
544
+ | TransIsoMooneyRivlin
545
+ | TransIsoVerondaWestmann
546
+ | UnconstrainedOgden
547
+ )
548
+
549
+ EvolvingUnconstrainedMaterials: TypeAlias = (
550
+ EllipsoidalFiberDistributionDonnanEquilibrium | CellGrowth | OsmoticVirialPressure | PerfectOsmometer
551
+ )
552
+
553
+
554
+ class ArrudaBoyceUC(MaterialBase, tag="material", extra="forbid"):
555
+ type: Literal["Arruda-Boyce"] = attr(default="Arruda-Boyce", frozen=True)
556
+ mu: MatPositiveFloat = element(default=MaterialParameter(text=0.09))
557
+ N: MatPositiveFloat = element(default=MaterialParameter(text=26.5))
558
+ k: MatPositiveFloat = element(default=MaterialParameter(text=100.0))
559
+
560
+
561
+ class EllipsoidalFiberDistributionUC(MaterialBaseNoDensity, tag="solid", extra="forbid"):
562
+ type: Literal["EFD uncoupled"] = attr(default="EFD uncoupled", frozen=True)
563
+ ksi: MatStringFloatVec3 = element(default=MaterialParameter(text="10,12,15"))
564
+ beta: MatStringFloatVec3 = element(default=MaterialParameter(text="2.5,3,3"))
565
+
566
+
567
+ class EllipsoidalFiberDistributionMooneyRivlinUC(MaterialBase, tag="material", extra="forbid"):
568
+ type: Literal["EFD Mooney-Rivlin"] = attr(default="EFD Mooney-Rivlin", frozen=True)
569
+ c1: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
570
+ c2: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
571
+ beta: MatStringFloatVec3 = element(default=MaterialParameter(text="4.5,4.5,4.5"))
572
+ ksi: MatStringFloatVec3 = element(default=MaterialParameter(text="1,1,1"))
573
+ k: MatPositiveFloat = element(default=MaterialParameter(text=1000.0))
574
+
575
+
576
+ class EllipsoidalFiberDistributionVerondaWestmannUC(MaterialBase, tag="material", extra="forbid"):
577
+ type: Literal["EFD Veronda-Westmann"] = attr(default="EFD Veronda-Westmann", frozen=True)
578
+ c1: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
579
+ c2: MatNonNegativeFloat = element(default=MaterialParameter(text=0.5))
580
+ beta: MatStringFloatVec3 = element(default=MaterialParameter(text="4.5,4.5,4.5"))
581
+ ksi: MatStringFloatVec3 = element(default=MaterialParameter(text="1,1,1"))
582
+ k: MatPositiveFloat = element(default=MaterialParameter(text=1000.0))
583
+
584
+
585
+ class FungOrthotropicUC(MaterialBase, tag="material", extra="forbid"):
586
+ type: Literal["Fung orthotropic"] = attr(default="Fung orthotropic", frozen=True)
587
+ E1: MatPositiveFloat = element(default=MaterialParameter(text=124.0))
588
+ E2: MatPositiveFloat = element(default=MaterialParameter(text=124.0))
589
+ E3: MatPositiveFloat = element(default=MaterialParameter(text=36.0))
590
+ G12: MatPositiveFloat = element(default=MaterialParameter(text=67.0))
591
+ G23: MatPositiveFloat = element(default=MaterialParameter(text=40.0))
592
+ G31: MatPositiveFloat = element(default=MaterialParameter(text=40.0))
593
+ v12: MatPositiveFloat = element(default=MaterialParameter(text=0.075))
594
+ v23: MatPositiveFloat = element(default=MaterialParameter(text=0.87))
595
+ v31: MatPositiveFloat = element(default=MaterialParameter(text=0.26))
596
+ c: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
597
+ k: MatPositiveFloat = element(default=MaterialParameter(text=120000.0))
598
+
599
+
600
+ class GentUC(MaterialBase, tag="material", extra="forbid"):
601
+ type: Literal["Gent"] = attr(default="Gent", frozen=True)
602
+ G: MatPositiveFloat = element(default=MaterialParameter(text=3.14))
603
+ Jm: MatPositiveFloat = element(default=MaterialParameter(text=1.5))
604
+ k: MatPositiveFloat = element(default=MaterialParameter(text=1e5))
605
+
606
+
607
+ class HolmesMowUC(MaterialBase, tag="material", extra="forbid"):
608
+ type: Literal["uncoupled Holmes-Mow"] = attr(default="uncoupled Holmes-Mow", frozen=True)
609
+ mu: MatPositiveFloat = element(default=MaterialParameter(text=0.5))
610
+ beta: MatPositiveFloat = element(default=MaterialParameter(text=2.0))
611
+ k: MatPositiveFloat = element(default=MaterialParameter(text=1000.0))
612
+
613
+
614
+ class HolzapfelGasserOgdenUC(MaterialBase, tag="material", extra="forbid"):
615
+ type: Literal["Holzapfel-Gasser-Ogden"] = attr(default="Holzapfel-Gasser-Ogden", frozen=True)
616
+ c: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
617
+ k1: MatPositiveFloat = element(default=MaterialParameter(text=10.0))
618
+ k2: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
619
+ gamma: MatLTE_90_GTE_0 = element(default=MaterialParameter(text=45.0))
620
+ kappa: MatLTE_OneThird_GTE_Zero = element(default=MaterialParameter(text=0.1))
621
+ k: MatPositiveFloat = element(default=MaterialParameter(text=100.0))
622
+ mat_axis: MaterialAxisVector | None = element(default=None)
623
+ fiber: FiberVector | None = element(default=None)
624
+
625
+
626
+ class MooneyRivlinUC(MaterialBase, tag="material", extra="forbid"):
627
+ type: Literal["Mooney-Rivlin"] = attr(default="Mooney-Rivlin", frozen=True)
628
+ c1: MatPositiveFloat = element(default=MaterialParameter(text=10.0))
629
+ c2: MatNonNegativeFloat = element(default=MaterialParameter(text=1.0))
630
+ k: MatPositiveFloat = element(default=MaterialParameter(text=1000.0))
631
+
632
+
633
+ class MuscleUC(MaterialBase, tag="material", extra="forbid"):
634
+ type: Literal["muscle material"] = attr(default="muscle material", frozen=True)
635
+ g1: MatPositiveFloat = element(default=MaterialParameter(text=500.0))
636
+ g2: MatPositiveFloat = element(default=MaterialParameter(text=500.0))
637
+ p1: MatPositiveFloat = element(default=MaterialParameter(text=0.5))
638
+ p2: MatPositiveFloat = element(default=MaterialParameter(text=6.6))
639
+ smax: MatPositiveFloat = element(default=MaterialParameter(text=3e5))
640
+ Lofl: MatGTOneFloat = element(default=MaterialParameter(text=1.07))
641
+ lam_max: MatGTOneFloat = element(default=MaterialParameter(text=1.4))
642
+ k: MatPositiveFloat = element(default=MaterialParameter(text=1e6))
643
+ fiber: FiberVector = element(default=FiberVector())
644
+
645
+
646
+ class OgdenUC(MaterialBase, tag="material", extra="forbid"):
647
+ type: Literal["Ogden"] = attr(default="Ogden", frozen=True)
648
+ k: MatPositiveFloat = element(default=MaterialParameter(text=100.0))
649
+ m1: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
650
+ c1: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
651
+ m2: MatPositiveFloat | None = element(default=None)
652
+ c2: MatPositiveFloat | None = element(default=None)
653
+ m3: MatPositiveFloat | None = element(default=None)
654
+ c3: MatPositiveFloat | None = element(default=None)
655
+ m4: MatPositiveFloat | None = element(default=None)
656
+ c4: MatPositiveFloat | None = element(default=None)
657
+ m5: MatPositiveFloat | None = element(default=None)
658
+ c5: MatPositiveFloat | None = element(default=None)
659
+ m6: MatPositiveFloat | None = element(default=None)
660
+ c6: MatPositiveFloat | None = element(default=None)
661
+
662
+
663
+ class TendonUC(MaterialBase, tag="material", extra="forbid"):
664
+ type: Literal["tendon material"] = attr(default="tendon material", frozen=True)
665
+ g1: MatPositiveFloat = element(default=MaterialParameter(text=5e4))
666
+ g2: MatNonNegativeFloat = element(default=MaterialParameter(text=5e4))
667
+ l1: MatPositiveFloat = element(default=MaterialParameter(text=2.7e6))
668
+ l2: MatPositiveFloat = element(default=MaterialParameter(text=46.4))
669
+ lam_max: MatGTOneFloat = element(default=MaterialParameter(text=1.03))
670
+ k: MatPositiveFloat = element(default=MaterialParameter(text=1e7))
671
+ fiber: FiberVector = element(default=FiberVector())
672
+
673
+
674
+ class TensionCompressionNonlinearOrthoUC(MaterialBase, tag="material", extra="forbid"):
675
+ type: Literal["TC nonlinear orthotropic"] = attr(default="TC nonlinear orthotropic", frozen=True)
676
+ c1: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
677
+ c2: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
678
+ k: MatPositiveFloat = element(default=MaterialParameter(text=100))
679
+ beta: MatStringFloatVec3 = element(default=MaterialParameter(text="4.3,4.3,4.3"))
680
+ ksi: MatStringFloatVec3 = element(default=MaterialParameter(text="4525,4525,4525"))
681
+ mat_axis: MaterialAxisVector = element(default=MaterialAxisVector())
682
+
683
+
684
+ class TransIsoMooneyRivlinUC(MaterialBase, tag="material", extra="forbid"):
685
+ type: Literal["trans iso Mooney-Rivlin"] = attr(default="trans iso Mooney-Rivlin", frozen=True)
686
+ c1: MatPositiveFloat = element(default=MaterialParameter(text=13.85))
687
+ c2: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
688
+ c3: MatNonNegativeFloat = element(default=MaterialParameter(text=2.07))
689
+ c4: MatPositiveFloat = element(default=MaterialParameter(text=61.44))
690
+ c5: MatPositiveFloat = element(default=MaterialParameter(text=640.7))
691
+ lam_max: MatGTOneFloat = element(default=MaterialParameter(text=1.03))
692
+ k: MatPositiveFloat = element(default=MaterialParameter(text=100.0))
693
+ fiber: FiberVector | None = element(default=None)
694
+ active_contraction: ActiveContraction | None = element(default=None)
695
+
696
+
697
+ class TransIsoVerondaWestmannUC(MaterialBase, tag="material", extra="forbid"):
698
+ type: Literal["trans iso Veronda-Westmann"] = attr(default="trans iso Veronda-Westmann", frozen=True)
699
+ c1: MatPositiveFloat = element(default=MaterialParameter(text=13.85))
700
+ c2: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
701
+ c3: MatNonNegativeFloat = element(default=MaterialParameter(text=2.07))
702
+ c4: MatPositiveFloat = element(default=MaterialParameter(text=61.44))
703
+ c5: MatPositiveFloat = element(default=MaterialParameter(text=640.7))
704
+ lam_max: MatGTOneFloat = element(default=MaterialParameter(text=1.03))
705
+ k: MatPositiveFloat = element(default=MaterialParameter(text=100.0))
706
+ fiber: FiberVector | None = element(default=None)
707
+ active_contraction: ActiveContraction | None = element(default=None)
708
+
709
+
710
+ class VerondaWestmannUC(MaterialBase, tag="material", extra="forbid"):
711
+ type: Literal["Veronda-Westmann"] = attr(default="Veronda-Westmann", frozen=True)
712
+ c1: MatPositiveFloat = element(default=MaterialParameter(text=1000.0))
713
+ c2: MatNonNegativeFloat = element(default=MaterialParameter(text=2000.0))
714
+ k: MatPositiveFloat = element(default=MaterialParameter(text=1000.0))
715
+
716
+
717
+ class MooneyRivlinVonMisesFibersUC(MaterialBase, tag="material", extra="forbid"):
718
+ type: Literal["Mooney-Rivlin von Mises Fibers"] = attr(default="Mooney-Rivlin von Mises Fibers", frozen=True)
719
+ c1: MatPositiveFloat = element(default=MaterialParameter(text=10.0))
720
+ c2: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
721
+ c3: MatPositiveFloat = element(default=MaterialParameter(text=50.0))
722
+ c4: MatPositiveFloat = element(default=MaterialParameter(text=5.0))
723
+ c5: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
724
+ k: MatPositiveFloat = element(default=MaterialParameter(text=100000.0))
725
+ kf: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
726
+ vmc: MatPositiveFloat = element(default=MaterialParameter(text=2.0))
727
+ var_n: MatPositiveFloat = element(default=MaterialParameter(text=2.0))
728
+ tp: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
729
+ gipt: MatPositiveIntMult10 = element(default=MaterialParameter(text=40))
730
+ mat_axis: MaterialAxisVector = element(default=MaterialAxisVector())
731
+
732
+
733
+ class LeeSacksUC(MaterialBase, tag="material", extra="forbid"):
734
+ type: Literal["uncoupled isotropic Lee-Sacks"] = attr(default="uncoupled isotropic Lee-Sacks", frozen=True)
735
+ c0: MatPositiveFloat = element(default=MaterialParameter(text=10.0))
736
+ c1: MatPositiveFloat = element(default=MaterialParameter(text=0.209))
737
+ c2: MatNonNegativeFloat = element(default=MaterialParameter(text=9.046))
738
+ tangent_scale: MatGTEOneFloat = element(default=MaterialParameter(text=1.0))
739
+ k: MatPositiveFloat = element(default=MaterialParameter(text=1000.0))
740
+
741
+
742
+ class Yeoh(MaterialBase, tag="material", extra="forbid"):
743
+ type: Literal["Yeoh"] = attr(default="Yeoh", frozen=True)
744
+ c1: MatPositiveFloat = element(default=MaterialParameter(text=0.75))
745
+ c2: MatNonNegativeFloat | None = element(default=None)
746
+ c3: MatNonNegativeFloat | None = element(default=None)
747
+ c4: MatNonNegativeFloat | None = element(default=None)
748
+ c5: MatNonNegativeFloat | None = element(default=None)
749
+ c6: MatNonNegativeFloat | None = element(default=None)
750
+ k: MatPositiveFloat = element(default=MaterialParameter(text=100.0))
751
+
752
+
753
+ UncoupledMaterials: TypeAlias = (
754
+ ArrudaBoyceUC
755
+ | EllipsoidalFiberDistributionMooneyRivlinUC
756
+ | EllipsoidalFiberDistributionVerondaWestmannUC
757
+ | FungOrthotropicUC
758
+ | GentUC
759
+ | HolmesMowUC
760
+ | HolzapfelGasserOgdenUC
761
+ | MooneyRivlinUC
762
+ | MuscleUC
763
+ | OgdenUC
764
+ | TendonUC
765
+ | TensionCompressionNonlinearOrthoUC
766
+ | TransIsoMooneyRivlinUC
767
+ | TransIsoVerondaWestmannUC
768
+ | MooneyRivlinVonMisesFibersUC
769
+ | LeeSacksUC
770
+ | Yeoh
771
+ )
772
+
773
+
774
+ class RigidBody(MaterialBase, tag="material", extra="forbid"):
775
+ type: Literal["rigid body"] = attr(default="rigid body", frozen=True)
776
+ center_of_mass: StringFloatVec3 | None = element(default=None)
777
+ E: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
778
+ v: MatNonNegativeFloat = element(default=MaterialParameter(text=0.3))
779
+
780
+
781
+ # Unconstrained Fibers
782
+ class FiberExponentialPower(BaseXmlModel, tag="solid", extra="forbid"):
783
+ type: str = attr(default="fiber-exp-pow", frozen=True)
784
+ ksi: MatPositiveFloat = element(default=MaterialParameter(text=5.0))
785
+ alpha: MatNonNegativeFloat = element(default=MaterialParameter(text=20.0))
786
+ beta: MatGTETwoFloat = element(default=MaterialParameter(text=2.0))
787
+ lam0: MatGTOneFloat = element(default=MaterialParameter(text=1.0))
788
+ fiber: FiberVector | None = element(default=None)
789
+
790
+
791
+ class FiberNeoHookean(BaseXmlModel, tag="solid", extra="forbid"):
792
+ type: str = attr(default="fiber-NH", frozen=True)
793
+ mu: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
794
+ fiber: FiberVector | None = element(default=None)
795
+
796
+
797
+ class FiberNaturalNeoHookean(BaseXmlModel, tag="solid", extra="forbid"):
798
+ type: str = attr(default="fiber-natural-NH", frozen=True)
799
+ ksi: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
800
+ lam0: MatGTEOneFloat = element(default=MaterialParameter(text=1.0))
801
+ fiber: FiberVector | None = element(default=None)
802
+
803
+
804
+ class FiberToeLinear(BaseXmlModel, tag="solid", extra="forbid"):
805
+ type: str = attr(default="fiber-pow-linear", frozen=True)
806
+ E: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
807
+ beta: MatGTETwoFloat = element(default=MaterialParameter(text=2.0))
808
+ lam0: MatGTOneFloat = element(default=MaterialParameter(text=1.01))
809
+ fiber: FiberVector | None = element(default=None)
810
+
811
+
812
+ class FiberExponentialPowerLinear(BaseXmlModel, tag="solid", extra="forbid"):
813
+ type: str = attr(default="fiber-exp-pow-linear", frozen=True)
814
+ E: MatPositiveFloat = element(default=MaterialParameter(text=1080.0))
815
+ alpha: MatNonNegativeFloat = element(default=MaterialParameter(text=1400.0))
816
+ beta: MatGTETwoFloat = element(default=MaterialParameter(text=2.73))
817
+ lam0: MatGTOneFloat = element(default=MaterialParameter(text=1.01))
818
+ fiber: FiberVector | None = element(default=None)
819
+
820
+
821
+ class FiberExponentialLinear(BaseXmlModel, tag="solid", extra="forbid"):
822
+ type: str = attr(default="fiber-exp-linear", frozen=True)
823
+ c3: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
824
+ c4: MatPositiveFloat = element(default=MaterialParameter(text=43.0))
825
+ c5: MatPositiveFloat = element(default=MaterialParameter(text=3.0))
826
+ lam0: MatGTOneFloat = element(default=MaterialParameter(text=1.05), tag="lambda")
827
+ fiber: FiberVector | None = element(default=None)
828
+
829
+
830
+ class FiberEntropyChain(BaseXmlModel, tag="solid", extra="forbid"):
831
+ type: str = attr(default="fiber-entropy-chain", frozen=True)
832
+ ksi: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
833
+ N: MatGTOneFloat = element(default=MaterialParameter(text=2.0))
834
+ n_term: MatPositiveInt = element(default=MaterialParameter(text=2))
835
+ fiber: FiberVector | None = element(default=None)
836
+
837
+
838
+ FiberModel: TypeAlias = (
839
+ FiberNeoHookean
840
+ | FiberNaturalNeoHookean
841
+ | FiberToeLinear
842
+ | FiberEntropyChain
843
+ | FiberExponentialPower
844
+ | FiberExponentialLinear
845
+ | FiberEntropyChain
846
+ )
847
+
848
+
849
+ # Uncoupled Fibers
850
+ class FiberExponentialPowerUC(BaseXmlModel, tag="solid", extra="forbid"):
851
+ type: str = attr(default="fiber-exp-pow-uncoupled")
852
+ ksi: MatPositiveFloat = element(default=MaterialParameter(text=5.0))
853
+ alpha: MatNonNegativeFloat = element(default=MaterialParameter(text=20.0))
854
+ beta: MatGTETwoFloat = element(default=MaterialParameter(text=3.0))
855
+ fiber: FiberVector | None = element(default=None)
856
+
857
+
858
+ class FiberKiousisUC(BaseXmlModel, tag="solid", extra="forbid"):
859
+ type: str = attr(default="fiber-Kiousis-uncoupled")
860
+ d1: MatPositiveFloat = element(default=MaterialParameter(text=500.0))
861
+ d2: MatGTOneFloat = element(default=MaterialParameter(text=2.25))
862
+ n: MatNonNegativeFloat = element(default=MaterialParameter(text=3))
863
+ fiber: FiberVector | None = element(default=None)
864
+
865
+
866
+ class FiberToeLinearUC(BaseXmlModel, tag="solid", extra="forbid"):
867
+ type: str = attr(default="fiber-pow-linear-uncoupled", frozen=True)
868
+ E: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
869
+ beta: MatGTETwoFloat = element(default=MaterialParameter(text=2.0))
870
+ lam0: MatGTOneFloat = element(default=MaterialParameter(text=1.01))
871
+ fiber: FiberVector | None = element(default=None)
872
+
873
+
874
+ class FiberExponentialLinearUC(BaseXmlModel, tag="solid", extra="forbid"):
875
+ type: str = attr(default="uncoupled fiber-exp-linear", frozen=True)
876
+ c3: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
877
+ c4: MatPositiveFloat = element(default=MaterialParameter(text=43.0))
878
+ c5: MatPositiveFloat = element(default=MaterialParameter(text=3.0))
879
+ lam0: MatGTOneFloat = element(default=MaterialParameter(text=1.05), tag="lambda")
880
+ fiber: FiberVector | None = element(default=None)
881
+
882
+
883
+ class FiberEntropyChainUC(BaseXmlModel, tag="solid", extra="forbid"):
884
+ type: str = attr(default="uncoupled fiber-entropy-chain", frozen=True)
885
+ ksi: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
886
+ N: MatGTOneFloat = element(default=MaterialParameter(text=2.0))
887
+ n_term: MatPositiveInt = element(default=MaterialParameter(text=2))
888
+ fiber: FiberVector | None = element(default=None)
889
+
890
+
891
+ FiberModelUC: TypeAlias = FiberToeLinearUC | FiberKiousisUC | FiberExponentialPowerUC | FiberExponentialLinearUC | FiberEntropyChainUC
892
+
893
+
894
+ # Continuous Fiber Distribution Functions
895
+ class CFDSpherical(BaseXmlModel, tag="distribution", extra="forbid"):
896
+ type: Literal["spherical"] = attr(default="spherical", frozen=True)
897
+
898
+
899
+ class CFDEllipsoidal(BaseXmlModel, tag="distribution", extra="forbid"):
900
+ type: Literal["ellipsoidal"] = attr(default="ellipsoidal", frozen=True)
901
+ spa: MatStringFloatVec3 = element(default=MaterialParameter(text="1.0,1.0,1.0"))
902
+
903
+
904
+ class CFDVonMises3d(BaseXmlModel, tag="distribution", extra="forbid"):
905
+ type: Literal["von-Mises-3d"] = attr(default="von-Mises-3d")
906
+ b: MatNonNegativeFloat = element(default=MaterialParameter(text=0.5))
907
+
908
+
909
+ class CFDCircular(BaseXmlModel, tag="distribution", extra="forbid"):
910
+ type: Literal["circular"] = attr(default="circular")
911
+
912
+
913
+ class CFDElliptical(BaseXmlModel, tag="distribution", extra="forbid"):
914
+ type: Literal["elliptical"] = attr(default="elliptical", frozen=True)
915
+ spa1: MatNonNegativeFloat = element(default=MaterialParameter(text=1.0))
916
+ spa2: MatNonNegativeFloat = element(default=MaterialParameter(text=1.0))
917
+
918
+
919
+ class CFDVonMises2d(BaseXmlModel, tag="distribution", extra="forbid"):
920
+ type: Literal["von-Mises-2d"] = attr(default="von-Mises-2d")
921
+ b: MatNonNegativeFloat = element(default=MaterialParameter(text=0.5))
922
+
923
+
924
+ CFDistributionModel: TypeAlias = CFDCircular | CFDSpherical | CFDVonMises3d | CFDVonMises2d | CFDEllipsoidal
925
+
926
+
927
+ # Continous Fiber Distribution Function Integration Schema
928
+ class GaussKronrodTrapezoidalIntegration(BaseXmlModel, tag="scheme", extra="forbid"):
929
+ type: Literal["fibers-3d-gkt"] = attr(default="fibers-3d-gkt", frozen=True)
930
+ nph: Literal[7, 11, 15, 19, 23, 27] = element(default=7)
931
+ nth: PositiveInt = element(default=31)
932
+
933
+
934
+ class FiniteElementIntegration(BaseXmlModel, tag="scheme", extra="forbid"):
935
+ type: Literal["fibers-3d-fei"] = attr(default="fibers-3d-fei", frozen=True)
936
+ resolution: Literal[
937
+ 20,
938
+ 34,
939
+ 60,
940
+ 74,
941
+ 196,
942
+ 210,
943
+ 396,
944
+ 410,
945
+ 596,
946
+ 610,
947
+ 796,
948
+ 810,
949
+ 996,
950
+ 1010,
951
+ 1196,
952
+ 1210,
953
+ 1396,
954
+ 1410,
955
+ 1596,
956
+ 1610,
957
+ 1796,
958
+ ] = element(default=1610)
959
+
960
+
961
+ class TrapezoidalRuleIntegration(BaseXmlModel, tag="scheme", extra="forbid"):
962
+ type: Literal["fibers-2d-trapezoidal"] = attr(default="fibers-2d-trapezoidal", frozen=True)
963
+ nth: PositiveInt = element(default=31)
964
+
965
+
966
+ IntegrationScheme: TypeAlias = GaussKronrodTrapezoidalIntegration | FiniteElementIntegration | TrapezoidalRuleIntegration
967
+
968
+
969
+ class ContinuousFiberDistribution(BaseXmlModel, tag="solid", extra="forbid"):
970
+ type: Literal["continuous fiber distribution"] = attr(default="continuous fiber distribution", frozen=True)
971
+ fibers: FiberModel = element(default=FiberNaturalNeoHookean(), tag="fibers")
972
+ distribution: CFDistributionModel = element(default=CFDSpherical())
973
+ scheme: IntegrationScheme = element(default=GaussKronrodTrapezoidalIntegration())
974
+ mat_axis: MaterialAxisVector | None = element(default=None)
975
+
976
+
977
+ class ContinuousFiberDistributionUC(BaseXmlModel, tag="solid", extra="forbid"):
978
+ type: Literal["continuous fiber distribution uncoupled"] = attr(default="continuous fiber distribution uncoupled", frozen=True)
979
+ fibers: FiberModelUC = element(default=FiberToeLinearUC(), tag="fibers")
980
+ distribution: CFDistributionModel = element(default=CFDSpherical())
981
+ scheme: IntegrationScheme = element(default=GaussKronrodTrapezoidalIntegration())
982
+ mat_axis: MaterialAxisVector | None = element(default=None)
983
+
984
+
985
+ # Solid Mixture
986
+ class SolidMixture(MaterialBaseNoDensity, tag="material", extra="forbid"):
987
+ type: Literal["solid mixture"] = attr(default="solid mixture", frozen=True)
988
+ solid_list: list[UnconstrainedMaterials | FiberModel | ContinuousFiberDistribution | EvolvingUnconstrainedMaterials] = element(
989
+ tag="solid", default=[]
990
+ )
991
+
992
+ def add_solid(
993
+ self,
994
+ new_solid: UnconstrainedMaterials | FiberModel | ContinuousFiberDistribution | EvolvingUnconstrainedMaterials,
995
+ ):
996
+ self.solid_list.append(new_solid)
997
+
998
+
999
+ # Uncoupled Solid Mixture
1000
+ class SolidMixtureUC(MaterialBaseNoDensity, tag="material", extra="forbid"):
1001
+ type: Literal["solid mixture"] = attr(default="uncoupled solid mixture", frozen=True)
1002
+ solid_list: list[UncoupledMaterials | FiberModelUC | ContinuousFiberDistributionUC] = element(tag="solid", default=[])
1003
+
1004
+ def add_solid(self, new_solid: UncoupledMaterials | FiberModelUC | ContinuousFiberDistributionUC):
1005
+ self.solid_list.append(new_solid)
1006
+
1007
+
1008
+ # Viscoelastic Material
1009
+ class ViscoelasticMaterial(MaterialBaseNoDensity, tag="material", extra="forbid"):
1010
+ type: Literal["viscoelastic"] = attr(default="viscoelastic", frozen=True)
1011
+ g0: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
1012
+ g1: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
1013
+ g2: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
1014
+ g3: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
1015
+ g4: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
1016
+ g5: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
1017
+ g6: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
1018
+ t1: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
1019
+ t2: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
1020
+ t3: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
1021
+ t4: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
1022
+ t5: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
1023
+ t6: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
1024
+ elastic: UnconstrainedMaterials | SolidMixture = element(default=NeoHookean(id=1), tag="elastic")
1025
+
1026
+
1027
+ # Viscoelastic Material
1028
+ class ViscoelasticMaterialUC(MaterialBaseNoDensity, tag="material", extra="forbid"):
1029
+ type: Literal["uncoupled viscoelastic"] = attr(default="uncoupled viscoelastic", frozen=True)
1030
+ k: MatPositiveFloat = element(default=MaterialParameter(text=10.0))
1031
+ g0: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
1032
+ g1: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
1033
+ g2: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
1034
+ g3: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
1035
+ g4: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
1036
+ g5: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
1037
+ g6: MatNonNegativeFloat = element(default=MaterialParameter(text=0.0))
1038
+ t1: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
1039
+ t2: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
1040
+ t3: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
1041
+ t4: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
1042
+ t5: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
1043
+ t6: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
1044
+ elastic: UncoupledMaterials | SolidMixtureUC = element(default=MooneyRivlinUC(id=1), tag="elastic")
1045
+
1046
+
1047
+ # Prestrain
1048
+ class InSituStretch(BaseXmlModel, tag="stretch", extra="forbid"):
1049
+ lc: int = attr(ge=1)
1050
+ type: Literal["map", "math"] | None = attr(default=None)
1051
+ text: str | float
1052
+
1053
+
1054
+ class PrestrainInSituStretch(BaseXmlModel, tag="prestrain", extra="forbid"):
1055
+ type: Literal["in-situ stretch"] = attr(default="in-situ stretch", frozen=True)
1056
+ stretch: InSituStretch = element()
1057
+ ischoric: Literal[0, 1] = element(default=1)
1058
+
1059
+
1060
+ class PrestrainRamp(BaseXmlModel, tag="ramp", extra="forbid"):
1061
+ lc: int = attr(ge=1)
1062
+ text: float = 1.0
1063
+
1064
+
1065
+ class PrestrainGradient(BaseXmlModel, tag="prestrain", extra="forbid"):
1066
+ type: Literal["prestrain gradient"] = attr(default="prestrain gradient", frozen=True)
1067
+ ramp: PrestrainRamp = element()
1068
+ F0: MatStringFloatVec9 = element(default=MaterialParameter(text="1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0"))
1069
+
1070
+
1071
+ class PrestrainElastic(MaterialBaseNoDensity, tag="material", extra="forbid"):
1072
+ type: Literal["prestrain elastic"] = attr(default="prestrain elastic", frozen=True)
1073
+ elastic: UnconstrainedMaterials | SolidMixture = element(default=TransIsoMooneyRivlin(id=1))
1074
+ prestrain: PrestrainInSituStretch | PrestrainGradient = element()
1075
+
1076
+
1077
+ class PrestrainElasticUC(MaterialBaseNoDensity, tag="material", extra="forbid"):
1078
+ type: Literal["prestrain elastic"] = attr(default="prestrain elastic", frozen=True)
1079
+ elastic: UncoupledMaterials | SolidMixtureUC = element(default=TransIsoMooneyRivlin(id=1))
1080
+ prestrain: PrestrainInSituStretch | PrestrainGradient = element()
1081
+
1082
+
1083
+ class ConstantIsoPerm(BaseXmlModel, tag="permeability", extra="forbid"):
1084
+ type: Literal["perm-const-iso"] = attr(default="perm-const-iso", frozen=True)
1085
+ perm: MatPositiveFloat = element(default=MaterialParameter(text=1e-3))
1086
+
1087
+
1088
+ class ExponentialIsoPerm(BaseXmlModel, tag="permeability", extra="forbid"):
1089
+ type: Literal["perm-exp-iso"] = attr(default="perm-exp-iso", frozen=True)
1090
+ perm: MatPositiveFloat = element(default=MaterialParameter(text=1e-3))
1091
+ M: MatPositiveFloat = element(default=MaterialParameter(text=1.5))
1092
+
1093
+
1094
+ class HolmesMowPerm(BaseXmlModel, tag="permeability", extra="forbid"):
1095
+ type: Literal["perm-Holmes-Mow"] = attr(default="perm-Holmes-Mow", frozen=True)
1096
+ perm: MatPositiveFloat = element(default=MaterialParameter(text=1e-3))
1097
+ M: MatNonNegativeFloat = element(default=MaterialParameter(text=1.5))
1098
+ alpha: MatNonNegativeFloat = element(default=MaterialParameter(text=2.0))
1099
+
1100
+
1101
+ class RefIsoPerm(BaseXmlModel, tag="permeability", extra="forbid"):
1102
+ type: Literal["perm-ref-iso"] = attr(default="perm-ref-iso", frozen=True)
1103
+ perm0: MatPositiveFloat = element(default=MaterialParameter(text=1e-3))
1104
+ perm1: MatPositiveFloat = element(default=MaterialParameter(text=5e-3))
1105
+ perm2: MatPositiveFloat = element(default=MaterialParameter(text=2e-3))
1106
+ M: MatNonNegativeFloat = element(default=MaterialParameter(text=1.5))
1107
+ alpha: MatNonNegativeFloat = element(default=MaterialParameter(text=2.0))
1108
+
1109
+
1110
+ class RefOrthoPerm(BaseXmlModel, tag="permeability", extra="forbid"):
1111
+ type: Literal["perm-ref-ortho"] = attr(default="perm-ref-ortho", frozen=True)
1112
+ perm0: MatPositiveFloat = element(default=MaterialParameter(text=1e-3))
1113
+ perm1: MatStringFloatVec3 = element(default=MaterialParameter(text="0.01,0.02,0.03"))
1114
+ perm2: MatStringFloatVec3 = element(default=MaterialParameter(text="0.001,0.002,0.003"))
1115
+ M0: MatNonNegativeFloat = element(default=MaterialParameter(text=0.5))
1116
+ M: MatStringFloatVec3 = element(default=MaterialParameter(text="1.5,2.0,2.5"))
1117
+ alpha0: MatNonNegativeFloat = element(default=MaterialParameter(text=2.0))
1118
+ alpha: MatStringFloatVec3 = element(default=MaterialParameter(text="2.0,2.5,3.0"))
1119
+
1120
+
1121
+ class RefTransIsoPerm(BaseXmlModel, tag="permeability", extra="forbid"):
1122
+ type: Literal["perm-ref-trans-iso"] = attr(default="perm-ref-trans-iso", frozen=True)
1123
+ perm0: MatPositiveFloat = element(default=MaterialParameter(text=2e-3))
1124
+ perm1A: MatPositiveFloat = element(default=MaterialParameter(text=1e-2))
1125
+ perm2A: MatPositiveFloat = element(default=MaterialParameter(text=1e-2))
1126
+ perm1T: MatPositiveFloat = element(default=MaterialParameter(text=1e-3))
1127
+ perm2T: MatPositiveFloat = element(default=MaterialParameter(text=1e-2))
1128
+ perm1A: MatPositiveFloat = element(default=MaterialParameter(text=5e-2))
1129
+ M0: MatNonNegativeFloat = element(default=MaterialParameter(text=1.0))
1130
+ MA: MatNonNegativeFloat = element(default=MaterialParameter(text=0.5))
1131
+ MT: MatNonNegativeFloat = element(default=MaterialParameter(text=1.5))
1132
+ alpha0: MatNonNegativeFloat = element(default=MaterialParameter(text=1.0))
1133
+ alphaA: MatNonNegativeFloat = element(default=MaterialParameter(text=0.5))
1134
+ alphaT: MatNonNegativeFloat = element(default=MaterialParameter(text=2.0))
1135
+
1136
+
1137
+ def tension_only_nonlinear_spring(slack: float, e0: float, k: float) -> str:
1138
+ """
1139
+ Blankevoort 1991 ligament model
1140
+
1141
+ :param slack: engineering strain representing amount of slack (will not produce force until slack strain is reached)
1142
+ :param e0: engineering strain where fibers are fully straigtened (start of linear region)
1143
+ :param k: elastic modulus of linear region
1144
+
1145
+ :return: A string expression of fiber force equation compatible with FEBio math interpreter
1146
+ """
1147
+
1148
+ toe_region = f"H(x - {slack:.5f}) * ({0.5 / e0 * k:.5f} * (x - {slack:.5f}) ^ 2) * (1.0 - H(x -{slack + e0:.5f}))"
1149
+ linear_region = f"H(x - {slack + e0:.5f}) * {k:.5f} * (x - {slack} - {e0 / 2.0:.5f})"
1150
+
1151
+ return " + ".join([toe_region, linear_region])
1152
+
1153
+
1154
+ PermeabilityType = ConstantIsoPerm | ExponentialIsoPerm | HolmesMowPerm | RefIsoPerm | RefOrthoPerm | RefTransIsoPerm
1155
+
1156
+
1157
+ class SolventSupply(BaseXmlModel, tag="solvent_supply", extra="forbid"):
1158
+ type: Literal["Starling"] = attr(default="Starling", frozen=True)
1159
+ kp: MatPositiveFloat = element(default=0.001)
1160
+ pv: MatPositiveFloat = element(default=0.1)
1161
+
1162
+
1163
+ class BiphasicMaterial(MaterialBaseNoDensity, tag="material", extra="forbid"):
1164
+ type: Literal["biphasic"] = attr(default="biphasic", frozen=True)
1165
+ fluid_density: MatPositiveFloat = element(default=MaterialParameter(text=1.0))
1166
+ phi0: MatPositiveFloat = element(default=MaterialParameter(text=0.2))
1167
+ tau: NonNegativeFloat | None = element(default=None)
1168
+ solid: UnconstrainedMaterials | UncoupledMaterials | SolidMixture | SolidMixtureUC = element(default=NeoHookean(id=1), tag="solid")
1169
+ permeability: PermeabilityType = element(default=ConstantIsoPerm())
1170
+ solvent_supply: SolventSupply | None = element(default=None)
1171
+
1172
+
1173
+ MaterialType = (
1174
+ UnconstrainedMaterials
1175
+ | EvolvingUnconstrainedMaterials
1176
+ | UncoupledMaterials
1177
+ | RigidBody
1178
+ | SolidMixture
1179
+ | SolidMixtureUC
1180
+ | BiphasicMaterial
1181
+ | ViscoelasticMaterial
1182
+ | ViscoelasticMaterialUC
1183
+ )
1184
+
1185
+
1186
+ class Material(BaseXmlModel, validate_assignment=True):
1187
+ all_materials: list[MaterialType] = element(tag="material", default=[])
1188
+
1189
+ def add_material(self, material: MaterialType):
1190
+ material.id = len(self.all_materials) + 1
1191
+ self.all_materials.append(material)