diff --git a/.bumpversion.cfg b/.bumpversion.cfg index e7cf612..e34834e 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.8.16 +current_version = 0.9.0 commit = True tag = False diff --git a/CITATION.cff b/CITATION.cff index d3b75bf..57f38cf 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -19,4 +19,4 @@ url: 'https://atomrdf.pyscal.org' license: "MIT" repository-code: https://github.com/pyscal/atomRDF type: software -version: 0.8.16 +version: 0.9.0 diff --git a/atomrdf/data/ldo.owl b/atomrdf/data/ldo.owl new file mode 100644 index 0000000..f071855 --- /dev/null +++ b/atomrdf/data/ldo.owl @@ -0,0 +1,481 @@ + + + + + Line Defect Ontology (LDO) + Line Defect Ontology + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Examples of a Contributor include a person, an organization, or a service. Typically, the name of a Contributor should be used to indicate the entity. + Contributor + An entity responsible for making contributions to the resource. + + + + + + + + + Examples of a Creator include a person, an organization, or a service. Typically, the name of a Creator should be used to indicate the entity. + Creator + An entity primarily responsible for making the resource. + + + + + + + + + + + Description may include but is not limited to: an abstract, a table of contents, a graphical representation, or a free-text account of the resource. + Description + An account of the resource. + + + + + + + + + Title + A name given to the resource. + In current practice, this term is used primarily with literal values; however, there are important uses with non-literal values as well. As of December 2007, the DCMI Usage Board is leaving this range unspecified pending an investigation of options. + + + + + + + + + The range of skos:altLabel is the class of RDF plain literals. + skos:prefLabel, skos:altLabel and skos:hiddenLabel are pairwise disjoint properties. + + alternative label + An alternative lexical label for a resource. + Acronyms, abbreviations, spelling variants, and irregular plural/singular forms may be included among the alternative labels for a concept. Mis-spelled terms are normally included as hidden labels (see skos:hiddenLabel). + + + + + + + + + + definition + A statement or formal explanation of the meaning of a concept. + + + + + + + + + + example + An example of the use of a concept. + + + + + + + + + A general note, for any purpose. + + + + + + + + A resource has no more than one value of skos:prefLabel per language tag, and no more than one value of skos:prefLabel without language tag. + The range of skos:prefLabel is the class of RDF plain literals. + skos:prefLabel, skos:altLabel and skos:hiddenLabel are pairwise + disjoint properties. + + preferred label + The preferred lexical label for a resource, in a given language. + + + + + + + + + + + + + + + + + + + + + + + belongs to system + + + + + + + + + + has Burgers vector + + + + + + + + + + has line direction + + + + + + + + + + has normal vector + + + + + + + + + + moves on + + + + + + + + + + results in + + + + + + + + + + + + + has dislocation density + + + + + + + + + + A data property linking a vector with its component on the x axis. + has component x + + + + + + + + + + A data property linking a vector with its component on the y axis. + has component y + + + + + + + + + + A data property linking a vector with its component on the z axis. + has component z + + + + + + + + + + + + + Angular Vector + Frank Vector + + + + + + + + + Burgers Vector + b + + + + + + + + + Disclination + + + + + + + + + Dislocation + + + + + + + + + Edge Dislocation + + + + + + + + Lattice Plane + + + + + + + + Linear or one-dimensional defect around which some of the atoms are misaligned. + Line Defect + + + + + + + + + Line Direction + Line Vector + + + + + + + + + Mixed Dislocation + + + + + + + + + Normal Vector + + + + + + + + + Partial Dislocation + Shockley Partial + + + + + + + + + Screw Dislocation + + + + + + + + Slip + + + + + + + + + Slip Direction + + + + + + + + + Slip Plane + + + + + + + + Slip System + + + + + + + + + Twist Disclination + + + + + + + + + Wedge Disclination + + + + + + + + Vector is a quantity that has a magnitude and direction. + Vector + + + + + + + diff --git a/atomrdf/namespace.py b/atomrdf/namespace.py index d453682..d6cb5ae 100644 --- a/atomrdf/namespace.py +++ b/atomrdf/namespace.py @@ -79,6 +79,7 @@ def __init__(self, infile, delimiter="/"): file_location = os.path.dirname(__file__) CMSO = Namespace(os.path.join(file_location, "data/cmso.owl")) +LDO = Namespace(os.path.join(file_location, "data/ldo.owl")) PLDO = Namespace(os.path.join(file_location, "data/pldo.owl")) PODO = Namespace(os.path.join(file_location, "data/podo.owl")) ASMO = Namespace(os.path.join(file_location, "data/asmo.owl")) diff --git a/atomrdf/network/ontology.py b/atomrdf/network/ontology.py index 8ec8459..ec24cc9 100644 --- a/atomrdf/network/ontology.py +++ b/atomrdf/network/ontology.py @@ -38,9 +38,10 @@ def read_ontology(): pldo = OntologyNetwork(os.path.join(file_location, "data/pldo.owl")) #d15d27712e3f64b405d75c70ad970c9d54ff0b51 podo = OntologyNetwork(os.path.join(file_location, "data/podo.owl")) #6a74d511c5b78042e1cb7a6e76e948fa56de598e asmo = OntologyNetwork(os.path.join(file_location, "data/asmo.owl")) #c7e2da99b9126844f19f225c6a10cdb01aeb55e6 + ldo = OntologyNetwork(os.path.join(file_location, "data/ldo.owl")) #52fc756d2e2f9baedfce478e7f8b790365648cea # combine them - combo = cmso + pldo + podo + asmo + combo = cmso + pldo + podo + asmo + ldo # add namespaces combo.add_namespace("prov", "http://www.w3.org/ns/prov#") @@ -95,7 +96,12 @@ def read_ontology(): combo.add_path(("podo:InterstitialImpurity", "rdfs:label", "string")) combo.add_path(("cmso:AtomicScaleSample", "podo:hasNumberOfImpurityAtoms", "int")) combo.add_path(("cmso:AtomicScaleSample", "podo:hasImpurityConcentration", "float")) - + + #CMSO -> LDO DISL paths + combo.add_path(("cmso:Material", "cmso:hasDefect", "ldo:LineDefect")) + combo.add_path(("cmso:Material", "cmso:hasDefect", "ldo:Dislocation")) + + combo.add_path( ("cmso:ComputationalSample", "prov:wasDerivedFrom", "cmso:ComputationalSample") ) diff --git a/atomrdf/structure.py b/atomrdf/structure.py index d5681d9..c135527 100644 --- a/atomrdf/structure.py +++ b/atomrdf/structure.py @@ -32,7 +32,7 @@ import atomrdf.properties as prp from rdflib import Graph, Namespace, XSD, RDF, RDFS, BNode, URIRef -from atomrdf.namespace import CMSO, PLDO, PODO, UNSAFEASMO, UNSAFECMSO, PROV, Literal +from atomrdf.namespace import CMSO, LDO, PLDO, PODO, UNSAFEASMO, UNSAFECMSO, PROV, Literal from atomman.defect.Dislocation import Dislocation import atomman as am @@ -175,10 +175,10 @@ def _make_general_lattice( def _make_dislocation( - burgers_vector, - slip_vector, + slip_system, dislocation_line, elastic_constant_dict, + burgers_vector=None, dislocation_type="monopole", structure=None, element=None, @@ -190,20 +190,27 @@ def _make_dislocation( graph=None, names=False, label=None, + return_atomman_dislocation=False, ): """ Generate a dislocation structure. Wraps the atomman.defect.Dislocation class. Parameters ---------- - burgers_vector : numpy array of length 3 - The Burgers vector of the dislocation. - slip_vector : numpy array of length 3 - The slip vector of the dislocation. + slip_system : list of lists, shape (2 x 3) + the slip system for the given system. The input should of type [[u, v, w], [h, k, l]]. + [u, v, w] is the slip direction and [h, k, l] is the slip plane. dislocation_line : numpy array of length 3 The dislocation line direction. + This determines the type of dislocation to generate, screw, edge or mixed. + burgers_vector : scalar or numpy array of length 3, optional + if a scalar value (b) is provided, the burgers vector is assumed to be b*[u, v, w]. + if a numpy array is provided, the burgers vector is set to this value. + Default is equal to slip direction [u, v, w] from slip_system. elastic_constant_dict : dict - Dictionary of elastic constants. + Dictionary of elastic constants. The keys should be in Voigt notation. + burgers_vector : numpy array of length 3 + The Burgers vector of the dislocation. dislocation_type : str, optional The type of dislocation to generate. Default is "monopole". structure : crystal lattice to be used @@ -247,6 +254,15 @@ def _make_dislocation( will be generated. If set to "periodicarray", a periodic array of dislocations will be generated. """ + slip_direction = slip_system[0] + slip_plane = slip_system[1] + if burgers_vector is None: + burgers_vector = slip_direction + elif np.isscalar(burgers_vector): + burgers_vector = burgers_vector * np.array(slip_direction) + elif len(burgers_vector) != 3: + raise ValueError('burgers vector should be None, scalar, or of length 3') + if structure is not None: # create a structure with the info @@ -298,7 +314,7 @@ def _make_dislocation( C, burgers_vector, dislocation_line, - slip_vector, + slip_plane, ) if dislocation_type == "monopole": disl_system = disc.monopole() @@ -318,6 +334,20 @@ def _make_dislocation( positions = np.column_stack( (atom_df["pos[0]"].values, atom_df["pos[1]"].values, atom_df["pos[2]"].values) ) + + #find dislocation character + angle = np.dot(dislocation_line, burgers_vector)/(np.linalg.norm(dislocation_line)*np.linalg.norm(burgers_vector)) + angle_rad = np.arccos(angle) + angle_deg = np.degrees(angle_rad) + + disl_dict = { + 'BurgersVector': burgers_vector, + 'SlipPlane': slip_plane, + 'SlipDirection': slip_direction, + 'DislocationLine': dislocation_line, + 'DislocationCharacter': angle_deg, + } + atom_dict = {"positions": positions, "types": types, "species": species} atom_obj = Atoms() atom_obj.from_dict(atom_dict) @@ -326,7 +356,12 @@ def _make_dislocation( output_structure.atoms = atom_obj output_structure = output_structure.modify.remap_to_box() output_structure.label = label + output_structure.graph = graph + output_structure.to_graph() + output_structure.add_dislocation(disl_dict) + if return_atomman_dislocation: + return output_structure, disc return output_structure @@ -1930,6 +1965,52 @@ def _add_atoms(self): # force_identifier = uuid.uuid4() # self.add((force, CMSO.hasIdentifier, Literal(force_identifier, datatype=XSD.string))) + def add_dislocation(self, disl_dict): + if self.graph is None: + return + + #find what kind of disl is present + angle_deg = disl_dict['DislocationCharacter'] + if (np.abs(angle_deg-0) < 1E-3) or (np.abs(angle_deg-180) < 1E-3) or (np.abs(angle_deg-360) < 1E-3): + disl_type = LDO.ScrewDislocation + elif (np.abs(angle_deg-90) < 1E-3) or (np.abs(angle_deg-270) < 1E-3): + disl_type = LDO.EdgeDislocation + else: + disl_type = LDO.MixedDislocation + + line_defect = self.graph.create_node(f"{self._name}_Dislocation", disl_type) + self.graph.add((self.material, CMSO.hasDefect, line_defect)) + + line_direction = self.graph.create_node(f"{self._name}_DislocationLineDirection", LDO.LineDirection) + self.graph.add((line_direction, CMSO.hasComponent_x, Literal(disl_dict['DislocationLine'][0], datatype=XSD.float))) + self.graph.add((line_direction, CMSO.hasComponent_y, Literal(disl_dict['DislocationLine'][1], datatype=XSD.float))) + self.graph.add((line_direction, CMSO.hasComponent_z, Literal(disl_dict['DislocationLine'][2], datatype=XSD.float))) + self.graph.add((line_defect, LDO.hasLineDirection, line_direction)) + + burgers_vector = self.graph.create_node(f"{self._name}_DislocationBurgersVector", LDO.BurgersVector) + self.graph.add((burgers_vector, CMSO.hasComponent_x, Literal(disl_dict['BurgersVector'][0], datatype=XSD.float))) + self.graph.add((burgers_vector, CMSO.hasComponent_y, Literal(disl_dict['BurgersVector'][1], datatype=XSD.float))) + self.graph.add((burgers_vector, CMSO.hasComponent_z, Literal(disl_dict['BurgersVector'][2], datatype=XSD.float))) + self.graph.add((line_defect, LDO.hasBurgersVector, burgers_vector)) + + slip_direction = self.graph.create_node(f"{self._name}_DislocationSlipDirection", LDO.SlipDirection) + self.graph.add((slip_direction, CMSO.hasComponent_x, Literal(disl_dict['SlipDirection'][0], datatype=XSD.float))) + self.graph.add((slip_direction, CMSO.hasComponent_y, Literal(disl_dict['SlipDirection'][1], datatype=XSD.float))) + self.graph.add((slip_direction, CMSO.hasComponent_z, Literal(disl_dict['SlipDirection'][2], datatype=XSD.float))) + + slip_plane = self.graph.create_node(f"{self._name}_DislocationSlipPlane", LDO.SlipPlane) + normal_vector = self.graph.create_node(f"{self._name}_DislocationNormalVector", LDO.NormalVector) + self.graph.add((normal_vector, CMSO.hasComponent_x, Literal(disl_dict['SlipPlane'][0], datatype=XSD.float))) + self.graph.add((normal_vector, CMSO.hasComponent_y, Literal(disl_dict['SlipPlane'][1], datatype=XSD.float))) + self.graph.add((normal_vector, CMSO.hasComponent_z, Literal(disl_dict['SlipPlane'][2], datatype=XSD.float))) + self.graph.add((slip_plane, LDO.hasNormalVector, normal_vector)) + + slip_system = self.graph.create_node(f"{self._name}_DislocationSlipSystem", LDO.SlipSystem) + self.graph.add((slip_direction, LDO.belongsToSystem, slip_system)) + self.graph.add((slip_plane, LDO.belongsToSystem, slip_system)) + self.graph.add((line_defect, LDO.movesOn, slip_system)) + + def add_gb(self, gb_dict): """ Add GB details which will be annotated using PLDO diff --git a/examples/02_grain_boundaries.ipynb b/examples/02_grain_boundaries.ipynb index 7b99f35..310253e 100644 --- a/examples/02_grain_boundaries.ipynb +++ b/examples/02_grain_boundaries.ipynb @@ -21,7 +21,20 @@ "execution_count": 1, "id": "f88eacd6-1bdc-4321-9e80-3d2720d318a1", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c4f616c028b447b58dfe55c7d388eeee", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "from atomrdf import KnowledgeGraph, System" ] @@ -1294,9 +1307,9 @@ } }, "text/html": [ - "