midas-diffract 0.2.0__tar.gz → 0.4.0__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.
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/PKG-INFO +2 -1
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/midas_diffract/__init__.py +1 -1
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/midas_diffract/forward.py +69 -41
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/midas_diffract.egg-info/PKG-INFO +2 -1
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/midas_diffract.egg-info/requires.txt +1 -0
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/pyproject.toml +2 -1
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/tests/test_forward.py +90 -0
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/LICENSE +0 -0
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/README.md +0 -0
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/midas_diffract/hkls.py +0 -0
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/midas_diffract/losses.py +0 -0
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/midas_diffract/optimize.py +0 -0
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/midas_diffract/simulate_panel_zarrs.py +0 -0
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/midas_diffract.egg-info/SOURCES.txt +0 -0
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/midas_diffract.egg-info/dependency_links.txt +0 -0
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/midas_diffract.egg-info/top_level.txt +0 -0
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/setup.cfg +0 -0
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/tests/test_c_comparison.py +0 -0
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/tests/test_distortion_layer.py +0 -0
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/tests/test_hkls.py +0 -0
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/tests/test_losses.py +0 -0
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/tests/test_multi_detector.py +0 -0
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/tests/test_strain_tensor.py +0 -0
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/tests/test_tilts.py +0 -0
- {midas_diffract-0.2.0 → midas_diffract-0.4.0}/tests/test_wedge.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: midas-diffract
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: End-to-end differentiable forward model for High-Energy Diffraction Microscopy (FF, NF, pf-HEDM)
|
|
5
5
|
Author-email: Hemant Sharma <hsharma@anl.gov>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -19,6 +19,7 @@ License-File: LICENSE
|
|
|
19
19
|
Requires-Dist: numpy>=1.22
|
|
20
20
|
Requires-Dist: torch>=2.0
|
|
21
21
|
Requires-Dist: midas-distortion>=0.2.0
|
|
22
|
+
Requires-Dist: midas-stress>=0.8.0
|
|
22
23
|
Provides-Extra: dev
|
|
23
24
|
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
24
25
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
@@ -34,6 +34,16 @@ import torch
|
|
|
34
34
|
import torch.nn as nn
|
|
35
35
|
import torch.nn.functional as F
|
|
36
36
|
|
|
37
|
+
# Canonical orientation + strain-frame primitives. midas_stress is the single
|
|
38
|
+
# source of truth for this math (Bunge ZXZ orientation algebra, sample<->crystal
|
|
39
|
+
# strain rotation); its torch backend is differentiable end-to-end and
|
|
40
|
+
# device-portable, so the forward model delegates rather than re-porting.
|
|
41
|
+
# NOTE: midas_stress's Voigt is Voigt-MANDEL (sqrt2 on shears); this model uses
|
|
42
|
+
# PLAIN-Voigt / raw 3x3 strain, so we only delegate the *rotation*, never the
|
|
43
|
+
# Voigt packing (see rotate_strain_sample_to_crystal / correct_hkls_latc).
|
|
44
|
+
from midas_stress.orientation import euler_to_orient_mat as _ms_euler_to_orient_mat
|
|
45
|
+
from midas_stress.tensor import strain_lab_to_grain as _ms_strain_lab_to_grain
|
|
46
|
+
|
|
37
47
|
|
|
38
48
|
# ---------------------------------------------------------------------------
|
|
39
49
|
# Configuration data classes
|
|
@@ -437,7 +447,13 @@ class HEDMForwardModel(nn.Module):
|
|
|
437
447
|
|
|
438
448
|
@staticmethod
|
|
439
449
|
def euler2mat(euler_angles: torch.Tensor) -> torch.Tensor:
|
|
440
|
-
"""Convert ZXZ Euler angles to rotation matrices.
|
|
450
|
+
"""Convert ZXZ (Bunge) Euler angles to crystal->sample rotation matrices.
|
|
451
|
+
|
|
452
|
+
Delegates to ``midas_stress.orientation.euler_to_orient_mat`` -- the
|
|
453
|
+
canonical orientation primitive -- so the convention can never drift
|
|
454
|
+
from the rest of MIDAS. midas_stress's torch backend is differentiable
|
|
455
|
+
and vmap-safe; the result is identical to the former in-line ZXZ build
|
|
456
|
+
(R = Rz(phi1) @ Rx(Phi) @ Rz(phi2)) to ~1e-16.
|
|
441
457
|
|
|
442
458
|
Parameters
|
|
443
459
|
----------
|
|
@@ -447,35 +463,14 @@ class HEDMForwardModel(nn.Module):
|
|
|
447
463
|
Returns
|
|
448
464
|
-------
|
|
449
465
|
Tensor (..., 3, 3)
|
|
450
|
-
Rotation matrices.
|
|
466
|
+
Rotation matrices (crystal->sample), orthogonalized onto SO(3).
|
|
451
467
|
"""
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
# ZXZ rotation matrix: R = Rz(phi1) @ Rx(Phi) @ Rz(phi2)
|
|
459
|
-
# Verified element-by-element against nfhedm.py lines 114-120.
|
|
460
|
-
# Built via torch.stack rather than indexed assignment so the function
|
|
461
|
-
# composes with torch.func.vmap (in-place writes block vmap).
|
|
462
|
-
row0 = torch.stack([
|
|
463
|
-
c0 * c2 - s0 * c1 * s2,
|
|
464
|
-
-s0 * c1 * c2 - c0 * s2,
|
|
465
|
-
s0 * s1,
|
|
466
|
-
], dim=-1)
|
|
467
|
-
row1 = torch.stack([
|
|
468
|
-
s0 * c2 + c0 * c1 * s2,
|
|
469
|
-
c0 * c1 * c2 - s0 * s2,
|
|
470
|
-
-c0 * s1,
|
|
471
|
-
], dim=-1)
|
|
472
|
-
row2 = torch.stack([
|
|
473
|
-
s1 * s2,
|
|
474
|
-
s1 * c2,
|
|
475
|
-
c1,
|
|
476
|
-
], dim=-1)
|
|
477
|
-
R = torch.stack([row0, row1, row2], dim=-2)
|
|
478
|
-
|
|
468
|
+
if not isinstance(euler_angles, torch.Tensor):
|
|
469
|
+
euler_angles = torch.as_tensor(euler_angles)
|
|
470
|
+
R = _ms_euler_to_orient_mat(euler_angles) # (..., 9), torch
|
|
471
|
+
R = R.reshape(*R.shape[:-1], 3, 3)
|
|
472
|
+
# midas_stress already returns a proper rotation; orthogonalize keeps the
|
|
473
|
+
# historical "exactly on SO(3)" guarantee and is idempotent here.
|
|
479
474
|
return HEDMForwardModel.orthogonalize(R)
|
|
480
475
|
|
|
481
476
|
# ------------------------------------------------------------------
|
|
@@ -525,6 +520,28 @@ class HEDMForwardModel(nn.Module):
|
|
|
525
520
|
"""Numerically stable arccos: clamp to [-1+eps, 1-eps]."""
|
|
526
521
|
return torch.acos(torch.clamp(x, -1.0 + self.epsilon, 1.0 - self.epsilon))
|
|
527
522
|
|
|
523
|
+
# ------------------------------------------------------------------
|
|
524
|
+
# strain_as_voigt (accept full 3x3 tensor OR plain-Voigt 6-vector)
|
|
525
|
+
# ------------------------------------------------------------------
|
|
526
|
+
|
|
527
|
+
@staticmethod
|
|
528
|
+
def strain_as_voigt(strain: torch.Tensor) -> torch.Tensor:
|
|
529
|
+
"""Normalize a strain input to PLAIN-Voigt [e11,e12,e13,e22,e23,e33].
|
|
530
|
+
|
|
531
|
+
Accepts either a plain-Voigt ``(..., 6)`` tensor (returned unchanged) or
|
|
532
|
+
a full symmetric ``(..., 3, 3)`` strain tensor. The 3x3 path is
|
|
533
|
+
convention-free -- the natural way to hand a strain field straight from
|
|
534
|
+
a tensor source (e.g. a midas_stress strain field) into the forward
|
|
535
|
+
model without picking a Voigt/Mandel packing. The off-diagonals are
|
|
536
|
+
taken as TRUE tensor components (no factor of 2).
|
|
537
|
+
"""
|
|
538
|
+
if strain.dim() >= 2 and strain.shape[-1] == 3 and strain.shape[-2] == 3:
|
|
539
|
+
return torch.stack([
|
|
540
|
+
strain[..., 0, 0], strain[..., 0, 1], strain[..., 0, 2],
|
|
541
|
+
strain[..., 1, 1], strain[..., 1, 2], strain[..., 2, 2],
|
|
542
|
+
], dim=-1)
|
|
543
|
+
return strain
|
|
544
|
+
|
|
528
545
|
# ------------------------------------------------------------------
|
|
529
546
|
# rotate_strain_sample_to_crystal (port of C RotateStrainSampleToCrystal)
|
|
530
547
|
# ------------------------------------------------------------------
|
|
@@ -536,19 +553,27 @@ class HEDMForwardModel(nn.Module):
|
|
|
536
553
|
) -> torch.Tensor:
|
|
537
554
|
"""Rotate a symmetric infinitesimal strain from sample to crystal frame.
|
|
538
555
|
|
|
539
|
-
|
|
556
|
+
Matches ``RotateStrainSampleToCrystal`` from
|
|
540
557
|
``FF_HEDM/src/ForwardSimulationCompressed.c:399-419``:
|
|
541
|
-
eps_crystal = OM^T . eps_sample . OM
|
|
542
|
-
|
|
558
|
+
eps_crystal = OM^T . eps_sample . OM.
|
|
559
|
+
|
|
560
|
+
The rotation is delegated to ``midas_stress.tensor.strain_lab_to_grain``
|
|
561
|
+
(the canonical sample/lab -> crystal/grain strain transform; bit-identical
|
|
562
|
+
to the former in-line ``OM^T S OM``). PLAIN-Voigt pack/unpack is kept here
|
|
563
|
+
on purpose -- midas_stress's Voigt is Mandel (sqrt2 on shears), which must
|
|
564
|
+
not touch the forward model's strain input.
|
|
543
565
|
|
|
544
566
|
Parameters
|
|
545
567
|
----------
|
|
546
568
|
orientation_matrices : Tensor (..., 3, 3)
|
|
569
|
+
Crystal->sample matrices (as returned by :meth:`euler2mat`).
|
|
547
570
|
strain_sample : Tensor (..., 6)
|
|
571
|
+
PLAIN-Voigt [eps_11, eps_12, eps_13, eps_22, eps_23, eps_33].
|
|
548
572
|
|
|
549
573
|
Returns
|
|
550
574
|
-------
|
|
551
575
|
strain_crystal : Tensor (..., 6)
|
|
576
|
+
PLAIN-Voigt, same layout.
|
|
552
577
|
"""
|
|
553
578
|
e = strain_sample
|
|
554
579
|
S = torch.stack([
|
|
@@ -556,8 +581,7 @@ class HEDMForwardModel(nn.Module):
|
|
|
556
581
|
torch.stack([e[..., 1], e[..., 3], e[..., 4]], dim=-1),
|
|
557
582
|
torch.stack([e[..., 2], e[..., 4], e[..., 5]], dim=-1),
|
|
558
583
|
], dim=-2)
|
|
559
|
-
|
|
560
|
-
C = torch.matmul(torch.matmul(OM.transpose(-1, -2), S), OM)
|
|
584
|
+
C = _ms_strain_lab_to_grain(S, orientation_matrices) # OM^T S OM
|
|
561
585
|
return torch.stack([
|
|
562
586
|
C[..., 0, 0], C[..., 0, 1], C[..., 0, 2],
|
|
563
587
|
C[..., 1, 1], C[..., 1, 2], C[..., 2, 2],
|
|
@@ -587,10 +611,12 @@ class HEDMForwardModel(nn.Module):
|
|
|
587
611
|
lattice_params : Tensor (..., 6)
|
|
588
612
|
[a, b, c, alpha, beta, gamma] in Angstroms and degrees.
|
|
589
613
|
The ``...`` dimensions allow per-voxel or per-grain parameters.
|
|
590
|
-
strain : Tensor (..., 6), optional
|
|
591
|
-
Crystal-frame symmetric infinitesimal strain
|
|
592
|
-
[eps_11, eps_12, eps_13, eps_22, eps_23, eps_33]
|
|
593
|
-
|
|
614
|
+
strain : Tensor (..., 6) or (..., 3, 3), optional
|
|
615
|
+
Crystal-frame symmetric infinitesimal strain, either PLAIN-Voigt
|
|
616
|
+
[eps_11, eps_12, eps_13, eps_22, eps_23, eps_33] or a full symmetric
|
|
617
|
+
3x3 tensor (normalized via :meth:`strain_as_voigt`; off-diagonals are
|
|
618
|
+
true tensor components, no factor of 2). When supplied, the
|
|
619
|
+
reciprocal lattice is post-multiplied by (I + eps)^{-1}:
|
|
594
620
|
B = (I + eps)^{-1} @ B0. Use :meth:`rotate_strain_sample_to_crystal`
|
|
595
621
|
to convert a sample-frame strain into the crystal frame.
|
|
596
622
|
|
|
@@ -671,6 +697,7 @@ class HEDMForwardModel(nn.Module):
|
|
|
671
697
|
# Voigt layout matches C CorrectHKLsLatCEpsilon:
|
|
672
698
|
# eps = [eps_11, eps_12, eps_13, eps_22, eps_23, eps_33]
|
|
673
699
|
if strain is not None:
|
|
700
|
+
strain = self.strain_as_voigt(strain) # accept full 3x3 too
|
|
674
701
|
e11 = strain[..., 0]
|
|
675
702
|
e12 = strain[..., 1]
|
|
676
703
|
e13 = strain[..., 2]
|
|
@@ -1311,9 +1338,10 @@ class HEDMForwardModel(nn.Module):
|
|
|
1311
1338
|
lattice_params : Tensor (..., 6) or (..., N, 6), optional
|
|
1312
1339
|
Strained lattice parameters [a,b,c,alpha,beta,gamma] in
|
|
1313
1340
|
Angstroms/degrees. None = use nominal hkls/thetas (no strain).
|
|
1314
|
-
strain : Tensor (..., 6)
|
|
1315
|
-
Crystal-frame symmetric infinitesimal strain
|
|
1316
|
-
[eps_11, eps_12, eps_13, eps_22, eps_23, eps_33]
|
|
1341
|
+
strain : Tensor (..., 6), (..., N, 6), or (..., 3, 3), optional
|
|
1342
|
+
Crystal-frame symmetric infinitesimal strain, either PLAIN-Voigt
|
|
1343
|
+
[eps_11, eps_12, eps_13, eps_22, eps_23, eps_33] or a full symmetric
|
|
1344
|
+
3x3 tensor (see :meth:`strain_as_voigt`). Applied as
|
|
1317
1345
|
B = (I + eps)^{-1} @ B0 in addition to any lattice-parameter
|
|
1318
1346
|
strain expressed through ``lattice_params``. Requires
|
|
1319
1347
|
``lattice_params`` to be supplied.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: midas-diffract
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: End-to-end differentiable forward model for High-Energy Diffraction Microscopy (FF, NF, pf-HEDM)
|
|
5
5
|
Author-email: Hemant Sharma <hsharma@anl.gov>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -19,6 +19,7 @@ License-File: LICENSE
|
|
|
19
19
|
Requires-Dist: numpy>=1.22
|
|
20
20
|
Requires-Dist: torch>=2.0
|
|
21
21
|
Requires-Dist: midas-distortion>=0.2.0
|
|
22
|
+
Requires-Dist: midas-stress>=0.8.0
|
|
22
23
|
Provides-Extra: dev
|
|
23
24
|
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
24
25
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "midas-diffract"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.4.0"
|
|
8
8
|
description = "End-to-end differentiable forward model for High-Energy Diffraction Microscopy (FF, NF, pf-HEDM)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "BSD-3-Clause"
|
|
@@ -27,6 +27,7 @@ dependencies = [
|
|
|
27
27
|
"numpy>=1.22",
|
|
28
28
|
"torch>=2.0",
|
|
29
29
|
"midas-distortion>=0.2.0",
|
|
30
|
+
"midas-stress>=0.8.0",
|
|
30
31
|
]
|
|
31
32
|
|
|
32
33
|
[project.optional-dependencies]
|
|
@@ -1111,5 +1111,95 @@ class TestCrossValidation:
|
|
|
1111
1111
|
import torch.nn.functional as F # for test_2d_position_backward_compat
|
|
1112
1112
|
|
|
1113
1113
|
|
|
1114
|
+
# ===================================================================
|
|
1115
|
+
# Test: midas_stress is the canonical orientation/strain-frame source
|
|
1116
|
+
# ===================================================================
|
|
1117
|
+
|
|
1118
|
+
class TestMidasStressDelegation:
|
|
1119
|
+
"""Guards that euler2mat / rotate_strain_sample_to_crystal delegate to
|
|
1120
|
+
midas_stress and never silently re-port (convention drift)."""
|
|
1121
|
+
|
|
1122
|
+
def test_euler2mat_matches_midas_stress(self):
|
|
1123
|
+
from midas_stress.orientation import euler_to_orient_mat
|
|
1124
|
+
torch.manual_seed(0)
|
|
1125
|
+
eul = torch.rand(7, 3, dtype=torch.float64) * 2 * math.pi
|
|
1126
|
+
R = HEDMForwardModel.euler2mat(eul)
|
|
1127
|
+
R_ms = euler_to_orient_mat(eul).reshape(7, 3, 3)
|
|
1128
|
+
torch.testing.assert_close(R, R_ms, atol=1e-12, rtol=0)
|
|
1129
|
+
|
|
1130
|
+
def test_euler2mat_vmap_safe(self):
|
|
1131
|
+
from torch.func import vmap
|
|
1132
|
+
eul = torch.rand(5, 3, dtype=torch.float64) * 2 * math.pi
|
|
1133
|
+
R = vmap(HEDMForwardModel.euler2mat)(eul)
|
|
1134
|
+
assert R.shape == (5, 3, 3)
|
|
1135
|
+
torch.testing.assert_close(R, HEDMForwardModel.euler2mat(eul), atol=1e-12, rtol=0)
|
|
1136
|
+
|
|
1137
|
+
def test_euler2mat_differentiable(self):
|
|
1138
|
+
eul = torch.rand(3, 3, dtype=torch.float64, requires_grad=True)
|
|
1139
|
+
HEDMForwardModel.euler2mat(eul).pow(2).sum().backward()
|
|
1140
|
+
assert eul.grad is not None and torch.all(torch.isfinite(eul.grad))
|
|
1141
|
+
|
|
1142
|
+
def test_rotate_strain_matches_midas_stress(self):
|
|
1143
|
+
from midas_stress.tensor import strain_lab_to_grain
|
|
1144
|
+
torch.manual_seed(1)
|
|
1145
|
+
OM = HEDMForwardModel.euler2mat(torch.rand(4, 3, dtype=torch.float64))
|
|
1146
|
+
v = torch.rand(4, 6, dtype=torch.float64) * 1e-3 # plain Voigt
|
|
1147
|
+
out = HEDMForwardModel.rotate_strain_sample_to_crystal(OM, v)
|
|
1148
|
+
# reference: build 3x3, rotate via midas_stress, repack plain Voigt
|
|
1149
|
+
S = torch.zeros(4, 3, 3, dtype=torch.float64)
|
|
1150
|
+
S[:, 0, 0], S[:, 1, 1], S[:, 2, 2] = v[:, 0], v[:, 3], v[:, 5]
|
|
1151
|
+
S[:, 0, 1] = S[:, 1, 0] = v[:, 1]
|
|
1152
|
+
S[:, 0, 2] = S[:, 2, 0] = v[:, 2]
|
|
1153
|
+
S[:, 1, 2] = S[:, 2, 1] = v[:, 4]
|
|
1154
|
+
C = strain_lab_to_grain(S, OM)
|
|
1155
|
+
ref = torch.stack([C[:, 0, 0], C[:, 0, 1], C[:, 0, 2],
|
|
1156
|
+
C[:, 1, 1], C[:, 1, 2], C[:, 2, 2]], dim=-1)
|
|
1157
|
+
torch.testing.assert_close(out, ref, atol=1e-14, rtol=0)
|
|
1158
|
+
|
|
1159
|
+
|
|
1160
|
+
# ===================================================================
|
|
1161
|
+
# Test: full 3x3 strain tensor entry point (convention-free)
|
|
1162
|
+
# ===================================================================
|
|
1163
|
+
|
|
1164
|
+
class TestStrainTensorInput:
|
|
1165
|
+
"""A full symmetric 3x3 strain must give the same result as the
|
|
1166
|
+
equivalent plain-Voigt 6-vector (NOT Voigt-Mandel)."""
|
|
1167
|
+
|
|
1168
|
+
def test_strain_as_voigt_roundtrip(self):
|
|
1169
|
+
v = torch.tensor([1e-3, 2e-4, 3e-4, -5e-4, 1e-4, 2e-4])
|
|
1170
|
+
S = torch.tensor([[1e-3, 2e-4, 3e-4],
|
|
1171
|
+
[2e-4, -5e-4, 1e-4],
|
|
1172
|
+
[3e-4, 1e-4, 2e-4]])
|
|
1173
|
+
torch.testing.assert_close(HEDMForwardModel.strain_as_voigt(S), v)
|
|
1174
|
+
# plain Voigt passes through unchanged
|
|
1175
|
+
torch.testing.assert_close(HEDMForwardModel.strain_as_voigt(v), v)
|
|
1176
|
+
|
|
1177
|
+
def test_3x3_strain_equals_voigt_in_correct_hkls_latc(self, nf_geometry, device):
|
|
1178
|
+
model, _, _ = make_model_with_cubic_iron(nf_geometry, device)
|
|
1179
|
+
latc = torch.tensor([2.87, 2.87, 2.87, 90., 90., 90.])
|
|
1180
|
+
v = torch.tensor([1e-3, 2e-4, 3e-4, -5e-4, 1e-4, 2e-4])
|
|
1181
|
+
S = torch.tensor([[1e-3, 2e-4, 3e-4],
|
|
1182
|
+
[2e-4, -5e-4, 1e-4],
|
|
1183
|
+
[3e-4, 1e-4, 2e-4]])
|
|
1184
|
+
g_v, t_v = model.correct_hkls_latc(latc, strain=v)
|
|
1185
|
+
g_S, t_S = model.correct_hkls_latc(latc, strain=S)
|
|
1186
|
+
torch.testing.assert_close(g_v, g_S)
|
|
1187
|
+
torch.testing.assert_close(t_v, t_S)
|
|
1188
|
+
|
|
1189
|
+
def test_3x3_strain_equals_voigt_in_forward(self, nf_geometry, device):
|
|
1190
|
+
model, _, _ = make_model_with_cubic_iron(nf_geometry, device)
|
|
1191
|
+
eul = torch.tensor([[0.3, 0.5, 1.1]])
|
|
1192
|
+
pos = torch.zeros(1, 3)
|
|
1193
|
+
latc = torch.tensor([2.87, 2.87, 2.87, 90., 90., 90.]).expand(1, 6)
|
|
1194
|
+
v = torch.tensor([[1e-3, 2e-4, 3e-4, -5e-4, 1e-4, 2e-4]])
|
|
1195
|
+
S = torch.tensor([[[1e-3, 2e-4, 3e-4],
|
|
1196
|
+
[2e-4, -5e-4, 1e-4],
|
|
1197
|
+
[3e-4, 1e-4, 2e-4]]])
|
|
1198
|
+
sp_v = model(eul, pos, lattice_params=latc, strain=v)
|
|
1199
|
+
sp_S = model(eul, pos, lattice_params=latc, strain=S)
|
|
1200
|
+
torch.testing.assert_close(sp_v.two_theta, sp_S.two_theta)
|
|
1201
|
+
torch.testing.assert_close(sp_v.omega, sp_S.omega)
|
|
1202
|
+
|
|
1203
|
+
|
|
1114
1204
|
if __name__ == "__main__":
|
|
1115
1205
|
pytest.main([__file__, "-v"])
|
|
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
|