metafold 0.15.dev1__tar.gz → 0.15.dev2__tar.gz
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.
- {metafold-0.15.dev1 → metafold-0.15.dev2}/PKG-INFO +1 -1
- {metafold-0.15.dev1 → metafold-0.15.dev2}/metafold/materials.py +18 -4
- {metafold-0.15.dev1 → metafold-0.15.dev2}/metafold.egg-info/PKG-INFO +1 -1
- {metafold-0.15.dev1 → metafold-0.15.dev2}/pyproject.toml +1 -1
- {metafold-0.15.dev1 → metafold-0.15.dev2}/tests/test_materials.py +48 -3
- {metafold-0.15.dev1 → metafold-0.15.dev2}/LICENSE +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/README.md +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/metafold/__init__.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/metafold/api.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/metafold/assets.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/metafold/auth.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/metafold/client.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/metafold/exceptions.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/metafold/jobs.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/metafold/projects.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/metafold/simulation/__init__.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/metafold/simulation/compression_experiment.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/metafold/simulation/compression_simulation.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/metafold/simulation/run_experiment.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/metafold/utils.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/metafold/workflows.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/metafold.egg-info/SOURCES.txt +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/metafold.egg-info/dependency_links.txt +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/metafold.egg-info/requires.txt +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/metafold.egg-info/top_level.txt +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/setup.cfg +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/tests/test_assets.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/tests/test_compession_experiment.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/tests/test_compression_simulation.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/tests/test_jobs.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/tests/test_projects.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/tests/test_run_experiment.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/tests/test_shear_simulation.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/tests/test_utils.py +0 -0
- {metafold-0.15.dev1 → metafold-0.15.dev2}/tests/test_workflows.py +0 -0
|
@@ -232,11 +232,14 @@ class HyperfoamTerm:
|
|
|
232
232
|
class HyperfoamParams(ParamsBase):
|
|
233
233
|
"""Ogden hyperfoam (mpmgpu only; no Uintah equivalent).
|
|
234
234
|
|
|
235
|
+
The Ogden hyperfoam model is defined entirely by its terms (bulk_modulus is
|
|
236
|
+
not used, so it is not part of this material; a legacy "bulk_modulus"/"K" is
|
|
237
|
+
ignored if present on from_dict).
|
|
238
|
+
|
|
235
239
|
An optional viscoelastic overlay (Prony series) may be supplied via
|
|
236
240
|
terminal_shear_modulus + viscoelastic_series, matching the MaxwellWeichert
|
|
237
241
|
mode structure. Omit both for a purely elastic hyperfoam.
|
|
238
242
|
"""
|
|
239
|
-
bulk_modulus: float
|
|
240
243
|
terms: List[HyperfoamTerm]
|
|
241
244
|
terminal_shear_modulus: Optional[float] = None
|
|
242
245
|
viscoelastic_series: Optional[List[ViscoelasticMode]] = None
|
|
@@ -247,7 +250,6 @@ class HyperfoamParams(ParamsBase):
|
|
|
247
250
|
|
|
248
251
|
def to_dict(self):
|
|
249
252
|
d = {
|
|
250
|
-
"bulk_modulus": float(self.bulk_modulus),
|
|
251
253
|
"terms": [t.to_dict() for t in self.terms],
|
|
252
254
|
}
|
|
253
255
|
if self.terminal_shear_modulus is not None:
|
|
@@ -258,9 +260,9 @@ class HyperfoamParams(ParamsBase):
|
|
|
258
260
|
|
|
259
261
|
@classmethod
|
|
260
262
|
def from_dict(cls, d: dict) -> "HyperfoamParams":
|
|
263
|
+
# A legacy bulk_modulus/K is ignored (older scripts may still send it).
|
|
261
264
|
series = d.get("viscoelastic_series")
|
|
262
265
|
return cls(
|
|
263
|
-
bulk_modulus=d["bulk_modulus"],
|
|
264
266
|
terms=[
|
|
265
267
|
HyperfoamTerm(
|
|
266
268
|
mu=t["mu"], alpha=t["alpha"], poisson_ratio=t["poisson_ratio"])
|
|
@@ -459,7 +461,19 @@ class Material:
|
|
|
459
461
|
]
|
|
460
462
|
PARAMS_CLASSES = {c.get_type(): c for c in params_classes}
|
|
461
463
|
cm = d["constitutive_model"]
|
|
462
|
-
|
|
464
|
+
model_type = cm.get("type")
|
|
465
|
+
if model_type not in PARAMS_CLASSES:
|
|
466
|
+
# ValueError so API callers reject with a 400, not a 500. An
|
|
467
|
+
# unknown type usually means a client newer than the server.
|
|
468
|
+
raise ValueError(
|
|
469
|
+
f"Unknown constitutive model type {model_type!r}. "
|
|
470
|
+
f"Known types: {', '.join(sorted(PARAMS_CLASSES))}.")
|
|
471
|
+
try:
|
|
472
|
+
params = PARAMS_CLASSES[model_type].from_dict(cm["params"])
|
|
473
|
+
except KeyError as e:
|
|
474
|
+
# Missing param -> ValueError (400) rather than an uncaught 500.
|
|
475
|
+
raise ValueError(
|
|
476
|
+
f"{model_type} material is missing required param {e}.")
|
|
463
477
|
return cls(
|
|
464
478
|
density=d["density"],
|
|
465
479
|
thermal_conductivity=d["thermal_conductivity"],
|
|
@@ -292,7 +292,6 @@ class TestHyperfoamParams:
|
|
|
292
292
|
specific_heat=1.36,
|
|
293
293
|
constitutive_model=ConstitutiveModel(
|
|
294
294
|
params=HyperfoamParams(
|
|
295
|
-
bulk_modulus=1.0e6,
|
|
296
295
|
terms=[
|
|
297
296
|
HyperfoamTerm(mu=0.16e6, alpha=8.9, poisson_ratio=0.0),
|
|
298
297
|
HyperfoamTerm(mu=0.01e6, alpha=-2.0, poisson_ratio=0.0),
|
|
@@ -307,10 +306,30 @@ class TestHyperfoamParams:
|
|
|
307
306
|
|
|
308
307
|
def test_type_key(self):
|
|
309
308
|
d = ConstitutiveModel(
|
|
310
|
-
params=HyperfoamParams(
|
|
309
|
+
params=HyperfoamParams(terms=[])
|
|
311
310
|
).to_dict()
|
|
312
311
|
assert d["type"] == "hyperfoam"
|
|
313
312
|
|
|
313
|
+
def test_bulk_modulus_not_emitted(self):
|
|
314
|
+
# bulk_modulus is not part of the Ogden hyperfoam model.
|
|
315
|
+
d = self._material().constitutive_model.params.to_dict()
|
|
316
|
+
assert "bulk_modulus" not in d
|
|
317
|
+
assert "K" not in d
|
|
318
|
+
|
|
319
|
+
def test_legacy_bulk_modulus_ignored_on_from_dict(self):
|
|
320
|
+
# Older scripts / GH plugins may still send bulk_modulus or K — ignore it.
|
|
321
|
+
d = {
|
|
322
|
+
"type": "hyperfoam",
|
|
323
|
+
"params": {
|
|
324
|
+
"bulk_modulus": 1.0e6,
|
|
325
|
+
"K": 2.0e6,
|
|
326
|
+
"terms": [{"mu": 0.16e6, "alpha": 8.9, "poisson_ratio": 0.0}],
|
|
327
|
+
},
|
|
328
|
+
}
|
|
329
|
+
params = HyperfoamParams.from_dict(d["params"])
|
|
330
|
+
assert len(params.terms) == 1
|
|
331
|
+
assert "bulk_modulus" not in params.to_dict()
|
|
332
|
+
|
|
314
333
|
def test_terms_preserved(self):
|
|
315
334
|
d = self._material().constitutive_model.params.to_dict()
|
|
316
335
|
assert len(d["terms"]) == 2
|
|
@@ -331,7 +350,6 @@ class TestHyperfoamParams:
|
|
|
331
350
|
specific_heat=1.36,
|
|
332
351
|
constitutive_model=ConstitutiveModel(
|
|
333
352
|
params=HyperfoamParams(
|
|
334
|
-
bulk_modulus=1.0e6,
|
|
335
353
|
terms=[HyperfoamTerm(mu=0.16e6, alpha=8.9, poisson_ratio=0.0)],
|
|
336
354
|
terminal_shear_modulus=5.0e4,
|
|
337
355
|
viscoelastic_series=[
|
|
@@ -389,3 +407,30 @@ class TestOrthotropicParams:
|
|
|
389
407
|
d = m.to_dict()
|
|
390
408
|
d["constitutive_model"]["params"]["direction_a"] = "1 0 0"
|
|
391
409
|
assert OrthotropicParams.from_dict(d["constitutive_model"]["params"]).direction_a == [1.0, 0.0, 0.0]
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
class TestMaterialFromDictErrors:
|
|
413
|
+
# from_dict must raise ValueError (not KeyError) so API callers return 400,
|
|
414
|
+
# not 500. See lightcycle experiments blueprint.
|
|
415
|
+
def _material_dict(self, mtype, params):
|
|
416
|
+
return {
|
|
417
|
+
"density": 1000.0, "thermal_conductivity": 1.0, "specific_heat": 1500,
|
|
418
|
+
"constitutive_model": {"type": mtype, "params": params},
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
def test_unknown_type_raises_value_error(self):
|
|
422
|
+
# A client newer than the server sends a type we don't know.
|
|
423
|
+
d = self._material_dict("some_future_type", {})
|
|
424
|
+
with pytest.raises(ValueError, match="Unknown constitutive model type"):
|
|
425
|
+
Material.from_dict(d)
|
|
426
|
+
|
|
427
|
+
def test_missing_param_raises_value_error(self):
|
|
428
|
+
params = {
|
|
429
|
+
"E1": 1e9, "E2": 1e9, "E3": 1e9,
|
|
430
|
+
"nu12": 0.3, "nu13": 0.3, "nu23": 0.3,
|
|
431
|
+
"G12": 5e8, "G13": 5e8, "G23": 5e8,
|
|
432
|
+
"direction_a": [1.0, 0.0, 0.0], "direction_b": [0.0, 1.0, 0.0],
|
|
433
|
+
}
|
|
434
|
+
del params["E1"]
|
|
435
|
+
with pytest.raises(ValueError, match="missing required param"):
|
|
436
|
+
Material.from_dict(self._material_dict("orthotropic", params))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|