Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pressure and temperature calculations for lattice parameters #593

Merged
merged 26 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
cc06fba
organize code a little bit. All material related files are nor in the…
saransh13 Oct 19, 2023
3d174d6
compute pressure.
saransh13 Oct 19, 2023
720bcd1
more import path corrections.
saransh13 Oct 20, 2023
e9eb841
finish volume computation.
saransh13 Oct 20, 2023
290935d
compute the scaling factor for lattice parameter lengths.
saransh13 Oct 21, 2023
994f5a4
calculate lattice parameter as a function of pressure and temperature…
saransh13 Oct 21, 2023
bcc809f
Rename "materials" package back to "material"
psavery Nov 2, 2023
bf95d21
Fix mistaken renaming
psavery Nov 3, 2023
993f1d1
Make changes needed to work with HEXRDGUI
psavery Nov 7, 2023
43fd6b9
import path fix
saransh13 Nov 8, 2023
106286d
Hande I/O of 'k0', 'k0p' and 'v0'.
saransh13 Nov 8, 2023
3ab9290
add temperature variables to the material class
saransh13 Nov 8, 2023
093b8e3
I/O for material class with JCPDS parameters. Moved BM EOS functions …
saransh13 Nov 8, 2023
c812f78
change np --> numpy
saransh13 Nov 8, 2023
e31bb16
Memoize the result of GenerateSGSym
psavery Nov 10, 2023
9d29914
Change all "numpy" to "np" in material.py
psavery Nov 30, 2023
716ffae
Add config for Black
psavery Nov 30, 2023
0571c59
Run "black" on material.py
psavery Nov 30, 2023
eea778b
Initialize v0 in the __init__ method if needed
psavery Nov 30, 2023
bdd749a
Several fixes and improvements to use with the GUI
psavery Nov 30, 2023
6e2e9bd
Set default LP factor to 1
psavery Dec 19, 2023
8baa384
Compute lparms0 and pt_lp_factor
psavery Dec 19, 2023
96ff679
Fix import paths for tests
psavery Dec 19, 2023
9f036b8
Fix pep8 issues
psavery Dec 22, 2023
7c28c6b
Remove setting latticeParameters0
psavery Dec 29, 2023
23d0db7
Create aliases to import paths to fix old scripts
psavery Jan 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion hexrd/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,32 @@
__path__ = __import__('pkgutil').extend_path(__path__, __name__)
import importlib
import sys

from .material import crystallography
from .material import jcpds
from .material import mksupport
from .material import spacegroup
from .material import symbols
from .material import symmetry
from .material import unitcell

# These are aliases for import paths, so we don't break old HEXRD scripts.
# We will verify the alias files *do not* exist, to avoid confusion.
module_aliases = {
'hexrd.crystallography': crystallography,
'hexrd.mksupport': mksupport,
'hexrd.spacegroup': spacegroup,
'hexrd.symbols': symbols,
'hexrd.symmetry': symmetry,
'hexrd.unitcell': unitcell,
}

for alias, module in module_aliases.items():
try:
file_exists = importlib.import_module(alias).__name__ == alias
except ImportError:
file_exists = False

if file_exists:
raise Exception(f'"{alias}" is an alias path and should not exist')

sys.modules[alias] = module
2 changes: 1 addition & 1 deletion hexrd/instrument/detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from hexrd import matrixutil as mutil
from hexrd import xrdutil

from hexrd.crystallography import PlaneData
from hexrd.material.crystallography import PlaneData

