RASPA
*****

(*contributed by* Patrick Melix)

The runscript written by PLAMS expects the environment variable
*$RASPA_DIR* to be set. It should point to the location where RASPA is
installed (*$RASPA_DIR/bin/simulate* being the compiled executable).


Input
=====

The RASPA input is not easily wrapped into a "Settings" class because
it does not know section endings and sections don't have a common
open/close statement. Like the other interfaces, the RASPA input file
is generated using the "input" branch of the job settings. An example
is given here:

   settings = Settings()
   settings.input.simulationtype = 'MonteCarlo'
   settings.input.numberofcycles = 100
   settings.input.printevery = 10
   settings.input.forcefield = 'GenericMOFs'
   settings.input.usechargesfromciffile = True
   settings.input.framework._h = 0
   settings.input.framework.frameworkname = 'someMOF'
   settings.input.framework.unitcells = '4 4 4'
   settings.input.externaltemperature = 298.0
   settings.input.component['0'] = Settings()
   settings.input.component['0'].moleculename = 'helium'
   settings.input.component['0'].moleculedefinition = 'TraPPE'
   settings.input.component['0'].widomprobability = 1.0
   settings.input.component['0'].createnumberofmolecules = 0
   settings.input.component._1 = Settings()
   settings.input.component._1.moleculename = 'methane'
   settings.input.component._1.moleculedefinition = 'TraPPE'
   settings.input.component._1.widomprobability = 1.0
   settings.input.component._1.createnumberofmolecules = 0

The input generated during the execution of the RASPA job is similar
to:

   numberofcycles 100
   printevery 10
   simulationtype MonteCarlo
   usechargesfromciffile yes

   componentexternaltemperature 298.0
   forcefield GenericMOFs
   framework 0
     frameworkname someMOF
     unitcells 4 4 4

   component 0 MoleculeName helium
     createnumberofmolecules 0
     moleculedefinition TraPPE
     widomprobability 1.0

   component 1 MoleculeName methane
     createnumberofmolecules 0
     moleculedefinition TraPPE
     widomprobability 1.0

The *Component* sections differ from the standard behavior and are
printed by the input parser as shown in this example. They can be
inserted using the dictionary-like or dot-like notation as shown
above. The "MoleculeName" key is obligatory.

As in other interfaces, the "_h" key results in the value being
printed along the section title. No other special sections are
defined.

If you need some files to be copied to the actual execution directory,
pass them to the constructor using the "copy=" option. Alternatively
you can symlink them using the "symlink=" option. See the API below.


Molecule parsing
================

Molecule handling is not supported yet. Prepare the needed files and
pass them to the constructor using the "copy" or "symlink" option.

For a more detailed description of the *RASPA* input see the
documentation in the RASPA GitHub repository.


Loading jobs
============

Calculations done without PLAMS can be loaded using the
"load_external()" functionality. The "RaspaResults" class **does not**
support reading input files into "Settings" objects yet.

Just do "RaspaJob.load_external(path)" to use the job inside PLAMS.


API
===

class RaspaJob(copy=None, symlink=None, **kwargs)

   A single job with RASPA2 class.

   Requires the ASE Python package.

   Files that should be copied to the job directory can be passed as a
   dictionary using the "copy" argument. The dict should have the
   following layout: *dict[<filename in jobdir>] = <path to file>*. If
   you prefer symlinks instead of copies use the "symlink" argument
   with the same layout. The path strings given to symlink are not
   altered. Remember that the job directory is not equal to the
   current work directory if using relative symlinks.

   **Molecule parsing is not yet supported!**

   The environment variable "$RASPA_DIR" needs to be set for the
   runscript to work.

   _result_type

      alias of "RaspaResults"

   __init__(copy=None, symlink=None, **kwargs)

   _get_ready()

      Copy files to execution dir if self.copy_files is set.

   get_input()

      Transform all contents of "settings.input" branch into string
      with blocks, keys and values.

      RASPA2 does not interpret indentation but rather certain keys
      automatically start a subsection. Subsections are never closed
      but *automatically* ended if the next key-value pair does not
      fit into it. So here we only need to care about readability of
      the input file. The logic is automatically preserved by using
      the nested PLAMS "settings" logic.

      Components should be built using either "component['INT'] =
      Settings()" or "component._INT = Settings()". It needs to have a
      key "moleculename" (case insensitive).

   get_runscript()

      $RASPA_DIR has to be set in the environment!

   check()

      Look for the normal termination signal in output.

class RaspaResults(job)

   A Class for handling RASPA Results.

   Note that the Output file is guessed in "self.collect". Do not rely
   on it to point to the file you need and but check
   "self._filenames['out']"!

   Parameters:
      **job** (*Job*) --

   collect()

      Try to Guess the Main Output File.

      Set it to whatever comes first in the 'Output/System_0' folder.

   get_block_value(search, file=None, get_std=False, get_unit=False)

      Return a Block Value from Output File.

      Can be used to retrieve block values from the final section of
      the output files. Uses *Results.grep_file* to retrieve the
      values. Remember to escape special *grep* characters in the
      search string. Returns the average value over all blocks.

      search: string String labeling the value you desire.

      file: string Defaults to the automatically detected output file.
      See *self.collect()*.

      get_std: boolean Also return the standard deviation of the value

      get_unit: boolean Also return the unit of the value

   get_value(search, file=None, get_std=False, get_unit=False)

      Return a Single Value from Output File.

      Can be used to retrieve single values from the final section of
      the output files. Uses *Results.grep_file* to retrieve the
      values. Remember to escape special *grep* characters in the
      search string.

      search: string String labeling the value you desire.

      file: string Defaults to the automatically detected output file.
      See *self.collect()*.

      get_std: boolean Also return the standard deviation of the value

      get_unit: boolean Also return the unit of the value

   get_from_all_files(*args, output_folder='Output/System_0/', method='get_value', **kwargs)

      Wrapper to Execute Methods on all Output files.

      output_folder: string The subfolder containing the relevant
      output files. Default should be fine.

      method: function The function to call, needs to be a function of
      the "RaspaResults" class that takes a *file* argument. All
      *args* and *kwargs* are passed on.

      If the *method* returns tuples, the tuples are unpacked and
      added to lists.

   get_isotherm(output_folder='Output/System_0/', search_x='Partial pressure:', search_y='Average loading excess \\[cm^3 (STP)/gr', get_std=False, get_unit=False)

      Try to automatically collect Isotherm Data.

      output_folder: string The subfolder containing the relevant
      output files. Default should be fine.

      search_x: string String labeling the desired x-Axis values in
      the output.

      search_y: string String labeling the desired y-Axis values in
      the output.

      get_std: boolean Return the standard deviation of the y values
      as a list.

      get_unit: boolean Return the units of the values as strings
      *x_unit*, *y_unit*.

      Returns two lists: *x_values*, *y_values*. Optionally after that
      *x_std*, *x_unit*, *y_unit*.
