Skip to content

Commit

Permalink
Merge pull request #96 from Exabyte-io/feature/SOF-7232
Browse files Browse the repository at this point in the history
Feature/SOF-7232
  • Loading branch information
VsevolodX authored Feb 1, 2024
2 parents ba734ca + f7e2923 commit 56f9806
Show file tree
Hide file tree
Showing 3 changed files with 837 additions and 0 deletions.
37 changes: 37 additions & 0 deletions other/materials_designer/Introduction.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Materials Transformations with Python Notebooks\n",
"\n",
"## Overview\n",
"\n",
"This Jupyter Lite distribution contains pre-configured examples of materials transformations including simple ones like creation of supercell or a surface, and more complex like creating an interface with Zur and McGill Superlattice matching algorithm\n",
"\n",
"## Examples\n",
"\n",
"### 1. Interface creation with Zur and McGill Superlattice algorithm\n",
"\n",
"[This file](zsl_interface_generation.ipynb) helps creating interface between two materials by finding matching superlattices and selecting optimal variants by size-strain trade-off. (Link to the lattice match algorithm: https://doi.org/10.1063/1.333084)\n",
"\n",
"### Definition for communication\n",
"\n",
"[definitions.py](definitions.py)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
132 changes: 132 additions & 0 deletions other/materials_designer/definitions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
from IPython.display import display, Javascript
import json


def set_materials(materials):
"""
This function takes a Python object, serializes it to JSON, and sends it to the host environment
through a JavaScript function defined in the JupyterLite extension `data_bridge`.
Args:
materials (object): The Python object to be sent to the host environment.
"""
python_data = materials
serialized_data = json.dumps({"materials": python_data})
js_code = f"""
(function() {{
window.sendDataToHost({serialized_data})
console.log({serialized_data})
}})();
"""

display(Javascript(js_code))
print("materials sent")


def get_materials():
"""
This function requests materials from the host environment through a JavaScript function defined in the JupyterLite
extension `data_bridge`. The materials are then returned to the Python environment.
"""
js_code = """
(function() {
if (window.requestDataFromHost) {
window.requestDataFromHost();
} else {
console.error('requestDataFromHost function is not defined on the window object.');
}
})();
"""

display(Javascript(js_code))
print("materials requested")


from pymatgen.core import Structure, Lattice


def to_pymatgen(material_data):
"""
Convert material object in ESSE format to a pymatgen Structure object.
Args:
material_data (dict): A dictionary containing the material information in ESSE format.
Returns:
Structure: A pymatgen Structure object.
"""

# Extract lattice information
lattice_params = material_data["lattice"]
lattice_vectors = lattice_params["vectors"]
a = lattice_vectors["a"]
b = lattice_vectors["b"]
c = lattice_vectors["c"]

# Create a Lattice
lattice = Lattice([a, b, c])

# Extract the basis information
basis = material_data["basis"]
elements = [element["value"] for element in basis["elements"]]
coordinates = [coord["value"] for coord in basis["coordinates"]]

# Assuming that the basis units are fractional since it's a crystal basis
coords_are_cartesian = basis["units"].lower() != "crystal"

# Create the Structure
structure = Structure(lattice, elements, coordinates, coords_are_cartesian=coords_are_cartesian)

return structure


def from_pymatgen(structure: Structure):
"""
Convert a pymatgen Structure object to a material object in ESSE format.
Args:
structure (Structure): A pymatgen Structure object.
Returns:
dict: A dictionary containing the material information in ESSE format.
"""
basis = {
"elements": [{"id": i, "value": str(site.specie)} for i, site in enumerate(structure.sites)],
"coordinates": [{"id": i, "value": list(site.frac_coords)} for i, site in enumerate(structure.sites)],
"units": "crystal",
"cell": structure.lattice.matrix.tolist(),
"constraints": [], # Assuming there are no constraints
}

# Extract lattice information
lattice = {
"a": structure.lattice.a,
"b": structure.lattice.b,
"c": structure.lattice.c,
"alpha": structure.lattice.alpha,
"beta": structure.lattice.beta,
"gamma": structure.lattice.gamma,
"units": {"length": "angstrom", "angle": "degree"},
"type": "FCC", # You need a way to determine the lattice type
"vectors": {
"a": structure.lattice.matrix[0].tolist(),
"b": structure.lattice.matrix[1].tolist(),
"c": structure.lattice.matrix[2].tolist(),
"alat": 1, # This seems to be a scaling factor; adjust if necessary
"units": "angstrom",
},
}

# Combine into a material dictionary
material = {
"name": structure.formula,
"basis": basis,
"lattice": lattice,
"isNonPeriodic": not structure.is_ordered,
"_id": "",
"metadata": {"boundaryConditions": {"type": "bc2", "offset": 0}},
"isUpdated": True,
}

return material
Loading

0 comments on commit 56f9806

Please sign in to comment.