from hexrd.transforms.xfcapi import (
detectorXYToGvec,
Expand Down
2 changes: 1 addition & 1 deletion hexrd/instrument/hedm_instrument.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
unitRowVector,
)
from hexrd import xrdutil
from hexrd.crystallography import PlaneData
from hexrd.material.crystallography import PlaneData
from hexrd import constants as ct
from hexrd.rotations import (
angleAxisOfRotMat,
Expand Down
7 changes: 7 additions & 0 deletions hexrd/material/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from .material import (
_angstroms,
_kev,
load_materials_hdf5,
Material,
save_materials_hdf5,
)
File renamed without changes.
327 changes: 327 additions & 0 deletions hexrd/material/jcpds.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,327 @@
import os
import numpy as np


class JCPDS_extend():
def __init__(self, filename=None):
self.a0 = 0
self.b0 = 0
self.c0 = 0
self.alpha0 = 0
self.beta0 = 0
self.gamma0 = 0
self.v0 = 0

self.k0 = 100
self.k0p = 5 # k0p at 298K

self.dk0dt = 0
self.dk0pdt = 0

self.symmetry = ''
self.alpha_t = 0 # alphat at 298K
self.dalpha_t_dt = 0

self.file = ' '
self.name = ' '
self.version = 0
self.comments = ''

if filename:
self.file = filename
self.read_file(self.file)
self.update_v0()

def read_file(self, file):
"""
read a jcpds file
"""
self.file = file
# Construct base name = file without path and without extension
name = os.path.splitext(os.path.basename(self.file))[0]
self.name = name
# line = '', nd=0
version = 0.
self.comments = []
self.DiffLines = []

version_status = ''

inp = open(file, 'r').readlines()
# my_list = [] # get all the text first and throw into my_list

if inp[0][0] in ('2', '3', '4'):
version = int(inp[0]) # JCPDS version number
self.version = version
header = inp[1] # header
self.comments = header

item = str.split(inp[2])
crystal_system = int(item[0])
if crystal_system == 1:
self.symmetry = 'cubic'
elif crystal_system == 2:
self.symmetry = 'hexagonal'
elif crystal_system == 3:
self.symmetry = 'tetragonal'
elif crystal_system == 4:
self.symmetry = 'orthorhombic'
elif crystal_system == 5:
self.symmetry = 'monoclinic'
elif crystal_system == 6:
self.symmetry = 'triclinic'
elif crystal_system == 7:
self.symmetry = 'manual'
# 1 cubic, 2 hexagonal, 3 tetragonal, 4 orthorhombic
# 5 monoclinic, 6 triclinic, 7 manual P, d-sp input

k0 = float(item[1])
k0p = float(item[2])
self.k0 = k0
self.k0p = k0p

item = str.split(inp[3]) # line for unit-cell parameters

if crystal_system == 1: # cubic
a = float(item[0])
b = a
c = a
alpha = 90.
beta = 90.
gamma = 90.
elif crystal_system == 7: # P, d-sp input
a = float(item[0])
b = a
c = a
alpha = 90.
beta = 90.
gamma = 90.
elif crystal_system == 2: # hexagonal
a = float(item[0])
c = float(item[1])
b = a
alpha = 90.
beta = 90.
gamma = 120.
elif crystal_system == 3: # tetragonal
a = float(item[0])
c = float(item[1])
b = a
alpha = 90.
beta = 90.
gamma = 90.
elif crystal_system == 4: # orthorhombic
a = float(item[0])
b = float(item[1])
c = float(item[2])
alpha = 90.
beta = 90.
gamma = 90.
elif crystal_system == 5: # monoclinic
a = float(item[0])
b = float(item[1])
c = float(item[2])
beta = float(item[3])
alpha = 90.
gamma = 90.
elif crystal_system == 6: # triclinic
a = float(item[0])
b = float(item[1])
c = float(item[2])
alpha = float(item[3])
beta = float(item[4])
gamma = float(item[5])

self.a0 = a
self.b0 = b
self.c0 = c
self.alpha0 = alpha
self.beta0 = beta
self.gamma0 = gamma

item = str.split(inp[4])

if self.version == 3:
alpha_t = 0.
else:
alpha_t = float(item[0])
self.alpha_t = alpha_t

version_status = 'new'

elif 'VERSION' in inp[0]:
jcpdsfile = open(file, 'r')
while True:
jcpdsline = jcpdsfile.readline()
if jcpdsline == '':
break

jlinespl = jcpdsline.split()

if jlinespl[0] == 'VERSION:':
version = int(jlinespl[1])
self.version = version

if jlinespl[0] == 'COMMENT:':
header = ' '.join(jlinespl[1:])
self.comments = header

if jlinespl[0] == 'K0:':
k0 = float(jlinespl[1])
self.k0 = k0

if jlinespl[0] == 'K0P:':
k0p = float(jlinespl[1])
self.k0p = k0p

if jlinespl[0] == 'DK0DT:':
dk0dt = float(jlinespl[1])
self.dk0dt = dk0dt

if jlinespl[0] == 'DK0PDT:':
dk0pdt = float(jlinespl[1])
self.dk0pdt = dk0pdt

if jlinespl[0] == 'SYMMETRY:':
self.symmetry = jlinespl[1].lower()

if jlinespl[0] == 'A:':
a = float(jlinespl[1])
self.a0 = a

if jlinespl[0] == 'B:':
b = float(jlinespl[1])
self.b0 = b

if jlinespl[0] == 'C:':
c = float(jlinespl[1])
self.c0 = c

if jlinespl[0] == 'ALPHA:':
alpha = float(jlinespl[1])
self.alpha0 = alpha

if jlinespl[0] == 'BETA:':
beta = float(jlinespl[1])
self.beta0 = beta

if jlinespl[0] == 'GAMMA:':
gamma = float(jlinespl[1])
self.gamma0 = gamma

if jlinespl[0] == 'VOLUME:':
v = float(jlinespl[1])
self.v0 = v

if jlinespl[0] == 'ALPHAT:':
alphat = float(jlinespl[1])
self.alpha_t = alphat

if jlinespl[0] == 'DALPHATDT:':
dalphatdt = float(jlinespl[1])
self.dalpha_t_dt = dalphatdt

if jlinespl[0] == 'DIHKL:':
pass

if self.symmetry == 'cubic':
self.b0 = self.a0
self.c0 = self.a0
self.alpha0 = 90.
self.beta0 = 90.
self.gamma0 = 90.
elif self.symmetry == 'manual':
self.b0 = self.a0
self.c0 = self.a0
self.alpha0 = 90.
self.beta0 = 90.
self.gamma0 = 90.
elif self.symmetry == 'hexagonal' or self.symmetry == 'trigonal':
self.b0 = self.a0
self.alpha0 = 90.
self.beta0 = 90.
self.gamma0 = 120.
elif self.symmetry == 'tetragonal':
self.b0 = self.a0
self.alpha0 = 90.
self.beta0 = 90.
self.gamma0 = 90.
elif self.symmetry == 'orthorhombic':
self.alpha0 = 90.
self.beta0 = 90.
self.gamma0 = 90.
elif self.symmetry == 'monoclinic':
self.alpha0 = 90.
self.gamma0 = 90.
# elif self.symmetry == 'triclinic':

jcpdsfile.close()

version_status = 'new'

else:
version_status = 'old'

if version_status == 'new':
self.v = self.calc_volume_unitcell()

def verify_symmetry_match(self, mat):
if not self.symmetry_matches(mat):
msg = (
f'The JCPDS symmetry "{self.symmetry}" does not match the '
f'symmetry of the material "{mat.latticeType}"!'
)
raise SymmetryMismatch(msg)

def symmetry_matches(self, mat):
return mat.latticeType == self.symmetry

@property
def _lat_param_names(self):
return ['a0', 'b0', 'c0', 'alpha0', 'beta0', 'gamma0']

@property
def lattice_params(self):
return [getattr(self, x) for x in self._lat_param_names]

def matches_material(self, mat):
self.verify_symmetry_match(mat)
mat_lp = [x.value for x in mat.latticeParameters]
for v1, v2 in zip(mat_lp, self.lattice_params):
if not np.isclose(v1, v2):
return False

def write_lattice_params_to_material(self, mat):
self.verify_symmetry_match(mat)
mat.latticeParameters = self.lattice_params
mat.reset_v0()

def write_pt_params_to_material(self, mat):
self.verify_symmetry_match(mat)
mat.k0 = self.k0
mat.k0p = self.k0p
mat.dk0dt = self.dk0dt
mat.dk0pdt = self.dk0pdt
mat.alpha_t = self.alpha_t
mat.dalpha_t_dt = self.dalpha_t_dt

def update_v0(self):
self.v0 = self.calc_volume_unitcell()

def calc_volume_unitcell(self):
'''calculate volume of the unitcell
Ref: Introduction to conventional TEM
Marc De Graef, Appendix 1 pg. 662
'''
ca = np.cos(np.radians(self.alpha0))
cb = np.cos(np.radians(self.beta0))
cg = np.cos(np.radians(self.gamma0))

v0 = self.a0*self.b0*self.c0
f = np.sqrt(1 - ca**2 - cb**2 - cg**2
+ 2 * ca * cb * cg)
return v0*f


class SymmetryMismatch(Exception):
pass
Loading