Fixed-Point SCF ASE Calculator
The fixed-point ASE calculator is implemented in
mace_scf/calculators/fixedpoint_scf.py.
Use this page as an API reference for constructing the calculator. For the SCF
concepts behind num_scf_steps, mixing_parameter, Fermi levels, initial
states, and restarts, read using fixed-point SCF models first.
Class
Use:
from mace_scf.calculators.fixedpoint_scf import MACEFixedPointSCF
MACEPolarizable is still available as a compatibility alias, but new code
should use MACEFixedPointSCF.
Minimal Example
For a neutral constant-charge calculation with no applied external field, the calculator can be constructed with only the model path, device, boundary condition handling, and SCF options:
from mace_scf.calculators.fixedpoint_scf import MACEFixedPointSCF
calc = MACEFixedPointSCF(
model_path="fit.model",
device="cuda",
pbc_handling="slab",
scf_options={
"num_scf_steps": 100,
"scf_tolerance": 1.0e-6,
"mixing_parameter": 0.2,
"constant_charge": True,
"use_autograd_forces": True,
},
)
atoms.calc = calc
energy = atoms.get_potential_energy()
forces = atoms.get_forces()
If atoms.info["total_charge"] is absent, the calculator uses 0.0. If
atoms.info["external_field"] is absent, the calculator uses a zero external
field. If atoms.info["initial_fermi_level"] is absent, the calculator uses a
zero Fermi-level input.
Constructor Arguments
Required arguments:
model_pathpath to the saved fixed-point model;devicedevice passed through the usual MACE/PyTorch device handling, such as"cpu"or"cuda".
Common optional arguments:
scf_optionsdictionary containing SCF runtime options;pbc_handlingboundary-condition mode used by the model electrostatics, for example"mixed_periodic","slab","pbc","realspace", or"molecule_in_box";total_charge_keyname of theatoms.infofield containing the requested total charge;external_field_keyname of theatoms.infofield containing the applied homogeneous field;fermi_level_keyname of theatoms.infofield containing the Fermi-level input;ignore_nonconvergedsuppresses the non-convergence warning when the final density change is abovescf_tolerance. Divergence and large constant-charge errors can still raise errors;save_full_scf_historystores the full density history incalc.results["full_scf_history"].
Less common unit and dtype arguments:
energy_units_to_eVlength_units_to_Adefault_dtype
Leave these at their defaults unless the saved model uses units or precision that differ from the normal ASE-facing workflow.
SCF Options
The calculator accepts these scf_options keys:
scf_options={
"num_scf_steps": 100,
"scf_tolerance": 1.0e-5,
"mixing_parameter": 0.2,
"constant_charge": True,
"use_autograd_forces": True,
}
These are runtime options only. Architecture hyperparameters such as field feature widths, update blocks, density smearing widths, and nonlocal energy readout settings are already stored in the saved model and are not passed to the calculator.
You do not need to include initial_density or initial_fermi_level in calculator
scf_options. The calculator uses the model’s local density guess for the initial multipoles. For the Fermi-level, the calculator reads the Fermi-level from
the configured fermi_level_key. In constant charge simualtions this is the initial Fermi-level, and in constant chemical potential mode this is the fixed Fermi-level.
Input Keys
The calculator maps fields from atoms.info and atoms.arrays into the model
input batch. The default key names are:
total_charge_key = "total_charge"
external_field_key = "external_field"
fermi_level_key = "initial_fermi_level"
atomic_multipoles_key = "initial_density_coefficients"
You only need to pass these key arguments when your Atoms objects use
different names.
For example, if your input file stores the applied field as
atoms.info["homogeneous_field"], pass:
calc = MACEFixedPointSCF(
model_path="fit.model",
device="cuda",
external_field_key="homogeneous_field",
)
The meaning of the fields is:
total_charge_keyused in constant-charge mode. If the field is absent, the target charge defaults to0.0;external_field_keyapplied homogeneous field. If absent, the field defaults to zero;fermi_level_keyFermi-level input. In constant-Fermi mode this is the controlled Fermi level. In constant-charge mode it is the initial Fermi-level guess. If absent, it defaults to zero;atomic_multipoles_keymaps an optional atom array intodensity_coefficients. The standard calculator does not require this for normal energy and force calculations because it starts from the model’s local density guess. In the current calculator API, this is not the usual way to set the SCF initial density.
Arguments You Usually Do Not Need
For ordinary ASE use, do not pass:
atomic_multipoles_keyunless your workflow deliberately stores multipoles in the input file;external_field_keyif there is no applied field or the default key name is already correct;fermi_level_keyif a zero Fermi-level input is acceptable or the default key name is already correct;total_charge_keyif the default key name is already correct. For neutral calculations, you usually do not need to puttotal_chargeinatoms.infoat all;
Constant Charge And Constant Fermi Level
For constant-charge calculations:
atoms.info["total_charge"] = 0.0
calc = MACEFixedPointSCF(
model_path="fit.model",
device="cuda",
scf_options={
"constant_charge": True,
"num_scf_steps": 100,
"scf_tolerance": 1.0e-6,
"mixing_parameter": 0.2,
"use_autograd_forces": True,
},
)
For constant-Fermi calculations:
atoms.info["initial_fermi_level"] = -4.8
calc = MACEFixedPointSCF(
model_path="fit.model",
fermi_level_key="initial_fermi_level",
device="cuda",
scf_options={
"constant_charge": False,
"num_scf_steps": 100,
"scf_tolerance": 1.0e-6,
"mixing_parameter": 0.2,
"use_autograd_forces": True,
},
)
In constant-charge mode, fermi_level_key supplies an initial guess. In
constant-Fermi mode, it supplies the fixed Fermi level.
Results
After a calculation, calc.results includes:
energyfree_energyforcesdensity_coefficientsdipolefermi_levelexternal_fieldelectrostatic_energyelectron_energyconvergence_historynum_scf_stepselectrostatic_featureselectrostatic_potentials, if the model returns themfull_scf_history, ifsave_full_scf_history=True
The most useful diagnostic is usually:
calc.results["convergence_history"]
It records the mean absolute density change between SCF steps. Inspect this when a calculation is slow, oscillatory, or non-converged.
Developer Restart Options
The calculator has restart hooks:
scf_restartrestart_densityrestart_fermi_level
These reuse state from the previous call to the same calculator object. They are currently developer-facing options and are not recommended as the default user workflow. Validate a model without restarts before relying on restarted calculations.