From 7490627789d06adaaf3875da6c758f561c9d002b Mon Sep 17 00:00:00 2001 From: Saransh Singh Date: Fri, 21 Nov 2025 13:22:22 -0800 Subject: [PATCH 1/7] phase transformation variants --- hexrd/core/valunits.py | 12 ++ .../phasetransformation/variants.py | 178 ++++++++++++++++++ 2 files changed, 190 insertions(+) create mode 100644 hexrd/singlextal/phasetransformation/variants.py diff --git a/hexrd/core/valunits.py b/hexrd/core/valunits.py index e0d00dbe7..d9e766910 100644 --- a/hexrd/core/valunits.py +++ b/hexrd/core/valunits.py @@ -313,6 +313,18 @@ def valWithDflt(val, dflt, toUnit=None): return retval +def _nm(x): + return valWUnit("lp", "length", x, "nm") + + +def _angstrom(x): + return valWUnit("lp", "length", x, "angstrom") + + +def _kev(x): + return valWUnit("kev", "energy", x, "keV") + + if __name__ == '__main__': # # doc testing diff --git a/hexrd/singlextal/phasetransformation/variants.py b/hexrd/singlextal/phasetransformation/variants.py new file mode 100644 index 000000000..808a45319 --- /dev/null +++ b/hexrd/singlextal/phasetransformation/variants.py @@ -0,0 +1,178 @@ +import numpy as np +from hexrd.rotations import misorientation +from hexrd.material import Material +from matplotlib import pyplot as plt +from hexrd.valunits import _angstrom, _kev +import mplstereonet +from numba import njit + +""" +define some helper functions +""" + +""" + remove all hkl, -hkl pairs from list of symmetrically +equivalent hkls""" + + +def removeinversion(ksym): + klist = [] + for i in range(ksym.shape[0]): + k = ksym[i, :] + kk = list(k) + nkk = list(-k) + if klist == []: + if np.sum(k) > np.sum(-k): + klist.append(kk) + else: + klist.append(nkk) + + else: + if (kk in klist) or (nkk in klist): + pass + else: + klist.append(kk) + klist = np.array(klist) + return klist + + +""" + get expected number of phase transformation variants + from group theoretic calculations +""" + + +def expected_num_variants(mat1, mat2, R1, R2): + """ + calculate expected number of orientational + variants using the formula given in + C. Cayron, J. Appl. Cryst. (2007). 40, 1179–1182 + page 2 + N_alpha = |G_beta|/|H_beta| + """ + T = np.dot(R1, R2.T) + sym1 = mat1.unitcell.SYM_PG_c + sym2 = mat2.unitcell.SYM_PG_c + ctr = 0 + for s2 in sym2: + ss = np.dot(T, np.dot(s2, T.T)) + for s1 in sym1: + diff = np.sum(np.abs(ss - s1)) + if diff < 1e-6: + ctr += 1 + return int(len(sym1) / ctr) + + +""" + get rotation matrix +""" + + +def get_rmats(p1, d1, mat, toprint=False): + sym = mat.unitcell.SYM_PG_c + z = p1 + x = d1 + y = np.cross(z, x) + return np.vstack((x, y, z)).T + + +""" + check if rotation matrix generated is a new one +""" + + +def isnew(mat, rmat, sym): + res = True + for r in rmat: + for s in sym: + rr = np.dot(s, r) + diff = np.sum(np.abs(rr - mat)) + if diff < 1e-6: + res = False + break + return res + + +def prepare_data(mat1, mat2, parallel_planes, parallel_directions): + """ + prepare the planes and directions by: + 1. converting to cartesian space + 2. normalizing magnitude""" + p1, p2 = parallel_planes + d1, d2 = parallel_directions + + p1 = mat1.unitcell.TransSpace(p1, "r", "c") + p1 = mat1.unitcell.NormVec(p1, "c") + d1 = mat1.unitcell.TransSpace(d1, "d", "c") + d1 = mat1.unitcell.NormVec(d1, "c") + + p2 = mat2.unitcell.TransSpace(p2, "r", "c") + p2 = mat2.unitcell.NormVec(p2, "c") + d2 = mat2.unitcell.TransSpace(d2, "d", "c") + d2 = mat2.unitcell.NormVec(d2, "c") + + return (p1, p2), (d1, d2) + + +# main function +# get the variants +def getOR(R1, R2, mat1, mat2): + """ + R1 ---> mat1 + R2 ---> mat2 + """ + rmat = [] + sym1 = mat1.unitcell.SYM_PG_c + sym2 = mat2.unitcell.SYM_PG_c + for sa in sym1: + ma = np.dot(sa, R1) + # for sb in sym2: + # mb = np.dot(sb, R2) + mb = R2 + m = np.dot(mb, ma.T) + if isnew(m, rmat, sym2): + rmat.append(m) + + rmat_t = [r.T for r in rmat] + return rmat_t + + +def getPhaseTransformationVariants( + mat1, mat2, parallel_planes, parallel_directions, plot=False +): + """ + main function to get the phase transformation variants between two materials + give a set of parallel planes and parallel directions + + Parameters + ---------- + mat1 : hexrd.material.Material + Material class for parent phase + mat2 : hexrd.material.Material + Material class for child phase + parallel_planes : list/tuple + list of numpy arrays with parallel planes, length=2 + parallel_planes : list/tuple + list of numpy arrays with parallel directions, length=2 + plot : boolean + plot the data in stereographic projection if true + + + """ + (p1, p2), (d1, d2) = prepare_data( + mat1, mat2, parallel_planes, parallel_directions + ) + + R1 = get_rmats(p1, d1, mat1) + R2 = get_rmats(p2, d2, mat2) + + rmat = getOR(R1, R2, mat1, mat2) + + num_var = expected_num_variants(mat1, mat2, R1, R2) + + print("Expected # of orientational variants = ", num_var) + print( + "number of orientation variants in phase transition = ", + len(rmat), + "\n", + ) From b1dbbb8824e702e99eccc8f0fc81e653acf97526 Mon Sep 17 00:00:00 2001 From: Saransh Singh Date: Fri, 21 Nov 2025 16:26:30 -0800 Subject: [PATCH 2/7] added plotting functionality --- hexrd/core/material/spacegroup.py | 46 +++++++++++++- .../phasetransformation/variants.py | 61 ++++++++++++++++++- 2 files changed, 103 insertions(+), 4 deletions(-) diff --git a/hexrd/core/material/spacegroup.py b/hexrd/core/material/spacegroup.py index 647f3777b..28a31b401 100644 --- a/hexrd/core/material/spacegroup.py +++ b/hexrd/core/material/spacegroup.py @@ -87,7 +87,6 @@ class SpaceGroup: - def __init__(self, sgnum): """Constructor for SpaceGroup @@ -373,6 +372,51 @@ def _sgrange(min, max): } +def get_symmetry_directions(mat): + """ + helper function to get a list of primary, + secondary and tertiary directions of the + space group of mat. e.g. cubic systems have + primary: [001] + secondary: [111] + tertiary: [110] + """ + ltype = mat.latticeType + + if ltype == "triclinic": + primary = np.array([0, 0, 1]) + secondary = np.array([0, 1, 0]) + tertiary = np.array([1, 0, 0]) + elif ltype == "monoclinic": + primary = np.array([0, 1, 0]) + secondary = np.array([1, 0, 0]) + tertiary = np.array([0, 0, 1]) + elif ltype == "orthorhombic": + primary = np.array([1, 0, 0]) + secondary = np.array([0, 1, 0]) + tertiary = np.array([1, 0, 1]) + elif ltype == "tetragonal": + primary = np.array([0, 0, 1]) + secondary = np.array([1, 0, 0]) + tertiary = np.array([1, 1, 0]) + elif ltype == "trigonal": + # it is assumed that trigonal crystals are + # represented in the hexagonal basis + primary = np.array([0, 0, 1]) + secondary = np.array([1, 0, 0]) + tertiary = np.array([1, 2, 0]) + elif ltype == "hexagonal": + primary = np.array([0, 0, 1]) + secondary = np.array([1, 0, 0]) + tertiary = np.array([1, 2, 0]) + elif ltype == "cubic": + primary = np.array([0, 0, 1]) + secondary = np.array([1, 1, 1]) + tertiary = np.array([1, 1, 0]) + + return (primary, secondary, tertiary) + + def Allowed_HKLs(sgnum, hkllist): """ this function checks if a particular g vector is allowed diff --git a/hexrd/singlextal/phasetransformation/variants.py b/hexrd/singlextal/phasetransformation/variants.py index 808a45319..6bdcb878e 100644 --- a/hexrd/singlextal/phasetransformation/variants.py +++ b/hexrd/singlextal/phasetransformation/variants.py @@ -5,6 +5,7 @@ from hexrd.valunits import _angstrom, _kev import mplstereonet from numba import njit +from hexrd.material.spacegroup import get_symmetry_directions """ define some helper functions @@ -137,8 +138,59 @@ def getOR(R1, R2, mat1, mat2): return rmat_t +def plot_OR_mat(rmat, mat, fig, ax, title): + font = { + "family": "serif", + "weight": "bold", + "size": 20, + } + + Gs = get_symmetry_directions(mat) + markers = ["ok", "^g", "sb"] + + leg = [] + for G in Gs: + leg.append(rf"$[{G[0]},{G[1]},{G[2]}]$") + + for m, g in zip(markers, Gs): + hkl = mat.unitcell.CalcStar(g, "d") + dip = [] + strike = [] + + for v in hkl: + vv = mat.unitcell.TransSpace(v, "d", "c") + vec = mat.unitcell.NormVec(vv, "c") + for r in rmat: + xyz = np.dot(r, vec) + if xyz[2] < 0.0: + xyz = -xyz + dip.append(np.degrees(np.arccos(xyz[2]))) + strike.append(180.0 + np.degrees(np.arctan2(xyz[1], xyz[0]))) + + ax.pole(strike, dip, m, markersize=16, markeredgecolor="red") + ax.set_azimuth_ticks([]) + ax.tick_params(axis="both", which="major", size=24) + ax.grid() + ax.legend(leg, bbox_to_anchor=(1.15, 1.15), loc="upper right", prop=font) + ax.set_title(title, **font) + + +def plot_OR(rmat_parent, rmat_variants, mat1, mat2, fig=None, ax=None): + if fig is None or ax is None: + fig, ax = mplstereonet.subplots(ncols=2, figsize=(16, 8)) + + plot_OR_mat(rmat_parent, mat1, fig, ax[0], title="Parent") + plot_OR_mat(rmat_variants, mat2, fig, ax[1], title="Variants") + fig.show() + + def getPhaseTransformationVariants( - mat1, mat2, parallel_planes, parallel_directions, plot=False + mat1, + mat2, + parallel_planes, + parallel_directions, + rmat_parent=[np.eye(3)], + plot=False, ): """ main function to get the phase transformation variants between two materials @@ -166,13 +218,16 @@ def getPhaseTransformationVariants( R1 = get_rmats(p1, d1, mat1) R2 = get_rmats(p2, d2, mat2) - rmat = getOR(R1, R2, mat1, mat2) + rmat_variants = getOR(R1, R2, mat1, mat2) num_var = expected_num_variants(mat1, mat2, R1, R2) print("Expected # of orientational variants = ", num_var) print( "number of orientation variants in phase transition = ", - len(rmat), + len(rmat_variants), "\n", ) + + if plot: + plot_OR(rmat_parent, rmat_variants, mat1, mat2, fig=None, ax=None) From a6637a4b8c8eaab7cca0abb8fd734001dad50b5d Mon Sep 17 00:00:00 2001 From: Saransh Singh Date: Fri, 21 Nov 2025 16:29:08 -0800 Subject: [PATCH 3/7] some more notes --- hexrd/core/material/spacegroup.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hexrd/core/material/spacegroup.py b/hexrd/core/material/spacegroup.py index 28a31b401..db261e4b5 100644 --- a/hexrd/core/material/spacegroup.py +++ b/hexrd/core/material/spacegroup.py @@ -380,6 +380,15 @@ def get_symmetry_directions(mat): primary: [001] secondary: [111] tertiary: [110] + + For some symmetries like monoclinic and trigonal, + some of the symmetry directions are not present. In + that case, we have choden them to be the same as the + crystal axis + + For trigonal systems, it is ALWAYS assumed that they + are represented in the hexagonal basis. so the directions + are the same for the two """ ltype = mat.latticeType From a378fad7328687d6f62bd889b7efa86f08fad036 Mon Sep 17 00:00:00 2001 From: Saransh Singh Date: Mon, 24 Nov 2025 11:21:03 -0800 Subject: [PATCH 4/7] improve some plotting --- .../singlextal/phasetransformation/variants.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/hexrd/singlextal/phasetransformation/variants.py b/hexrd/singlextal/phasetransformation/variants.py index 6bdcb878e..ce8765e36 100644 --- a/hexrd/singlextal/phasetransformation/variants.py +++ b/hexrd/singlextal/phasetransformation/variants.py @@ -142,7 +142,7 @@ def plot_OR_mat(rmat, mat, fig, ax, title): font = { "family": "serif", "weight": "bold", - "size": 20, + "size": 12, } Gs = get_symmetry_directions(mat) @@ -167,20 +167,28 @@ def plot_OR_mat(rmat, mat, fig, ax, title): dip.append(np.degrees(np.arccos(xyz[2]))) strike.append(180.0 + np.degrees(np.arctan2(xyz[1], xyz[0]))) - ax.pole(strike, dip, m, markersize=16, markeredgecolor="red") + ax.pole(strike, dip, m, markersize=12, markeredgecolor="red") + ax.tick_params(axis="both", size=24) + ax.grid(True, which="both", ls=":", lw=1) + ax.set_longitude_grid(10) + # ax.set_latitude_grid(10) ax.set_azimuth_ticks([]) - ax.tick_params(axis="both", which="major", size=24) - ax.grid() ax.legend(leg, bbox_to_anchor=(1.15, 1.15), loc="upper right", prop=font) ax.set_title(title, **font) def plot_OR(rmat_parent, rmat_variants, mat1, mat2, fig=None, ax=None): if fig is None or ax is None: - fig, ax = mplstereonet.subplots(ncols=2, figsize=(16, 8)) + fig, ax = mplstereonet.subplots( + ncols=2, figsize=(10, 5), projection='equal_angle_stereonet' + ) plot_OR_mat(rmat_parent, mat1, fig, ax[0], title="Parent") plot_OR_mat(rmat_variants, mat2, fig, ax[1], title="Variants") + # cosmetic + fig.subplots_adjust( + hspace=0, wspace=0.05, left=0.01, bottom=0.1, right=0.99 + ) fig.show() From caa1f416bf2369888eaec6ef303297bfe1da67ae Mon Sep 17 00:00:00 2001 From: Saransh Singh Date: Mon, 24 Nov 2025 11:23:36 -0800 Subject: [PATCH 5/7] include mplstereonet in conda recipe --- conda.recipe/meta.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/conda.recipe/meta.yaml b/conda.recipe/meta.yaml index 57f0945fb..cb5ea1b74 100644 --- a/conda.recipe/meta.yaml +++ b/conda.recipe/meta.yaml @@ -59,6 +59,9 @@ requirements: # Installing TBB means numba will use it instead of OpenMP. - tbb - tqdm + # needed for the phase transformation variants plotting. + # could also be used for pole density plotting in the future + - mplstereonet test: # [build_platform == target_platform] imports: From 2ccbe829c2a0821754466775796b4556ebbb8bb6 Mon Sep 17 00:00:00 2001 From: Saransh Singh Date: Mon, 24 Nov 2025 11:45:19 -0800 Subject: [PATCH 6/7] adding tests --- .../phasetransformation/variants.py | 16 ++++--- tests/data/materials/materials_variants.h5 | Bin 0 -> 48896 bytes tests/test_variants.py | 45 ++++++++++++++++++ 3 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 tests/data/materials/materials_variants.h5 create mode 100644 tests/test_variants.py diff --git a/hexrd/singlextal/phasetransformation/variants.py b/hexrd/singlextal/phasetransformation/variants.py index ce8765e36..da192d916 100644 --- a/hexrd/singlextal/phasetransformation/variants.py +++ b/hexrd/singlextal/phasetransformation/variants.py @@ -199,6 +199,7 @@ def getPhaseTransformationVariants( parallel_directions, rmat_parent=[np.eye(3)], plot=False, + verbose=False, ): """ main function to get the phase transformation variants between two materials @@ -230,12 +231,15 @@ def getPhaseTransformationVariants( num_var = expected_num_variants(mat1, mat2, R1, R2) - print("Expected # of orientational variants = ", num_var) - print( - "number of orientation variants in phase transition = ", - len(rmat_variants), - "\n", - ) + if verbose: + print("Expected # of orientational variants = ", num_var) + print( + "number of orientation variants in phase transition = ", + len(rmat_variants), + "\n", + ) if plot: plot_OR(rmat_parent, rmat_variants, mat1, mat2, fig=None, ax=None) + + return rmat_variants, num_var diff --git a/tests/data/materials/materials_variants.h5 b/tests/data/materials/materials_variants.h5 new file mode 100644 index 0000000000000000000000000000000000000000..41578477cd9446b98da68b1b017dd54417f599b4 GIT binary patch literal 48896 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 literal 0 HcmV?d00001 diff --git a/tests/test_variants.py b/tests/test_variants.py new file mode 100644 index 000000000..22002cb48 --- /dev/null +++ b/tests/test_variants.py @@ -0,0 +1,45 @@ +from hexrd.core.material import Material, load_materials_hdf5 +import h5py +import numpy as np +from hexrd.singlextal.phasetransformation import variants +from hexrd.valunits import _kev, _nm +import pytest + + +@pytest.fixture +def test_variants_material_file(test_data_dir): + return f'{test_data_dir}/materials/materials_variants.h5' + + +def test_variants(test_variants_material_file): + beamenergy = _kev(10) + dmin = _nm(0.075) + print(test_variants_material_file) + mats = load_materials_hdf5( + test_variants_material_file, dmin=dmin, kev=beamenergy + ) + + # 4H-SiC phase crystal structure + fourH = mats["4H_SiC_HP"] + + # B1 phase crystal structure + B1 = mats["SiC_B1"] + + p1 = np.array([0.0, 0.0, 1.0]) + p2 = np.array([0.0, 0.0, 1.0]) + d1 = np.array([2.0, 1.0, 0.0]) + d2 = np.array([1.0, 1.0, 0.0]) + parallel_planes = (p1, p2) + parallel_directions = (d1, d2) + + rmat_variants, num_variants = variants.getPhaseTransformationVariants( + fourH, + B1, + parallel_planes, + parallel_directions, + plot=False, + verbose=False, + ) + + assert len(rmat_variants) == num_variants + assert len(rmat_variants) == 3 From c7799c4fa62e0a1f5f9737b2953e887a7b4d3117 Mon Sep 17 00:00:00 2001 From: Saransh Singh Date: Mon, 24 Nov 2025 11:52:10 -0800 Subject: [PATCH 7/7] add mplstereonet in install reqs. --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index dd567034c..844a7f9eb 100644 --- a/setup.py +++ b/setup.py @@ -31,6 +31,7 @@ 'scipy', 'tqdm', 'xxhash', + 'mplstereonet', ] if platform.machine() == 'x86_64':