"""Set up eos commandline interface."""
from __future__ import annotations
from pathlib import Path
from typing import Annotated, get_args
from typer import Context, Option, Typer
from typer_config import use_config
from janus_core.cli.types import (
Architecture,
CalcKwargs,
Device,
LogPath,
MinimizeKwargs,
ModelPath,
ReadKwargsLast,
StructPath,
Summary,
WriteKwargs,
)
from janus_core.cli.utils import yaml_converter_callback
app = Typer()
[docs]
@app.command()
@use_config(yaml_converter_callback)
def eos(
# numpydoc ignore=PR02
ctx: Context,
struct: StructPath,
min_volume: Annotated[float, Option(help="Minimum volume scale factor.")] = 0.95,
max_volume: Annotated[float, Option(help="Maximum volume scale factor.")] = 1.05,
n_volumes: Annotated[int, Option(help="Number of volumes.")] = 7,
eos_type: Annotated[
str, Option(help="Type of fit for equation of state.")
] = "birchmurnaghan",
minimize: Annotated[
bool, Option(help="Whether to minimize initial structure before calculations.")
] = True,
minimize_all: Annotated[
bool,
Option(help="Whether to minimize all generated structures for calculations."),
] = False,
fmax: Annotated[
float, Option(help="Maximum force for optimization convergence.")
] = 0.1,
minimize_kwargs: MinimizeKwargs = None,
write_structures: Annotated[
bool,
Option(help="Whether to write out all genereated structures."),
] = False,
write_kwargs: WriteKwargs = None,
plot_to_file: Annotated[
bool,
Option(help="Whether to plot equation of state."),
] = False,
arch: Architecture = "mace_mp",
device: Device = "cpu",
model_path: ModelPath = None,
read_kwargs: ReadKwargsLast = None,
calc_kwargs: CalcKwargs = None,
file_prefix: Annotated[
Path | None,
Option(
help=(
"""
Prefix for output filenames. Default is inferred from structure name,
or chemical formula.
"""
),
),
] = None,
log: LogPath = None,
tracker: Annotated[
bool, Option(help="Whether to save carbon emissions of calculation")
] = True,
summary: Summary = None,
) -> None:
"""
Calculate equation of state and write out results.
Parameters
----------
ctx
Typer (Click) Context. Automatically set.
struct
Path of structure to simulate.
min_volume
Minimum volume scale factor. Default is 0.95.
max_volume
Maximum volume scale factor. Default is 1.05.
n_volumes
Number of volumes to use. Default is 7.
eos_type
Type of fit for equation of state. Default is "birchmurnaghan".
minimize
Whether to minimize initial structure before calculations. Default is True.
minimize_all
Whether to optimize geometry for all generated structures. Default is False.
fmax
Set force convergence criteria for optimizer in units eV/Å.
Default is 0.1.
minimize_kwargs
Other keyword arguments to pass to geometry optimizer. Default is {}.
write_structures
True to write out all genereated structures. Default is False.
write_kwargs
Keyword arguments to pass to ase.io.write to save generated structures.
Default is {}.
plot_to_file
Whether to save plot equation of state to svg. Default is False.
arch
MLIP architecture to use for geometry optimization.
Default is "mace_mp".
device
Device to run model on. Default is "cpu".
model_path
Path to MLIP model. Default is `None`.
read_kwargs
Keyword arguments to pass to ase.io.read. By default,
read_kwargs["index"] is -1.
calc_kwargs
Keyword arguments to pass to the selected calculator. Default is {}.
file_prefix
Prefix for output filenames. Default is inferred from structure name, or
chemical formula.
log
Path to write logs to. Default is inferred from the name of the structure file.
tracker
Whether to save carbon emissions of calculation in log file and summary.
Default is True.
summary
Path to save summary of inputs, start/end time, and carbon emissions. Default
is inferred from the name of the structure file.
config
Path to yaml configuration file to define the above options. Default is None.
"""
from janus_core.calculations.eos import EoS
from janus_core.cli.utils import (
carbon_summary,
check_config,
end_summary,
parse_typer_dicts,
save_struct_calc,
set_read_kwargs_index,
start_summary,
)
from janus_core.helpers.janus_types import EoSNames
# Check options from configuration file are all valid
check_config(ctx)
[read_kwargs, calc_kwargs, minimize_kwargs, write_kwargs] = parse_typer_dicts(
[read_kwargs, calc_kwargs, minimize_kwargs, write_kwargs]
)
if eos_type not in get_args(EoSNames):
raise ValueError(f"Fit type must be one of: {get_args(EoSNames)}")
# Read only first structure by default and ensure only one image is read
set_read_kwargs_index(read_kwargs)
# Check fmax option not duplicated
if "fmax" in minimize_kwargs:
raise ValueError("'fmax' must be passed through the --fmax option")
minimize_kwargs["fmax"] = fmax
log_kwargs = {"filemode": "w"}
if log:
log_kwargs["filename"] = log
# Dictionary of inputs for EoS class
eos_kwargs = {
"struct_path": struct,
"arch": arch,
"device": device,
"model_path": model_path,
"read_kwargs": read_kwargs,
"calc_kwargs": calc_kwargs,
"attach_logger": True,
"log_kwargs": log_kwargs,
"track_carbon": tracker,
"min_volume": min_volume,
"max_volume": max_volume,
"n_volumes": n_volumes,
"eos_type": eos_type,
"minimize": minimize,
"minimize_all": minimize_all,
"minimize_kwargs": minimize_kwargs,
"write_structures": write_structures,
"write_kwargs": write_kwargs,
"plot_to_file": plot_to_file,
"file_prefix": file_prefix,
}
# Initialise EoS
equation_of_state = EoS(**eos_kwargs)
# Set summary and log files
summary = equation_of_state._build_filename(
"eos-summary.yml", filename=summary
).absolute()
log = equation_of_state.log_kwargs["filename"]
# Store inputs for yaml summary
inputs = eos_kwargs.copy()
# Add structure, MLIP information, and log to inputs
save_struct_calc(
inputs=inputs,
struct=equation_of_state.struct,
struct_path=struct,
arch=arch,
device=device,
model_path=model_path,
read_kwargs=read_kwargs,
calc_kwargs=calc_kwargs,
log=log,
)
# Save summary information before calculations begin
start_summary(command="eos", summary=summary, inputs=inputs)
# Run equation of state calculations
equation_of_state.run()
# Save carbon summary
if tracker:
carbon_summary(summary=summary, log=log)
# Time after calculations have finished
end_summary(summary)