Monte Carlo Evaluator

For standard Monte Carlo (MC) runs using the standard clease.calculator.clease.Clease cluster expansion (CE) calculator, this is generally not required. However, it is possible to use the clease.montecarlo.montecarlo.Montecarlo class without the CLEASE calculator, and use a different calculator instead.

In general, if the atoms object has a generic calculator attached, which is not a CLEASE calculator, it will assume it is an ASE calcualtor, and simply use the get_potential_energy method of the calculator object. This will also cause a complete re-evaluation of the entire system whenever a change is proposed in the MC algorithm, which may or may not be desired. The specifics of how to deal with local changes in the energy evaluation is up to the individual cases, but let’s take a look at how to use the ASE EMT calculator with the MC class, using the MCEvaluator class.

An Example

Let’s assume we have a system comprised of Au, Cu and vacancies (in ASE denoted as X). The EMT calculator is unable to evaluate an atom which is X, however we need to keep track of them anyway in the Monte Carlo run. We can then create a new MC evaluator, which changes the rules for how we get the energy, by removing vacancies from the atoms object prior to evaluating the energy.

>>> from clease.montecarlo import MCEvaluator
>>> from ase.calculators.emt import EMT
>>> class MyEvaluator(MCEvaluator):
...     def __init__(self, atoms):
...         super().__init__(atoms)
...         # Have a pre-made calculator instance ready
...         self.calc = EMT()
...     def get_energy(self, applied_changes = None) -> float:
...         # Make a copy of the atoms, and remove all vacancies.
...         atoms_cpy = self.atoms.copy()
...         mask = [atom.index for atom in atoms_cpy if atom.symbol != 'X']
...         atoms_cpy = atoms_cpy[mask]
...
...         atoms_cpy.calc = self.calc
...         return atoms_cpy.get_potential_energy()

Note that we overwrite the get_energy method of the MCEvaluator, in order to have custom rules for the energy evaluation. Let’s create an example system to run the MC on:

>>> from ase.build import bulk
>>> atoms = bulk('Au') * (5, 5, 5)
>>> atoms.symbols[:10] = 'Cu'
>>> atoms.symbols[10:20] = 'X'
>>> print(atoms.symbols)
Cu10X10Au105

We can now run our Monte Carlo:

>>> from clease.montecarlo import Montecarlo
>>> temp = 300  # 300 kelvin
>>> evaluator = MyEvaluator(atoms)
>>> mc = Montecarlo(evaluator, temp)
>>> mc.run(steps=10)

Which successfully now runs our MC simulation on an atoms object using custom energy evaluation rules. You can write your own custom evaluators to do more complex things, such as utilizing the applied_changes keyword, to make energy evaluations only consider local changes to the atoms object.

The API

class clease.montecarlo.mc_evaluator.MCEvaluator(atoms: Atoms)[source]

A Montecarlo evaluator class, used to perform the energy evaluations within a Montecarlo run.

Parameters:

atoms (ase.Atoms) – ASE Atoms object to be used for the evaluation. This atoms object may be mutated.

apply_system_changes(system_changes: Sequence[SystemChange], keep=False) None[source]

Mutate the atoms object to reflect the system change.

Parameters:
  • system_changes (SystemChanges) – Sequence of changes to be applied.

  • keep (bool, optional) – Whether to call keep_system_changes() after applying changes. Defaults to False.

get_energy(applied_changes: Sequence[SystemChange] | None = None) float[source]

Evaluate the energy of a system. If a change is sufficiently local/small, it there, in some situations, may be other ways of evaluating the energy than a full calculation. Must return the energy of the new configuration.

The applied changes only reflect what has already been applied to the system.

Parameters:

applied_changes (SystemChanges, optional) – A list of changes which has been applied to the atoms object. This change has already been applied, and is only for bookkeeping purposes, if evaluation schemas want to make decisions based on what has changed. Defaults to None.

Returns:

Energy of the atoms object.

Return type:

float

get_energy_given_change(system_changes: Sequence[SystemChange]) float[source]

Calculate the energy of a set of changes, and undo any changes.

Parameters:
  • atoms (Atoms) – Atoms object to be mutated.

  • system_changes (SystemChanges) – Sequence of changes to be applied.

Returns:

The resulting energy from a call to get_energy().

Return type:

float

keep_system_changes(system_changes: Sequence[SystemChange] | None = None) None[source]

A set of system changes are to be kept. Perform necessary actions to prepare for a new evaluation.

reset() None[source]

Perform a reset on the evaluator and/or on the atoms

synchronize() None[source]

Ensure the calculator and atoms objects are synchronized.

undo_system_changes(system_changes: Sequence[SystemChange]) None[source]

Mutate the atoms object to undo the system change.

Parameters:
  • atoms (Atoms) – Atoms object to be mutated.

  • system_changes (SystemChanges) – Sequence of changes to be applied.