ASE Calculator for AMS
**********************


Introduction
============

The "AMSCalculator" class is an ASE Calculator that lets you use any
AMS engine (ADF, BAND, DFTB, ReaxFF, MLPotential, ForceField, ...)
together with ASE.

See also:

  **Example**: ASE calculator

  **Engine ASE**: Couple external ASE calculators to the AMS Driver


AMS settings
============

A "Settings" object is used to set up the AMS settings in the same way
as for normal PLAMS jobs.

See also: Preparing input for AMS jobs in PLAMS


ASE results
-----------

Currently only the energy, forces and stress tensor are provided
through the ASE interface. All other results can be accessed through
"AMSCalculator.ams_results", which is an "AMSResults" object. Use
"AMSCalculator.ensure_property('forces')" and
"AMSCalculator.ensure_property('stress')" to ensure these ASE
properties are computed regardless of whether it was originally
requested in the "Settings" object.


Charge
------

There is currently no universal interface in ASE for the total charge
of a system and is instead considered to be calculator-specific. The
easiest way to set the charge of a calculation with the
"AMSCalculator" is to define "Atoms.info['charge']". Additionally,
when the charge needs to be treated extensively w.r.t. manipulations
of the "Atoms" object in ASE, the initial charge of each atom can also
be set. The total charge is thus obtained as
"sum(Atoms.get_initial_charges())+Atoms.info['charge']". See the ASE
documentation for details on initial charges and info.

See also: **Example**: Charged AMS calculator


AMS standalone and worker mode
==============================

AMS can run in two modes: standalone and worker.

In **standalone mode** ("amsworker=False"), AMS is started for every
new structure, and stores the normal AMS output. Use this mode if:

* you need to access all results, *or*

* you run a calculation not supported by the AMSworker (e.g., a
  PESScan)

In **AMSworker mode** ("amsworker=True"), AMS is only started once.
This significantly reduces overhead, especially for fast engines like
ReaxFF. The downside is that you cannot access all results. Use this
mode if:

* you only need access to energy, forces, and stress tensor, *and*

* you only need to run single point calculations, for example to use
  the "ase.optimize.BFGS" geometry optimizer.

Technical:

  In **AMSworker mode**,  make sure to use "AMSCalculator" as a
  context manager, or explicitly call "AMSCalculator.stop_worker()"
  when you want to terminate the AMS process.


Technical
=========

Technical:

  When creating a deep copy of "AMSCalculator" the "AMSWorker" is not
  copied and instead every copy of "AMSCalculator" has a reference to
  the same "AMSWorker".


AMSCalculator API
=================

class AMSCalculator(settings=None, name='', amsworker=False, restart=True, molecule=None, extractors=[])

   ASE Calculator which can run any AMS engine (ADF, BAND, DFTB,
   ReaxFF, MLPotential, ForceField, ...).

   The settings are specified with a PLAMS "Settings" object in the
   same way as when running AMS through PLAMS.

   Parameters:

   settings : Settings
      A Settings object representing the input for an AMSJob or
      AMSWorker. This also determines which *implemented_properties*
      are available: *settings.input.ams.properties.gradients*:
      *force* *settings.input.ams.properties.stresstensor*: *stress*

   name : str, optional
      Name of the rundir of calculations done by this calculator. A
      counter is appended to the name for every calculation.

   amsworker : bool , optional
      If True, use the AMSWorker to set up an interactive session. The
      AMSWorker will spawn a separate process (an amsdriver). In order
      to make sure this process is closed, either use AMSCalculator as
      a context manager or ensure that AMSCalculator.stop_worker() is
      called before python is finished:

         with AMSCalculator(settings=settings, amsworker=True) as calc:
             atoms.calc = calc
             print(atoms.get_potential_energy())

      If False, use AMSJob to set up an io session (a normal AMS
      calculation storing all output on disk).

   restart : bool , optional
      Allow the engine to restart based on previous calculations.

   molecule : Molecule , optional
      A Molecule object for which the calculation has to be performed.
      If settings.input.ams.system is defined it overrides the
      molecule argument. If AMSCalculator.calculate(atoms = atoms) is
      called with an atoms argument it overrides any earlier
      definition of the system and remembers it.

   extractors: List[BasePropertyExtractor] , optional
      Define extractors for additional properties.

   Examples:

   Parameters:
      * **settings** (*Settings** | **None*) --

      * **name** (*str*) --

      * **amsworker** (*bool*) --

      * **restart** (*bool*) --

      * **molecule** (*Molecule** | **None*) --

      * **extractors** (*List**[**BasePropertyExtractor**]*) --

   Return type:
      *TSelf* | AMSPipeCalculator | AMSJobCalculator

   static __new__(cls, settings=None, name='', amsworker=False, restart=True, molecule=None, extractors=[])

      Dispatch object creation to AMSPipeCalculator or
      AMSJobCalculator depending on "AMSWorker"

      Parameters:
         * **cls** (*Type**[**TSelf**]*) --

         * **settings** (*Settings** | **None*) --

         * **name** (*str*) --

         * **amsworker** (*bool*) --

         * **restart** (*bool*) --

         * **molecule** (*Molecule** | **None*) --

         * **extractors** (*List**[**BasePropertyExtractor**]*) --

      Return type:
         *TSelf* | AMSPipeCalculator | AMSJobCalculator

   property implemented_properties: List[str]

      Returns the list of properties that this calculator has
      implemented

   calculate(atoms=None, properties=['energy'], system_changes=['positions', 'numbers', 'cell', 'pbc', 'initial_charges', 'initial_magmoms'])

      Calculate the requested properties. If atoms is not set, it will
      reuse the last known Atoms object.

      Parameters:
         * **atoms** (*Atoms** | **None*) --

         * **properties** (*List**[**str**]*) --

         * **system_changes** (*List**[**str**]*) --

      Return type:
         None

   ensure_property(properties)

      A list of ASE properties that the calculator will ensure are
      available from AMS or it gives an error.

      Parameters:
         **properties** (*str** | **List**[**str**]*) --

      Return type:
         None

   stop_worker()

      Stops the amsworker if it exists

      Return type:
         *Tuple*[*List*[str] | None, *List*[str] | None]

   clean_exit()

      Function called by ASEPipeWorker to tell the Calculator to stop
      and clean up

      Return type:
         None
