-
Notifications
You must be signed in to change notification settings - Fork 11
/
define_ontology.py
executable file
·249 lines (188 loc) · 8.19 KB
/
define_ontology.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""An example script that uses EMMO to describe a vertical use case on
welding aluminium to steel and how the thin layer of intermetallic
that are formed at the interface is influencing the overall
properties. Based on TEM observations using scanning precision
electron diffraction (SPED) the following (simplified) sequence of
intermetallic phases could be established:
Al | alpha-AlFeSi | Fe4Al13 | Fe2Al5 | Fe
which is consistent with phase stability when the Fe-concentration is
increasing when going from left to right.
In this case study three scales are considered:
- Macroscopic scale: predicts the overall mechanical behaviour of
the welded structure during deformation.
- Microscopic scale: a local crystal plasticity model of a small
part of the interface. The constitutive equations were based on
the results from DFT. The results from this model was used to
calibrate decohesion elements for the macroscopic scale.
- Electronic scale: elastic properties of the individual phases as
well work of decohesion within and at the interfaces between the
phases were calculated with DFT [1]. The calculation of work of
decohesion was performed as a series of rigid steps, providing
stress-strain relations in both tensile and shear.
References
----------
[1] Khalid et al. Proc. Manufact. 15 (2018) 1407
"""
# pylint: disable=fixme,invalid-name,too-few-public-methods
from ontopy import World
# Load EMMO
world = World(filename="demo.sqlite3")
emmo = world.get_ontology(
"https://raw.githubusercontent.com/emmo-repo/EMMO/master/emmo.ttl"
)
emmo.load()
# emmo.sync_reasoner()
# Create a new ontology with out extensions that imports EMMO
onto = world.get_ontology("http://www.emmc.info/emmc-csa/demo#")
onto.imported_ontologies.append(emmo)
# Add new classes and object/data properties needed by the use case
with onto:
#
# Relations
# =========
class hasType(emmo.hasConvention):
"""Associates a type (string, number...) to a property."""
class isTypeOf(emmo.hasConvention):
"""Associates a property to a type (string, number...)."""
inverse_property = hasType
#
# Units
# =====
# TODO: remove
class SquareLengthDimension(emmo.PhysicalDimension):
"""Squared length dimension."""
is_a = [emmo.hasSymbolData.value("T0 L2 M0 I0 Θ0 N0 J0")]
# TODO: remove
class SquareMetre(emmo.SICoherentDerivedUnit):
"""A square metre unit."""
emmo.altLabel = ["m²"]
is_a = [emmo.hasPhysicalDimension.only(SquareLengthDimension)]
#
# Properties
# ==========
# TODO: update instead of redefine Position
class Position(emmo.Length):
"""Spatial position of an physical entity."""
is_a = [
emmo.hasReferenceUnit.only(
emmo.hasPhysicalDimension.only(emmo.LengthDimension)
),
hasType.exactly(3, emmo.Real),
]
# TODO: remove
class Area(emmo.ISQDerivedQuantity):
"""Extent of a surface."""
is_a = [
emmo.hasReferenceUnit.only(
emmo.hasPhysicalDimension.only(SquareLengthDimension)
),
hasType.exactly(1, emmo.Real),
]
emmo.Pressure.is_a.append(hasType.exactly(1, emmo.Real))
# TODO: update when we have dimensionality
class StiffnessTensor(emmo.Pressure):
r"""The stiffness tensor $c_{ijkl}$ is a property of a continuous
elastic material that relates stresses to strains (Hooks's
law) according to
$\sigma_{ij} = c_{ijkl} \epsilon_{kl}$
Due to symmetry and using the Voight notation, the stiffness
tensor can be represented as a symmetric 6x6 matrix
/ c_1111 c_1122 c_1133 c_1123 c_1131 c_1112 \
| c_2211 c_2222 c_2233 c_2223 c_2231 c_2212 |
| c_3311 c_3322 c_3333 c_3323 c_3331 c_3312 |
| c_2311 c_2322 c_2333 c_2323 c_2331 c_2312 |
| c_3111 c_3122 c_3133 c_3123 c_3131 c_3112 |
\ c_1211 c_1222 c_1233 c_1223 c_1231 c_1212 /
"""
is_a = [hasType.exactly(36, emmo.Real)]
# class Spacegroup(emmo.DescriptiveProperty):
# """A spacegroup is the symmetry group off all symmetry operations
# that apply to a crystal structure.
#
# It is identifies by its Hermann-Mauguin symbol or space group
# number (and setting) in the International tables of
# Crystallography."""
# is_a = [hasType.exactly(1, emmo.String)]
# pass
# class Plasticity(emmo.PhysicalQuantity):
# """Describes Yield stress and material hardening."""
# is_a = [hasUnit.exactly(1, Pascal),
# hasType.min(2, emmo.Real)]
# Will be included when dimensionality is in place in EMMO.
# class TractionSeparation(Pressure):
# """The force required to separate two materials a certain distance
# per interface area. Hence, traction_separation is a curve, that
# numerically can be represented as a series of (force,
# separation_distance) pairs."""
# is_a = [hasUnit.exactly(1, Pascal),
# hasType.min(4, emmo.Real)]
# class LoadCurve(Pressure):
# """A measure for the displacement of a material as function of the
# appliced force."""
# is_a = [hasUnit.exactly(1, Pascal),
# hasType.min(4, emmo.Real)]
# Crystallography-related classes
# TODO: import crystallography ontology instead
# -------------------------------
class LatticeVector(emmo.Length):
"""A vector that participitates defining the unit cell."""
is_a = [hasType.exactly(3, emmo.Real)]
# FIXME - CrystalUnitCell is not a matter, but a model or a symbolic
# Just use crystalography
class CrystalUnitCell(emmo.Material):
"""A volume defined by the 3 unit cell vectors. It contains the atoms
constituting the unit cell of a crystal."""
is_a = [
emmo.hasSpatialDirectPart.some(emmo.BondedAtom),
emmo.hasProperty.exactly(3, LatticeVector),
emmo.hasProperty.exactly(1, StiffnessTensor),
]
class InterfaceModel(CrystalUnitCell):
"""A crystal interface."""
is_a = [emmo.hasProperty.some(Area)]
class Crystal(emmo.Solid):
"""A periodic crystal structure."""
is_a = [emmo.hasSpatialDirectPart.only(CrystalUnitCell)]
# Add some properties to our atoms
emmo.Atom.is_a.append(emmo.hasProperty.exactly(1, Position))
# Continuum
# ---------
class Boundary(emmo.Continuum):
"""A boundary is a 4D region of spacetime shared by two material
entities."""
equivalent_to = [emmo.hasSpatialDirectPart.exactly(2, emmo.Continuum)]
is_a = [emmo.hasProperty.exactly(1, Area)]
class Phase(emmo.Continuum):
"""A phase is a continuum in which properties are homogeneous and can
have different state of matter."""
is_a = [emmo.hasProperty.exactly(1, StiffnessTensor)]
class RVE(emmo.Continuum):
"""Representative volume element. The minimum volume that is
representative for the system in question."""
is_a = [
emmo.hasSpatialDirectPart.only(
Phase | Boundary # pylint: disable=unsupported-binary-operation
)
]
class WeldedComponent(emmo.EngineeredMaterial):
"""A welded component consisting of two materials welded together
using a third welding material. Hence it has spatial direct
parts 3 materials and two boundaries."""
is_a = [
emmo.hasSpatialDirectPart.exactly(3, emmo.Material),
emmo.hasSpatialDirectPart.exactly(2, Boundary),
# emmo.hasProperty.exactly(1, LoadCurve),
]
# Sync attributes to make sure that all classes get a `label` and to
# include the docstrings in the comments
onto.sync_attributes(name_policy="uuid", name_prefix="DEMO_")
# Run the reasoner
# onto.sync_reasoner()
# set version of ontology
onto.set_version("0.9")
# Save our new EMMO-based ontology to demo.owl
onto.save("demo.owl", overwrite=True)
# ...and to the sqlite3 database.
world.save()