1"""Verify the tutorial's three circular platelet families in generated frame 0."""
3from pathlib
import Path
7parser = argparse.ArgumentParser(description=__doc__)
8parser.add_argument(
"--output-dir", type=Path, default=
Path(__file__).resolve().parent)
9folder = parser.parse_args().output_dir
13 text = re.sub(
r"#.*",
"", path.read_text())
14 match = re.search(
r"(?:^|;)\s*" + re.escape(name) +
r"\s*=([^;]*);", text)
16 raise ValueError(f
"Missing {name} in {path}")
17 return np.fromstring(match.group(1), sep=
" ")
20inputs = folder /
"inputFiles"
21C2G =
read_value(inputs /
"polycrystal.txt",
"C2G1").reshape(3, 3)
22F =
read_value(inputs /
"polycrystal.txt",
"F").reshape(3, 3)
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)
31for family, normal
in [(
'100', [1, 0, 0]), (
'010', [0, 1, 0]), (
'001', [0, 0, 1])]:
32 inclusion = inputs / f
"ellipsoidalInclusionsDensity_{family}.txt"
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)
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.")