Skip to content

DRAFT: Diffraction model with intragranular misorientation#28

Open
MACarlsen wants to merge 11 commits into
FABLE-3DXRD:mainfrom
MACarlsen:main
Open

DRAFT: Diffraction model with intragranular misorientation#28
MACarlsen wants to merge 11 commits into
FABLE-3DXRD:mainfrom
MACarlsen:main

Conversation

@MACarlsen
Copy link
Copy Markdown

Hi All,

I was reading a very nice paper-draft this wednesday, which was using this package to simulate diffraction from deformed microstructures. But I couldn't help to thing that there must be a better way to make such a simulation. So I tried to implement a concept where the sample consists of a collection of gaussian-shaped "grains" with a narrow anisotropic gaussian ODF each.

If you make a the right approximations, the diffraction peaks produced by such a grain is also a "gaussian" in the detector coordinates, so you can use some concept from "gaussian splatting" to do fast evaluation. Since this package already has a few different model for rendering diffraction peaks, I figured why not add another one.

There is still a lot of work to be done testing and optimizing, but if you are interested and can give me some pointers about how to implement it, I would try to do it.

The model is also fully differentiable, so one can dream about doing proper gaussian-splatting fitting...

In the jupyternotebook from the front-page of the documentation you can run this:

from xrd_simulator.gaussian_crystal_model import GaussianGrainish, GaussianPolycrystal
import torch

def make_random_tensor(axis_1, axis_2):
    random_direction = np.random.normal(size=3)
    random_direction = random_direction/np.linalg.norm(random_direction)
    tensor = axis_1**2 * np.eye(3) + (axis_2**2-axis_1**2) * np.outer(random_direction, random_direction)
    return tensor

N = mesh.number_of_elements
orientation = R.random(mesh.number_of_elements).as_matrix()

grain_list = []
for ii in range(N):

    shape_tensor = torch.eye(3) * mesh.eradius[ii]**2

    misorientation_tensor = make_random_tensor(
        np.random.uniform(0.002, 0.0005),
        np.random.uniform(0.002, 0.0005),
    )

    grain = GaussianGrainish(
        phase=quartz, #  For now it assumes all gaussians are the same phase, but it just needs a wrapper for multiphase
        position=mesh.espherecentroids[ii], # 3 vector centroid real-space position
        shape_tensor=shape_tensor, # 3-by-3 symmetric shape tensor where the eigenvalues are the radii-squared.
        orientation=orientation[ii], # 3-by-3 rotation matrix.
        misorientation_tensor=misorientation_tensor, # 3-by-3 misorientation tensor where the eigenvalues are the misorientaion spread in radians squared.
                                                     # misorientation vectors live in laboratory coordinates.
        strain_tensor=polycrystal.strain_lab[ii] # 3-by-3 symmetric strain tensor.
    )

    grain_list.append(grain)

gauss_polycrystal = GaussianPolycrystal(grain_list)

f = gauss_polycrystal.render_detector_frame(
    detector=detector,    
    xray_propagation_direction=np.array([1.0, 0.0, 0.0]),
    wavelength=0.28523,
    max_misorientation=np.radians(1.0),
    sample_rotation_during_exposure = np.array([0, 1 / np.sqrt(2), -1 / np.sqrt(2)])*np.radians(1.0), # This is of course with a gaussian time-window
)

fig, ax = plt.subplots(1, 1, figsize=(12, 12))
ax.imshow(f, cmap="gray", vmax=100000)
plt.show()
quartz_from_documentation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant