Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions metatomic-torch/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ a changelog](https://keepachangelog.com/en/1.1.0/) format. This project follows
- 2-argument `unit_conversion_factor(from_unit, to_unit)` that parses
arbitrary unit expressions and checks dimensional compatibility

### Deprecated

- `ModelOutput.quantity` field is deprecated; use the 2-argument `unit()` instead
for unit specification. Unit conversion now determines dimensions from the
expression automatically.
- `TensorMap.set_info("quantity", ...)` convention is deprecated; quantity is
no longer required for unit conversion.

### Changed

- 3-argument `unit_conversion_factor(quantity, from_unit, to_unit)` is
Expand Down
2 changes: 2 additions & 0 deletions metatomic-torch/include/metatomic/torch/model.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ class METATOMIC_TORCH_EXPORT ModelOutputHolder: public torch::CustomClassHolder

/// quantity of the output (e.g. energy, dipole, …). If this is an empty
/// string, no unit conversion will be performed.
/// @deprecated This field is no longer required for unit conversion.
/// The unit parser determines dimensions from the expression itself.
const std::string& quantity() const {
return quantity_;
}
Expand Down
7 changes: 7 additions & 0 deletions metatomic-torch/src/model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ static void read_vector_int_json(
/******************************************************************************/

void ModelOutputHolder::set_quantity(std::string quantity) {
if (!quantity.empty()) {
TORCH_WARN(
"ModelOutput.quantity is deprecated and will be removed in a future version. "
"The quantity field is no longer required for unit conversion since the "
"unit parser determines dimensions from the expression itself."
);
}
if (valid_quantity(quantity)) {
validate_unit(quantity, unit_);
}
Expand Down
14 changes: 9 additions & 5 deletions metatomic-torch/tests/models.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,15 @@ TEST_CASE("Models metadata") {
struct WarningHandler: public torch::WarningHandler {
virtual ~WarningHandler() override = default;
void process(const torch::Warning& warning) override {
auto expected = std::string(
"unknown quantity 'unknown', only [charge energy force heat_flux "
"length mass momentum pressure velocity] are supported"
);
CHECK(warning.msg() == expected);
// First warning is deprecation, second is unknown quantity
// We check for the unknown quantity warning
if (warning.msg().find("unknown quantity") != std::string::npos) {
auto expected = std::string(
"unknown quantity 'unknown', only [charge energy force heat_flux "
"length mass momentum pressure velocity] are supported"
);
CHECK(warning.msg() == expected);
}
}
};

Expand Down
4 changes: 4 additions & 0 deletions python/metatomic_ase/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,13 @@ python_files = ["*.py"]
testpaths = ["tests"]
filterwarnings = [
"error",
# TorchScript deprecation warnings
"ignore:`torch.jit.script` is deprecated. Please switch to `torch.compile` or `torch.export`:DeprecationWarning",
"ignore:`torch.jit.script_method` is deprecated. Please switch to `torch.compile` or `torch.export`:DeprecationWarning",
"ignore:`torch.jit.save` is deprecated. Please switch to `torch.export`:DeprecationWarning",
"ignore:`torch.jit.load` is deprecated. Please switch to `torch.export`:DeprecationWarning",
# There is a circular dependency between metatomic-torch and vesin.metatomic
"ignore:.*vesin.metatomic was only tested with metatomic.torch >=0.1.3,<0.2.*:UserWarning",
# Deprecated function used internally
"ignore:`compute_requested_neighbors_from_options` is deprecated:UserWarning",
]
3 changes: 2 additions & 1 deletion python/metatomic_ase/tests/calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,8 @@ def test_additional_input(atoms):
assert head == "extra"
assert name in inputs

assert tensor.get_info("quantity") == inputs[name].quantity
# quantity info is no longer set (deprecated); just check unit is set
assert tensor.get_info("unit") == inputs[name].unit
values = tensor[0].values.numpy()

expected = ARRAY_QUANTITIES[name]["getter"](atoms).reshape(values.shape)
Expand Down
16 changes: 15 additions & 1 deletion python/metatomic_ase/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import re

import pytest


Expand All @@ -6,5 +8,17 @@ def fail_test_with_output(capfd):
yield
captured = capfd.readouterr()
# the code should not print anything to stdout or stderr
# except for expected deprecation warnings
assert captured.out == ""
assert captured.err == ""
# Filter out expected deprecation warnings
stderr_lines = captured.err.splitlines()
unexpected_errors = [
line
for line in stderr_lines
if not re.search(
r"(ModelOutput\.quantity is deprecated|"
r"compute_requested_neighbors_from_options.*is deprecated)",
line,
)
]
assert "".join(unexpected_errors) == "", f"Unexpected stderr output: {captured.err}"
5 changes: 5 additions & 0 deletions python/metatomic_torch/metatomic/torch/documentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,11 @@ def quantity(self) -> str:
Quantity of the output (e.g. energy, dipole, …). If this is an empty string, no
unit conversion will be performed.

.. deprecated::
The ``quantity`` field is deprecated and will be removed.
Unit conversion determines dimensions from the unit expression.
Set ``quantity`` to an empty string to suppress deprecation warnings.

The list of possible quantities is available :ref:`here
<known-base-units>`.
"""
Expand Down
10 changes: 8 additions & 2 deletions python/metatomic_torch/metatomic/torch/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,11 @@ def forward(
if declared.quantity == "" or requested.quantity == "":
continue

# Note: Deprecation warning for quantity is emitted from C++ when
# ModelOutput is constructed with non-empty quantity.
# We don't warn here because TorchScript can't handle
# DeprecationWarning.

if declared.quantity != requested.quantity:
raise ValueError(
f"model produces values as '{declared.quantity}' for the "
Expand Down Expand Up @@ -971,7 +976,9 @@ def _convert_systems_units(
tensor = system.get_data(name)
unit = tensor.get_info("unit")

if requested.quantity != "" and unit is not None:
# Convert units if both the tensor and requested output have units.
# The quantity field is deprecated; unit conversion is dimension-aware.
if unit is not None and requested.unit != "":
conversion = unit_conversion_factor(
unit,
requested.unit,
Expand Down Expand Up @@ -1009,7 +1016,6 @@ def _convert_systems_units(
blocks=new_blocks,
)
new_tensor.set_info("unit", requested.unit)
new_tensor.set_info("quantity", requested.quantity)
new_system.add_data(name, new_tensor)

new_systems.append(new_system)
Expand Down
4 changes: 4 additions & 0 deletions python/metatomic_torch/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ python_files = ["*.py"]
testpaths = ["tests"]
filterwarnings = [
"error",
# ModelOutput.quantity deprecation
"ignore:ModelOutput.quantity is deprecated:DeprecationWarning",
# TorchScript deprecation warnings
"ignore:`torch.jit.script` is deprecated. Please switch to `torch.compile` or `torch.export`:DeprecationWarning",
"ignore:`torch.jit.save` is deprecated. Please switch to `torch.export`:DeprecationWarning",
Expand All @@ -67,4 +69,6 @@ filterwarnings = [
"ignore:`torch.jit.load` is not supported in Python 3.14+:DeprecationWarning",
# There is a circular dependency between metatomic-torch and vesin.metatomic
"ignore:.*vesin.metatomic was only tested with metatomic.torch >=0.1.3,<0.2.*:UserWarning",
# Deprecated function used internally by metatomic-ase calculator
"ignore:`compute_requested_neighbors_from_options` is deprecated:UserWarning",
]
16 changes: 15 additions & 1 deletion python/metatomic_torch/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import re

import pytest


Expand All @@ -6,5 +8,17 @@ def fail_test_with_output(capfd):
yield
captured = capfd.readouterr()
# the code should not print anything to stdout or stderr
# except for expected deprecation warnings
assert captured.out == ""
assert captured.err == ""
# Filter out expected deprecation warnings
stderr_lines = captured.err.splitlines()
unexpected_errors = [
line
for line in stderr_lines
if not re.search(
r"(ModelOutput\.quantity is deprecated|"
r"compute_requested_neighbors_from_options.*is deprecated)",
line,
)
]
assert "".join(unexpected_errors) == "", f"Unexpected stderr output: {captured.err}"
2 changes: 1 addition & 1 deletion python/metatomic_torch/tests/examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def test_export_atomistic_model(tmp_path):
)

outputs = {
"energy": ModelOutput(quantity="energy", unit="eV", per_atom=False),
"energy": ModelOutput(unit="eV", per_atom=False),
}

# run bare model
Expand Down
1 change: 0 additions & 1 deletion python/metatomic_torch/tests/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,6 @@ def test_not_requested_output(system):
def test_systems_unit_conversion(system):
requested_inputs = {
"masses": ModelOutput(
quantity="mass",
unit="kg",
per_atom=True,
),
Expand Down
73 changes: 38 additions & 35 deletions python/metatomic_torch/tests/units.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,41 +212,42 @@ def test_overflow_division():

def test_valid_units():
# just checking that all of these are valid
ModelOutput(quantity="length", unit="A")
ModelOutput(quantity="length", unit="Angstrom")
ModelOutput(quantity="length", unit="Bohr")
ModelOutput(quantity="length", unit="meter")
ModelOutput(quantity="length", unit=" centimeter")
ModelOutput(quantity="length", unit="cm")
ModelOutput(quantity="length", unit="millimeter")
ModelOutput(quantity="length", unit="mm")
ModelOutput(quantity="length", unit=" micrometer")
ModelOutput(quantity="length", unit="um")
ModelOutput(quantity="length", unit="µm")
ModelOutput(quantity="length", unit="nanometer")
ModelOutput(quantity="length", unit="nm ")

ModelOutput(quantity="energy", unit="eV")
ModelOutput(quantity="energy", unit="meV")
ModelOutput(quantity="energy", unit="Hartree")
ModelOutput(quantity="energy", unit="kcal / mol ")
ModelOutput(quantity="energy", unit="kJ/mol")
ModelOutput(quantity="energy", unit="Joule")
ModelOutput(quantity="energy", unit="J")
ModelOutput(quantity="energy", unit="Rydberg")
ModelOutput(quantity="energy", unit="Ry")

ModelOutput(quantity="force", unit="eV/Angstrom")
ModelOutput(quantity="force", unit="eV/A")

ModelOutput(quantity="pressure", unit="eV/Angstrom^3")
ModelOutput(quantity="pressure", unit="eV/A^3")

ModelOutput(quantity="momentum", unit="u * A/ fs")
ModelOutput(quantity="momentum", unit=" (eV*u )^(1/ 2 )")

ModelOutput(quantity="velocity", unit="A/fs")
ModelOutput(quantity="velocity", unit="A/s")
# quantity parameter is deprecated, only testing unit parsing
ModelOutput(unit="A")
ModelOutput(unit="Angstrom")
ModelOutput(unit="Bohr")
ModelOutput(unit="meter")
ModelOutput(unit=" centimeter")
ModelOutput(unit="cm")
ModelOutput(unit="millimeter")
ModelOutput(unit="mm")
ModelOutput(unit=" micrometer")
ModelOutput(unit="um")
ModelOutput(unit="µm")
ModelOutput(unit="nanometer")
ModelOutput(unit="nm ")

ModelOutput(unit="eV")
ModelOutput(unit="meV")
ModelOutput(unit="Hartree")
ModelOutput(unit="kcal / mol ")
ModelOutput(unit="kJ/mol")
ModelOutput(unit="Joule")
ModelOutput(unit="J")
ModelOutput(unit="Rydberg")
ModelOutput(unit="Ry")

ModelOutput(unit="eV/Angstrom")
ModelOutput(unit="eV/A")

ModelOutput(unit="eV/Angstrom^3")
ModelOutput(unit="eV/A^3")

ModelOutput(unit="u * A/ fs")
ModelOutput(unit=" (eV*u )^(1/ 2 )")

ModelOutput(unit="A/fs")
ModelOutput(unit="A/s")


# ---- Accumulated floating-point error with fractional powers ----
Expand Down Expand Up @@ -318,6 +319,8 @@ def test_micro_sign_microsecond():

def test_quantity_unit_mismatch():
# energy quantity with force unit
# quantity parameter is deprecated, but we still test unit validation
# Warning is emitted via C++ TORCH_WARN, not Python warnings
with pytest.raises((ValueError, RuntimeError), match="incompatible with quantity"):
ModelOutput(quantity="energy", unit="eV/A")

Expand Down
2 changes: 2 additions & 0 deletions python/metatomic_torchsim/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ filterwarnings = [
"ignore:`torch.jit.load` is not supported in Python 3.14+:DeprecationWarning",
# There is a circular dependency between metatomic-torch and vesin.metatomic
"ignore:.*vesin.metatomic was only tested with metatomic.torch >=0.1.3,<0.2.*:UserWarning",
# Deprecated function used internally by metatomic-ase calculator
"ignore:`compute_requested_neighbors_from_options` is deprecated:UserWarning",
# This comes from inside TorchSim
"ignore:The 'nvalchemiops.neighborlist' module has been renamed to 'nvalchemiops.neighbors':DeprecationWarning",
]
16 changes: 15 additions & 1 deletion python/metatomic_torchsim/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import re

import pytest


Expand All @@ -6,5 +8,17 @@ def fail_test_with_output(capfd):
yield
captured = capfd.readouterr()
# the code should not print anything to stdout or stderr
# except for expected deprecation warnings
assert captured.out == ""
assert captured.err == ""
# Filter out expected deprecation warnings
stderr_lines = captured.err.splitlines()
unexpected_errors = [
line
for line in stderr_lines
if not re.search(
r"(ModelOutput\.quantity is deprecated|"
r"compute_requested_neighbors_from_options.*is deprecated)",
line,
)
]
assert "".join(unexpected_errors) == "", f"Unexpected stderr output: {captured.err}"
Loading