TargetProperty
==============
The primary purpose of the TargetProperty class is to perform analysis to
calculate a property of interest such as the melting point or elastic constant
of a materials. This module can utilize other modules within the orchestrator
to carry out the target property calculations. For example, the
:ref:`target_property_module` can be used to perform melting point
calculations by utilizing :ref:`simulator_module` and :ref:`workflow_module`
modules.
The abstract base class :class:`~.TargetProperty` provides the standard
interface for all of the concrete implementations.
See the full API for the module at :ref:`target_property_module`.
Use Cases
---------
Basic usage
^^^^^^^^^^^
A simple example of how to use the target property class in a standalone application
for melting point calculations can be seen below. The target property class uses
functionalities from several other modules such as Simulator, Workflow and Storage.
The example uses the LAMMPS simulator, local storage and local workflow. The user should
modify .json file located in the test_inputs folder according to needs of a specific
calculation.::
from target_property import target_property_builder
from storage import storage_builder
from simulator import simulator_builder
from workflow import workflow_builder
# Choose MeltingPoint for target property type.
# Target property args are read from the input json file.
built_target_property = target_property_builder.build(
type=MeltingPoint, target_property_args)
# Build local storage. The database path and name are not shown here
built_storage = storage_builder.build(storage_type='LOCAL')
# Build local workflow.
# Workflow root and workflow args are not shown here and read from json file.
built_workflow = workflow_builder.build(workflow_type='LOCAL')
# To estimate melting temperature using a single calculation
results_dict = built_target_property.calculate_property(
workflow=built_workflow, storage=built_storage)
value = results_dict['property_value']
value_std = results_dict['property_std']
value_calc_ids = results_dict['calc_ids']
# To estimate melting temperature using multiple calculations with a standard deviation
results_dict = built_target_property.calculate_with_error(
n_calc=4, workflow=built_workflow)
avg_value = results_dict['property_value']
value_std = results_dict['property_std']
value_calc_ids = results_dict['calc_ids']
.. _kimrun:
KIMRun
^^^^^^
This class uses `KIM Tests `_
to calculate material properties. This is done by invoking the
`KIM Developer Platform `_
as a Podman (default) or Singularity image.
:func:`~orchestrator.target_property.kimrun.KIMRun.calculate_property`
has one required argument, ``get_test_result_args``. This is a dictionary of
keyword arguments that will be passed to a ``get_test_result`` KIM simplified
query. See
`Querying KIM Content `_
for more info.
``get_test_result_args`` may also be a list of dictionaries if multiple query
results are desired.
The ``model`` argument should be omitted, as it is provided
by the ``potential`` argument to
:func:`~orchestrator.target_property.property_base.TargetProperty.calculate_property`.
In addition to the examples on this page, you can experiment with the web GUI at
`query.openkim.org `__ to learn the syntax for
``get_test_result``.
:class:`~orchestrator.target_property.kimrun.KIMRun` works with
:class:`~orchestrator.potential.potential_base.Potential` objects whose
:func:`~orchestrator.potential.potential_base.Potential.save_potential_to_kimkit`
function saves an archive of a directory that is installable using the KIM API.
Alternatively, the ``potential`` argument may be a string naming a potential
that is already archived in KIMKit.
As with the generic example above, various invocations of
:class:`~orchestrator.target_property.kimrun.KIMRun` using a ``json`` file
can be seen in ``test/target_property/test_inputs``. This module does not
use any Simulator or Storage.
Additionally, ``KIMRun`` may be invoked directly. The below example will
be used to demonstrate details of usage::
from orchestrator.target_property.kimrun import KIMRun
my_kimrun = KIMRun()
print(
my_kimrun.calculate_property(
potential = "Sim_LAMMPS_MEAM_Lenosky_2017_W__SM_631352869360_000",
get_test_result_args = [
{
"test": ["VacancyFormationEnergyRelaxationVolume_bcc_W__TE_197190379294"],
"prop": ["monovacancy-neutral-relaxed-formation-potential-energy-crystal-npt"],
"keys": ["relaxed-formation-potential-energy"],
"units": ["eV"]
},
{
"test": ["VacancyFormationEnergyRelaxationVolume_bcc_W__TE_197190379294"],
"prop": ["monovacancy-neutral-relaxation-volume-crystal-npt"],
"keys": ["relaxation-volume"],
"units": ["angstrom^3"]
},
{
"test": ["SurfaceEnergyCubicCrystalBrokenBondFit_bcc_W__TE_378149060769"],
"prop": ["surface-energy-cubic-crystal-npt"],
"keys": ["miller-indices","surface-energy"],
"units": [None,"eV/angstrom^2"]
}
]
)
)
When specifying the ``test`` key(s), the version and the prefix are optional.
The value ``VacancyFormationEnergyRelaxationVolume_bcc_W__TE_197190379294`` in the example above
automatically runs the latest version of that test found in KIMKit.
``VacancyFormationEnergyRelaxationVolume_bcc_W__TE_197190379294_001``, ``TE_197190379294``, or
``TE_197190379294_001`` would also be valid values that run the same test.
Any Tests requested to run by the ``test`` key(s) in
``get_test_result_args``, as well as their Test Drivers
and their upstream dependencies (i.e. almost any KIM Test depends on the
LatticeConstant test for the corresponding material) must be manually archived in
KIMKit ahead of time. A full listing of OpenKIM tests can be found
`here `__.
To demonstrate, consider the Test
``VacancyFormationEnergyRelaxationVolume_bcc_W__TE_197190379294_001``.
The source files are available at the bottom of
`its page on openkim.org `_
(use the "Files" link at the top right to jump to the bottom).
To make it possible to run the Test, you must download the ``.txz`` archives
for the Test itself
(``VacancyFormationEnergyRelaxationVolume_bcc_W__TE_197190379294_001.txz``), and its Driver
(``VacancyFormationEnergyRelaxationVolume__TD_647413317626_001.txz``) from the linked page.
Additionally note that the listing of source files contains a file named
``dependencies.edn`` containing the text ``[ "TE_155104699590" ]``.
This indicates that this Test depends on the result of another Test, which
must also be installed. By searching for the Short KIM ID in the full
list of KIM Tests, we can see that it is the Lattice Constant test,
`LatticeConstantCubicEnergy_bcc_W__TE_155104699590_007 `_.
Even if you do not need any properties computed by that Test, it must
be installed to run the VacancyFormationEnergyRelaxationVolume test, so you would need to download
the ``.txz`` files for the Test and its Driver in the same way.
Once you have the ``.txz`` files downloaded, you must add them to KIMKit.
For example, assuming you have the 4 ``.txz`` files in question in the
current working directory, the following Python script would add them to
KIMKit. Drivers must be imported before corresponding Tests if the Driver
is not already in KIMKit.::
import tarfile, kimkit
kimkit.models.import_item(tarfile.open(
"LatticeConstantCubicEnergy__TD_475411767977_007.txz"))
kimkit.models.import_item(tarfile.open(
"LatticeConstantCubicEnergy_bcc_W__TE_155104699590_007.txz"))
kimkit.models.import_item(tarfile.open(
"VacancyFormationEnergyRelaxationVolume_bcc_W__TE_197190379294_001.txz"))
kimkit.models.import_item(tarfile.open(
"VacancyFormationEnergyRelaxationVolume__TD_647413317626_001.txz"))
As is evident from the Test names, the choice of Test determines the crystal
structure and species. All results in the example above are for BCC tungsten.
As described in
`Querying KIM Content `_,
the values returned by the ``get_test_result`` queries are the
`KIM Property keys `_
that are requested in the query. The full list of KIM Property Definitions is
`here `__. In the example above, the
``prop`` keys of ``get_test_result_args`` indicate that the properties that
will be queried for are
`monovacancy-neutral-relaxed-formation-potential-energy-crystal-npt `_
and so on. The ``keys`` keys of ``get_test_result_args`` indicate which keys will be
extracted from those properties.
By default, The ``property_value`` returned as part of ``results_dict``
is a a doubly nested list. First index is over each dictionary in ``get_test_result_args``.
Second index is over the number of times the queried Test returned the queried property
(e.g. multiple surface energies). Third index is over the keys requested within the property.
The values may be arrays of arbitrary dimension themselves.
If :func:`~orchestrator.target_property.kimrun.KIMRun.calculate_property` is passed the argument
``flatten=True``, then ``property_value`` is flattened into a 1-D array (this is done for testing,
as the current test suite can't handle nested lists with inhomogeneous dimensions). Currently,
uncertainty is not supported.
To demonstrate the organization of the (non-flattened) output, see the output of the Python example
above, with indentation and comments added for clarity::
[
# Result of the first query.
# The VacancyFormationEnergyRelaxationVolume test returns a single
# instance of the property
# "monovacancy-neutral-relaxed-formation-potential-energy-crystal-npt",
# Therefore there is only one element corresponding to returned
# property instances. Because we only requested one key from this property
# ("relaxed-formation-potential-energy"), there is only one element
# in the inner list corresponding to requested keys.
[[3.19968717282485]],
# Result of the second query. It is analogous to above, except for
# vacancy relaxation volume. Even though the two quantities were
# computed by the same test, they are written to different
# properties (in this case,
# "monovacancy-neutral-relaxation-volume-crystal-npt"). Therefore we must
# query for them separately.
[[5.640063822313584]],
# Result of the third query. Here, the
# SurfaceEnergyCubicCrystalBrokenBondFit test returns 4 instances of the
# "surface-energy-cubic-crystal-npt" property, corresponding to different
# Miller indices, so there are 4 elements in the list corresponding to
# returned property instances. Within each of those lists, there are two
# elements corresponding to the keys we requested -- "miller-indices" and
# "surface-energy"
[
[[1, 1, 1], 0.2278375012400934],
[[1, 0, 0], 0.214109530467288],
[[1, 2, 1], 0.2130027972015625],
[[1, 1, 0], 0.1817853309873278]
]
]
Inheritance Graph
-----------------
.. inheritance-diagram::
orchestrator.target_property.elastic_constants
orchestrator.target_property.factory
orchestrator.target_property.kimrun
orchestrator.target_property.melting_point
:parts: 3