Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
verifyConfiguration.py
Go to the documentation of this file.
1"""Verify the tutorial's three circular platelet families in generated frame 0."""
2import argparse
3from pathlib import Path
4import re
5import numpy as np
6
7parser = argparse.ArgumentParser(description=__doc__)
8parser.add_argument("--output-dir", type=Path, default=Path(__file__).resolve().parent)
9folder = parser.parse_args().output_dir
10
11
12def read_value(path, name):
13 text = re.sub(r"#.*", "", path.read_text())
14 match = re.search(r"(?:^|;)\s*" + re.escape(name) + r"\s*=([^;]*);", text)
15 if match is None:
16 raise ValueError(f"Missing {name} in {path}")
17 return np.fromstring(match.group(1), sep=" ")
18
19
20inputs = folder / "inputFiles"
21C2G = read_value(inputs / "polycrystal.txt", "C2G1").reshape(3, 3)
22F = read_value(inputs / "polycrystal.txt", "F").reshape(3, 3)
23b = read_value(inputs / "W.txt", "b_SI")[0]
24volume_SI = abs(np.linalg.det(F)) * b**3
25lines = (folder / "config/evl_0.txt").read_text().splitlines()
26counts = [int(line) for line in lines[:11]]
27start = 11 + sum(counts[:5])
28records = np.array([np.fromstring(line, sep=" ") for line in lines[start:start + counts[5]]])
29np.testing.assert_allclose(C2G, np.eye(3), atol=1e-12)
30offset = 0
31for family, normal in [('100', [1, 0, 0]), ('010', [0, 1, 0]), ('001', [0, 0, 1])]:
32 inclusion = inputs / f"ellipsoidalInclusionsDensity_{family}.txt"
33 target = read_value(inclusion, "targetDensity")[0]
34 count = int(np.ceil(target * volume_SI))
35 crystal_axes = read_value(inclusion, "crystalAxes").reshape(3, 3)
36 means = read_value(inclusion, "axesLognormalDistributionMean_SI")
37 crystal_distortion = read_value(inclusion, "crystalEigenDistortion").reshape(3, 3)
38 np.testing.assert_allclose(read_value(inclusion, "patternVector_SI"), np.zeros(3))
39 np.testing.assert_allclose(read_value(inclusion, "axesLognormalDistributionStd_SI"), np.zeros(3))
40 family_records = records[offset:offset + count]
41 if len(family_records) != count:
42 raise ValueError(f"Missing platelets for family {family}")
43 for record in family_records:
44 axes = record[4:13].reshape(3, 3) * b
45 lengths = np.linalg.norm(axes, axis=0)
46 np.testing.assert_allclose(2 * lengths, [40e-9, 40e-9, 3e-9], rtol=1e-12, atol=1e-22)
47 np.testing.assert_allclose(axes[:, 2] / lengths[2], normal, atol=1e-12)
48 np.testing.assert_allclose(axes, C2G @ crystal_axes @ np.diag(means), rtol=1e-12, atol=1e-22)
49 np.testing.assert_allclose(record[13:22].reshape(3, 3),
50 C2G @ crystal_distortion @ C2G.T, atol=1e-14)
51 offset += count
52 print(f"PASS: {count} circular platelets on ({family}), diameter 40 nm, thickness 3 nm.")
53if counts[5] != offset:
54 raise ValueError(f"Expected {offset} total platelets, found {counts[5]}")
55print("PASS: all three families have correct geometry/tensors and no positional pattern.")