import datetime
import os
from warnings import warn
import mbuild.formats.charmm_writer as mf_charmm
def dict_keys_to_list(dict):
"""
Converts the dictionary keys into a list
Parameters
----------
dict : dict
A provided dictionary
Returns
---------
list : list
list of keys from the provided dictionary
"""
return [key for key in dict.keys()]
def print_valid_required_input_variables(description=False):
"""
Prints the valid required input, which is necessary to write the GOMC control file.
Parameters
----------
description : bool, default = False
If True, it prints the descriptions of the input_variables (i.e. dict),
If False, it only prints the input_variables without the descriptions (i.e. list)
Returns
---------
Prints out the valid input variables (user optional) on the screen,
which can be entered in the GOMC writer. These are the valid input
variables for all ensembles.
"""
valid_args = _get_all_possible_input_variables(description=description)
for arg, description in valid_args.items():
print("{:10s}: {}".format(arg, description))
def _get_required_data(description=False):
"""
Provides a list of the required inputs for all possible ensembles.
Parameters
----------
description : bool, default = False.
If True, it prints the descriptions of the input_variables (i.e. dict),
If False, it only prints the input_variables without the descriptions (i.e. list)
Returns
---------
required_data : dict or list, default = list.
If the description = True then a dict is provided with the key and value.
if the description = False then a list of the dict keys is provided.
Note:
Variables and text extracted with permission from the GOMC manual version 2.60.
Some of the text was modified from its original version.
Cite: Potoff, Jeffrey; Schwiebert, Loren; et al. GOMC Documentation.
https://raw.githubusercontent.com/GOMC-WSU/GOMC/master/GOMC_Manual.pdf, 2021.
"""
required_data = {
"charmm_object": "Charmm object, "
"A Charmm object, which by definition has been parameterized "
"from the selected force field.",
"ensemble_type": "Required files or System Info (all ensembles): str, "
"(valid strings are 'NVT', 'NPT', 'GEMC_NPT', 'GCMC-NVT', or 'GCMC'), "
"the ensemble type for the simulation.",
"RunSteps": "Required files or System Info (all ensembles): int (> 0), "
"The number or run steps for the simulation.",
"Temperature": "Required files or System Info (all ensembles): float or integer (> 0), "
"Temperature of system in Kelvin (K)",
"ff_psf_pdb_file_directory": "str (optional), default=None (i.e., the current directory). "
"The full or relative directory added to the force field, psf, and pdb "
"file names, created via the Charmm object.",
"check_input_files_exist": "Required to check if files exist (all ensembles): bool (default=True), "
"Check if the force field, psf, and pdb files exist. "
"If the files are checked and do not exist, the writer will throw "
"a ValueError. "
"True, check if the force field, psf, and pdb files exist. "
"False, do not check if the force field, psf, and pdb files exist.",
"Restart": "Required for restarting (all ensembles): boolean (default=False), "
"Determines whether to restart the simulation "
"from restart file (*_restart.pdb and *_restart.psf) or not.",
"RestartCheckpoint": "Required for optimal restarting (all ensembles): boolean (default=False),"
"Determines whether to restart the simulation with the "
"checkpoint file (checkpoint.dat) or not. Restarting the "
"simulation with checkpoint.dat would result in an identical outcome, "
"as if previous simulation was continued.",
"Parameters": "Required for alternate force field file (all ensembles): "
"str, (default=None), "
"Override all other force field directory and filename input with the correct extension (.inp or .par). "
"Note: the default directory is the current directory with the Charmm object file name.",
"Coordinates_box_0": "Required for alternate box 0 .pdb file (all ensembles): "
"str, (default=None), "
"Override all other box 0 pdb directory and filename inputs. "
"Note: the default directory is the current directory with the Charmm object file name.",
"Structure_box_0": "Required for alternate box 0 .psf file (all ensembles): "
"str, (default=None), "
"Override all other box 0 psf directory and filename inputs. "
"Note: the default directory is the current directory with the Charmm object file name.",
"Coordinates_box_1": "Required for alternate box 1 .pdb file (all ensembles): "
"str, (default=None), "
"Override all other box 1 pdb directory and filename inputs. "
"Note: the default directory is the current directory with the Charmm object file name.",
"Structure_box_1": "Required for alternate box 1 .psf file (all ensembles): "
"str, (default=None), "
"Override all other box 1 psf directory and filename inputs. "
"Note: the default directory is the current directory with the Charmm object file name.",
"binCoordinates_box_0": "Required for alternate box 0 .coor file (all ensembles): "
"str, (default=None), "
"The box 0 binary coordinate file is used only for restarting "
"a GOMC simulation, which provides increased numerical accuracy.",
"extendedSystem_box_0": "Required for alternate box 0 .xsc file (all ensembles): "
"str, (default=None), "
"The box 0 vectors and origin file is used only for restarting a "
"GOMC simulation. ",
"binVelocities_box_0": "Required for alternate box 0 .vel file (all ensembles): "
"str, (default=None), "
"The box 0 binary velocity file is used only for "
"restarting a GOMC simulation, which provides increased "
"numerical accuracy. These velocities are only passed thru "
"GOMC since Monte Carlo simulations do not utilize any "
"velocity information. ",
"binCoordinates_box_1": "Required for alternate box 1 .coor file (all ensembles): "
"str, (default=None), "
"The box 1 binary coordinate file is used only for restarting a "
"GOMC simulation, which provides increased numerical accuracy. ",
"extendedSystem_box_1": "Required for alternate box 1 .coor file (all ensembles): "
"str, (default=None), "
"The box 1 vectors and origin file is used "
"only for restarting a GOMC simulation. ",
"binVelocities_box_1": "Required for alternate box 1 .vel file (all ensembles): "
"str, (default=None), "
"The box 1 binary velocity file is used only for restarting a "
"GOMC simulation, which provides increased numerical accuracy. "
"These velocities are only passed thru GOMC since Monte Carlo "
"simulations do not utilize any velocity information.",
}
if description:
return required_data
else:
return list(required_data.keys())
def _get_all_possible_input_variables(description=False):
"""
Provides a list of the variables inputs (user optional) for all possible ensembles.
Parameters
----------
description : bool, default = False.
If True, it prints the descriptions of the input_variables (i.e. dict),
If False, it only prints the input_variables without the descriptions (i.e. list)
Returns
---------
valid_input_variables : dict or list, default = list.
If the description = True then a dict is provided with the key and value.
if the description = False then a list of the dict keys is provided.
Note:
Variables and text extracted with permission from the GOMC manual version 2.60.
Some of the text was modified from its original version.
Cite: Potoff, Jeffrey; Schwiebert, Loren; et. al. GOMC Documentation.
https://raw.githubusercontent.com/GOMC-WSU/GOMC/master/GOMC_Manual.pdf, 2021.
"""
valid_input_variables = {
# ******************************************************************************************************
# Definitions in this function are copied to a large extent from the GOMC manual release version 2.60 (start)
# insert citation here:
# ******************************************************************************************************
"PRNG": 'Simulation info (all ensembles): string or int (>= 0) ("RANDOM" or integer), default = {}. '
"PRNG = Pseudo-Random Number Generator (PRNG). "
'There are two (2) options, entering the string, "RANDOM", or a integer. \n'
'\t\t\t\t\t\t\t\t\t\t\t\t\t --- "RANDOM", which selects a random seed number. '
'This will enter the line "PRNG RANDOM" in the gomc configuration file. \n'
"\t\t\t\t\t\t\t\t\t\t\t\t\t --- integer, which defines the integer seed number "
"for the simulation. "
"This is equivalent to entering the following two lines in the configuration file: "
"line 1 = PRNG INTSEED, "
"line 2 = Random_Seed user_selected_integer. "
'Example 1: for a random seed enter the string "RANDOM. '
"Example 2: for a specific seed number enter a integer of your choosing. "
"".format(_get_default_variables_dict()["PRNG"]),
"ParaTypeCHARMM": "Simulation info (all ensembles): boolean, default = {}. "
"True if a CHARMM forcefield, False otherwise."
"".format(_get_default_variables_dict()["ParaTypeCHARMM"]),
"ParaTypeMie": "Simulation info (all ensembles): boolean, default = {}. "
"True if a Mie forcefield type, False otherwise."
"".format(_get_default_variables_dict()["ParaTypeMie"]),
"ParaTypeMARTINI": "Simulation info (all ensembles): boolean, default = {}. "
"True if a MARTINI forcefield, False otherwise."
"".format(_get_default_variables_dict()["ParaTypeMARTINI"]),
"RcutCoulomb_box_0": "Simulation info (all ensembles): int or float (>= 0), default = {}."
"Sets a specific radius in box 0 where the short-range "
"electrostatic energy will be calculated (i.e., The distance to truncate the "
"Note: if None, GOMC will default to the Rcut value"
"".format(_get_default_variables_dict()["RcutCoulomb_box_0"]),
"RcutCoulomb_box_1": "Simulation info (all ensembles): int or float (>= 0), default = {}."
"Sets a specific radius in box 1 where the short-range "
"electrostatic energy will be calculated. (i.e., The distance to truncate the "
"short-range electrostatic energy in box 1.)"
"Note: if None, GOMC will default to the Rcut value"
"".format(_get_default_variables_dict()["RcutCoulomb_box_1"]),
"Pressure": "Simulation info (only GEMC_NPT and NPT): int or float (>= 0), default = {}. "
"The pressure in bar utilized for the NPT "
"and GEMC_NPT simulations."
"".format(_get_default_variables_dict()["Pressure"]),
"Rcut": "Simulation info (all ensembles): int or float (>= 0 and RcutLow < Rswitch < Rcut), default = {}. "
"Sets a specific radius in Angstroms that non-bonded interaction "
"energy and force will be considered and calculated using defined potential function. "
"The distance in Angstoms to truncate the LJ, Mie, or other VDW type potential at. "
'Note: Rswitch is only used when the "Potential" = SWITCH. '
"".format(_get_default_variables_dict()["Rcut"]),
"RcutLow": "Simulation info (all ensembles): int or float (>= 0 and RcutLow < Rswitch < Rcut), default = {}. "
"Sets a specific minimum possible distance in Angstroms that reject "
"any move that places any atom closer than specified distance. The minimum possible "
"distance between any atoms. "
"Sets a specific radius in Angstroms that non-bonded interaction "
'Note: Rswitch is only used when the "Potential" = SWITCH. '
"WARNING: When using a molecule that has charge atoms with non-bonded epsilon values of zero (i.e., water), "
"the RcutLow need to be greater than zero, typically 1 angstrom. "
"WARNING: When using the free energy calculations, RcutLow needs to be set to zero (RcutLow=0);"
"otherwise, the free energy calculations can produce results that are slightly off or wrong. "
"".format(_get_default_variables_dict()["RcutLow"]),
"LRC": "Simulation info (all ensembles): boolean, default = {}. "
"If True, the simulation considers the long range tail corrections for the non-bonded VDW or "
"dispersion interactions. "
"Note: In case of using SHIFT or SWITCH potential functions, LRC will be ignored."
"".format(_get_default_variables_dict()["LRC"]),
"IPC": "Simulation info (all ensembles): boolean, default = {}. "
"If True, the simulation adds the impulse correction term to the pressure, "
"which considers to correct for the discontinuous Rcut potential "
"(i.e., a hard cutoff potential, meaning a potential without tail corrections) "
"the long range tail corrections for the non-bonded VDW or dispersion interactions. "
"If False, the impulse correction term to the pressure is not applied. "
"Note: This can not be used if LRC is True or the Potential is set to SWITCH, or SHIFT."
"".format(_get_default_variables_dict()["IPC"]),
"Exclude": "Simulation info (all ensembles): str "
'(The string inputs are "1-2", "1-3", or "1-4"), default = {}. '
"Note: In CHARMM force field, the 1-4 interaction needs to be considered. "
'Choosing "Excude 1-3", will modify 1-4 interaction based on 1-4 parameters '
"in parameter file. If a kind force field is used, where "
'1-4 interaction needs to be ignored, such as TraPPE, either Exlcude "1-4" needs to be '
"chosen or 1-4 parameter needs to be assigned to zero in the parameter file. \n"
'\t\t\t\t\t\t\t\t\t\t\t\t\t --- "1-2": All interaction pairs of bonded atoms, '
"except the ones that separated with one bond, "
"will be considered and modified using 1-4 parameters defined in parameter file. \n"
'\t\t\t\t\t\t\t\t\t\t\t\t\t --- "1-3": All interaction pairs of bonded atoms, '
"except the ones that separated with one or two "
"bonds, will be considered and modified using 1-4 parameters defined in parameter file. \n"
'\t\t\t\t\t\t\t\t\t\t\t\t\t --- "1-4": All interaction pairs of bonded atoms, '
"except the ones that separated with one, "
"two or three bonds, will be considered using non-bonded parameters defined in parameter file."
"".format(_get_default_variables_dict()["Exclude"]),
"Potential": 'Simulation info (all ensembles): str, ["VDW", "EXP6", "SHIFT" or "SWITCH"], default = {}. '
"Defines the potential function type to calculate non-bonded dispersion interaction "
"energy and force between atoms. \n"
'\t\t\t\t\t\t\t\t\t\t\t\t\t --- "VDW": Non-bonded dispersion interaction energy and force '
"calculated based on n-6 (Lennard - Jones) equation. This function will be discussed "
"further in the Intermolecular energy and "
"Virial calculation section. \n"
'\t\t\t\t\t\t\t\t\t\t\t\t\t --- "EXP6": Non-bonded dispersion interaction energy and force '
"calculated based on exp-6 (Buckingham potential) equation. \n"
'\t\t\t\t\t\t\t\t\t\t\t\t\t --- "SHIFT": This option forces the potential energy to be '
"zero at Rcut distance. \n"
'\t\t\t\t\t\t\t\t\t\t\t\t\t --- "SWITCH": This option smoothly forces the potential '
"energy to be zero at Rcut distance and starts modifying the potential at Rswitch "
"distance. Depending on force field type, specific potential function will be applied. "
"".format(_get_default_variables_dict()["Potential"]),
"Rswitch": "Simulation info (all ensembles): int or float (>= 0 and RcutLow < Rswitch < Rcut), default = {}. "
'Note: Rswitch is only used when the SWITCH function is used (i.e., "Potential" = SWITCH). '
"The Rswitch distance is in Angstrom. If the “SWITCH” function is chosen, "
"Rswitch needs to be defined, otherwise, the program will be terminated. When using "
'choosing "SWITCH" as potential function, the Rswitch distance defines where the'
"non-bonded interaction energy modification is started, which is eventually truncated "
"smoothly at Rcut distance."
"".format(_get_default_variables_dict()["Rswitch"]),
"ElectroStatic": "Simulation info (all ensembles): boolean, default = {}. "
"Considers the coulomb interactions or not. "
"If True, coulomb interactions are considered and false if not. "
"Note: To simulate the polar molecule in MARTINI force field, ElectroStatic needs to be "
"turn on. The MARTINI force field uses short-range coulomb interaction with constant "
"Dielectric of 15.0."
"".format(_get_default_variables_dict()["ElectroStatic"]),
"Ewald": "Simulation info (all ensembles): boolean, default = {}. "
"Considers the standard Ewald summation method for electrostatic calculations. "
"If True, Ewald summation calculation needs to be considered and false if not. "
"Note: By default, GOMC will set ElectroStatic to True if Ewald summation "
"method was used to calculate coulomb interaction."
"".format(_get_default_variables_dict()["Ewald"]),
"CachedFourier": "Simulation info (all ensembles): boolean, default = {}. "
"Considers storing the reciprocal terms for Ewald summation "
"calculation in order to improve the code performance. This option would increase the code "
"performance with the cost of memory usage. If True, to store reciprocal terms of Ewald "
"summation calculation and False if not. "
"Warning: Monte Carlo moves, such as MEMC-1, MEMC-2, MEMC-3, "
"IntraMEMC-1, IntraMEMC-2, and IntraMEMC-3 are not support with CachedFourier."
"".format(_get_default_variables_dict()["CachedFourier"]),
"Tolerance": "Simulation info (all ensembles): float (0.0 < float < 1.0), default = {}. "
"Sets the accuracy in Ewald summation calculation. Ewald separation parameter and number "
"of reciprocal vectors for the Ewald summation are determined based on the accuracy parameter."
"".format(_get_default_variables_dict()["Tolerance"]),
"Dielectric": "Simulation info (all ensembles): int or float (>= 0.0), default = {}. "
"Sets dielectric value used in coulomb interaction when the Martini "
"force field is used. Note: In MARTINI force field, Dielectric needs to be set to 15.0."
"".format(_get_default_variables_dict()["Dielectric"]),
"PressureCalc": "Simulation info (all ensembles): list [bool , int (> 0)] or [bool , step_frequency], "
"default = {} or [{} , set via formula based on the number of RunSteps or {} max]. "
"Calculate the system pressure or not. bool = True, enables the pressure calculation "
"during the simulation, false disables the calculation. The int/step frequency sets the "
"frequency of calculating the pressure."
"".format(
_get_default_variables_dict()["PressureCalc"],
_get_default_variables_dict()["PressureCalc"][0],
_get_default_variables_dict()["PressureCalc"][1],
),
"EqSteps": "Simulation info (all ensembles): int (> 0), "
"default = set via formula based on the number of RunSteps or {} max. "
"Sets the number of steps necessary to equilibrate the system. "
"Averaging will begin at this step. "
"Note: In GCMC simulations, the Histogram files will be outputed at EqSteps."
"".format(_get_default_variables_dict()["EqSteps"]),
"AdjSteps": "Simulation info (all ensembles): int (> 0), "
"default = set via formula based on the number of RunSteps or {} max. "
"Sets the number of steps per adjustment of the parameter associated with each move "
"(e.g. maximum translate distance, maximum rotation, maximum volume exchange, etc.)."
"".format(_get_default_variables_dict()["AdjSteps"]),
"VDWGeometricSigma": "Simulation info (all ensembles): boolean, default = {}. "
"Use geometric mean, as required by OPLS force field, "
"to combining Lennard-Jones sigma parameters for different atom types. "
"If set to True, GOMC uses geometric mean to combine Lennard-Jones or VDW sigmas. "
"Note: The default setting of VDWGeometricSigma is false, which uses the arithmetic "
"mean when combining Lennard-Jones or VDW sigma parameters for different atom types."
"".format(_get_default_variables_dict()["VDWGeometricSigma"]),
"useConstantArea": "Simulation info (only GEMC_NPT and NPT): boolean: default = {}. "
"Changes the volume of the simulation box by fixing the cross-sectional "
"area (x-y plane). If true, the volume will change only in z axis, If False, "
"the volume of the box will change in a way to maintain the constant axis ratio. "
"".format(_get_default_variables_dict()["useConstantArea"]),
"FixVolBox0": "Simulation info (only GEMC_NPT): boolean, default = {}. "
"Changing the volume of fluid phase (Box 1) to maintain the constant imposed pressure and "
"Temperature, while keeping the volume of adsorbed phase (Box 0) fixed. Note: By default, "
"GOMC will set useConstantArea to False if no value was set. It means, the volume of the "
"box will change in a way to maintain the constant axis ratio."
"".format(_get_default_variables_dict()["FixVolBox0"]),
# GCMC only properties
"ChemPot": "Simulation info (only GCMC): dict {str (4 dig limit) , int or float}, "
+ "default = {} ".format(_get_default_variables_dict()["ChemPot"])
+ "(i.e., the user must set this variable as there is no working default)."
"The chemical potentials in GOMC units of energy, K. "
"There is a 4 character limit for the string/residue name since the PDB/PSF "
"files have a 4 character limitation and require and exact match in the conf file. "
"Note: These strings must match the residue in the psf and psb files or it will fail. "
"The name of the residues and their corresponding chemical potential must specified "
'for every residue in the system (i.e., {"residue_name" : chemical_potential}). '
"Note: IF 2 KEYS WITH THE SAME STRING/RESIDUE ARE PROVIDED, ONE WILL BE AUTOMATICALLY "
"OVERWRITTEN AND NO ERROR WILL BE THROWN IN THIS CONTROL FILE WRITER. "
'Example 1 (system with only water): {"H2O" : -4000} . '
'Example 2 (system with water and ethanol): {"H2O" : -4000, "ETH" : -8000} ',
"Fugacity": "Simulation info (only GCMC): dict {str , int or float (>= 0)}, "
+ "default = {} ".format(_get_default_variables_dict()["Fugacity"])
+ "(i.e., the user must set this variable as there is no working default). "
"The fugacity in GOMC units of pressure, bar. "
"There is a 4 character limit for the string/residue name since the PDB/PSF "
"files have a 4 character limitation and require and exact match in the conf file. "
"Note: These strings must match the residue in the psf and psb files or it will fail. "
"The name of the residues and their corresponding fugacity must specified "
'for every residue in the system (i.e., {"residue_name" : fugacity}). '
"Note: IF 2 KEYS WITH THE SAME STRING/RESIDUE ARE PROVIDED, ONE WILL BE AUTOMATICALLY "
"OVERWRITTEN AND NO ERROR WILL BE THROWN IN THIS CONTROL FILE WRITER. "
'Example 1 (system with only water): {"H2O" : 1} . '
'Example 2 (system with water and ethanol): {"H2O" : 0.5, "ETH" : 10} ',
# CBMC inputs
"CBMC_First": "CBMC inputs (all ensembles): int (>= 0), default = {}, "
"The number of CD-CBMC trials to choose the first atom position"
"(Lennard-Jones trials for first seed growth)."
"".format(_get_default_variables_dict()["CBMC_First"]),
"CBMC_Nth": "CBMC inputs (all ensembles): int (>= 0), default = {}, "
"The number of CD-CBMC trials to choose the later atom positions "
"(Lennard-Jones trials for first seed growth)."
"".format(_get_default_variables_dict()["CBMC_Nth"]),
"CBMC_Ang": "CBMC inputs (all ensembles): int (>= 0), default = {}, "
"The number of CD-CBMC bending angle trials to perform for geometry "
"(per the coupled-decoupled CBMC scheme)."
"".format(_get_default_variables_dict()["CBMC_Ang"]),
"CBMC_Dih": "CBMC inputs (all ensembles): int (>= 0), default = {}, "
"The number of CD-CBMC dihedral angle trials to perform for geometry "
"(per the coupled-decoupled CBMC scheme)."
"".format(_get_default_variables_dict()["CBMC_Dih"]),
# Control file (.conf file ) output controls/parameters
"OutputName": "Output Frequency (all ensembles): str (NO SPACES), default = {}. "
"The UNIQUE STRING NAME, WITH NO SPACES, which is used for the "
"output block average, PDB, and PSF file names."
"".format(_get_default_variables_dict()["OutputName"]),
"CoordinatesFreq": "PDB Output Frequency (all ensembles): list [bool , int (> 0)] or "
"[Generate_data_bool , steps_per_data_output_int], "
"default = {} or [{} , set via formula based on the number of RunSteps or {} max]. "
"Controls output of PDB file (coordinates). "
"If bool is True, this enables outputting the coordinate files at the "
"integer frequency (set steps_per_data_output_int), "
'while "False" disables outputting the coordinates.'
"".format(
_get_default_variables_dict()["CoordinatesFreq"],
_get_default_variables_dict()["CoordinatesFreq"][0],
_get_default_variables_dict()["CoordinatesFreq"][1],
),
"DCDFreq": "DCD Output Frequency (all ensembles): list [bool , int (> 0)] or "
"[Generate_data_bool , steps_per_data_output_int], "
"default = {} or [{} , set via formula based on the number of RunSteps or {} max]. "
"Controls output of DCD file (coordinates). "
"If bool is True, this enables outputting the coordinate files at the "
"integer frequency (set steps_per_data_output_int), "
'while "False" disables outputting the coordinates.'
"".format(
_get_default_variables_dict()["DCDFreq"],
_get_default_variables_dict()["DCDFreq"][0],
_get_default_variables_dict()["DCDFreq"][1],
),
"RestartFreq": "Output Frequency (all ensembles): list [bool , int (> 0)] or "
"[Generate_data_bool , steps_per_data_output_int], "
"default = {} or [{} , set via formula based on the number of RunSteps or {} max]. "
"This creates the PDB and PSF (coordinate and topology) files for restarting the system "
"at the set steps_per_data_output_int (frequency) "
"If bool is True, this enables outputting the PDB/PSF restart files at the "
"integer frequency (set steps_per_data_output_int), "
"while “false” disables outputting the PDB/PSF restart files. "
"".format(
_get_default_variables_dict()["RestartFreq"],
_get_default_variables_dict()["RestartFreq"][0],
_get_default_variables_dict()["RestartFreq"][1],
),
"CheckpointFreq": "Output Frequency (all ensembles): list [bool , int (> 0)] or "
"[Generate_data_bool , steps_per_data_output_int], "
"default = {} or [{} , set via formula based on the number of RunSteps or {} max]. "
"Controls the output of the last state of simulation at a specified step, in a "
"binary file format (checkpoint.dat). Checkpoint file contains the following "
"information in full precision: "
"(1) Last simulation step that saved into checkpoint file "
"(2) Simulation cell dimensions and angles "
"(3) Maximum amount of displacement (Å), rotation (δ), and volume (Å^3) that is used in "
"the Displacement, Rotation, MultiParticle, and Volume moves "
"(4) Number of Monte Carlo move trial and acceptance "
"(5) All molecule’s coordinates "
"(6) Random number sequence "
"If bool is True, this enables outputting the checkpoint file at the "
"integer frequency (set steps_per_data_output_int), "
'while "False" disables outputting the checkpoint file.'
"".format(
_get_default_variables_dict()["CheckpointFreq"],
_get_default_variables_dict()["CheckpointFreq"][0],
_get_default_variables_dict()["CheckpointFreq"][1],
),
"ConsoleFreq": "Output Frequency (all ensembles): list [bool , int (> 0)] or "
"[Generate_data_bool , steps_per_data_output_int], "
"default = {} or [{} , set via formula based on the number of RunSteps or {} max]. "
'Controls the output to the "console” or log file, which prints the '
"acceptance statistics, and run timing info. In addition, instantaneously-selected"
"thermodynamic properties will be output to this file. If bool is True, "
"this enables outputting the console data at the integer frequency "
'(set steps_per_data_output_int), while "False" disables outputting the console '
"data file. "
"".format(
_get_default_variables_dict()["ConsoleFreq"],
_get_default_variables_dict()["ConsoleFreq"][0],
_get_default_variables_dict()["ConsoleFreq"][1],
),
"BlockAverageFreq": "Output Frequency (all ensembles): list [bool , int (> 0)] or "
"[Generate_data_bool , steps_per_data_output_int], "
"default = {} or [{} , set via formula based on the number of RunSteps or {} max]. "
"Controls the block averages output of selected thermodynamic properties. "
"Block averages are averages of thermodynamic values of interest for chunks of the "
"simulation (for post-processing of averages or std. dev. in those values)."
"If bool is True, this enables outputting the block averaging data/file at the "
"integer frequency (set steps_per_data_output_int), "
'while "False" disables outputting the block averaging data/file.'
"".format(
_get_default_variables_dict()["BlockAverageFreq"],
_get_default_variables_dict()["BlockAverageFreq"][0],
_get_default_variables_dict()["BlockAverageFreq"][1],
),
"HistogramFreq": "Output Frequency (all ensembles): list [bool , int (> 0)] or "
"[Generate_data_bool , steps_per_data_output_int], "
"default = {} or [{} , set via formula based on the number of RunSteps or {} max]. "
"Controls the histograms. Histograms are a binned listing of observation frequency "
"for a specific thermodynamic variable. In the GOMC code, they also control the output "
"of a file containing energy/molecule samples, "
'which is only used for the "GCMC" ensemble simulations for histogram reweighting purposes.'
"If bool is True, this enables outputting the data to the histogram data at the "
"integer frequency (set steps_per_data_output_int), "
'while "False" disables outputting the histogram data.'
"".format(
_get_default_variables_dict()["HistogramFreq"],
_get_default_variables_dict()["HistogramFreq"][0],
_get_default_variables_dict()["HistogramFreq"][1],
),
# Histogram data
"DistName": "Histogram Output (all ensembles): str (NO SPACES), default = {}. "
"Short phrase which will be combined with RunNumber and RunLetter "
"to use in the name of the binned histogram for molecule distribution."
"".format(_get_default_variables_dict()["DistName"]),
"HistName": "Histogram Output (all ensembles): str (NO SPACES), default = {}. "
"Short phrase, which will be combined with RunNumber and RunLetter, "
"to use in the name of the energy/molecule count sample file."
"".format(_get_default_variables_dict()["HistName"]),
"RunNumber": "Histogram Output (all ensembles): int ( > 0 ), default = {}. "
"Sets a number, which is a part of DistName and HistName file name."
"".format(_get_default_variables_dict()["RunNumber"]),
"RunLetter": "Histogram Output (all ensembles): str (1 alphabetic character only), default = {}. "
"Sets a letter, which is a part of DistName and HistName file name."
"".format(_get_default_variables_dict()["RunLetter"]),
"SampleFreq": "Histogram Output (all ensembles): int ( > 0 ), default = {}. "
"The number of steps per histogram sample or frequency."
"".format(_get_default_variables_dict()["SampleFreq"]),
# Data output for the console and bulk properties calculations
"OutEnergy": "Output Data (all ensembles): [bool, bool], default = {}. "
"The list provides the booleans to [block_averages_bool, console_output_bool]. "
"This outputs the energy data into the block averages and console output/log files."
"".format(_get_default_variables_dict()["OutEnergy"]),
"OutPressure": "Output Data (all ensembles): [bool, bool], default = {}. "
"The list provides the booleans to [block_averages_bool, console_output_bool]. "
"This outputs the pressure data into the block averages and console output/log files."
"".format(_get_default_variables_dict()["OutPressure"]),
"OutMolNum": "Output Data (all ensembles): [bool, bool], default = {}. "
"The list provides the booleans to [block_averages_bool, console_output_bool]. "
"This outputs the number of molecules data into the block averages and console "
"output/log files."
"".format(_get_default_variables_dict()["OutMolNum"]),
"OutDensity": "Output Data (all ensembles): [bool, bool], default = {}. "
"The list provides the booleans to [block_averages_bool, console_output_bool]. "
"This outputs the density data into the block averages and console output/log files."
"".format(_get_default_variables_dict()["OutDensity"]),
"OutVolume": "Output Data (all ensembles): [bool, bool], default = {}. "
"The list provides the booleans to [block_averages_bool, console_output_bool]. "
"This outputs the volume data into the block averages and console output/log files."
"".format(_get_default_variables_dict()["OutVolume"]),
"OutSurfaceTension": "Output Data (all ensembles): [bool, bool], default = {}. "
"The list provides the booleans to [block_averages_bool, console_output_bool]. "
"This outputs the surface tension data into the block averages and console "
"output/log files."
"".format(_get_default_variables_dict()["OutSurfaceTension"]),
# free energy calculation in NVT and NPT ensembles.
"FreeEnergyCalc": "Free Energy Calcs (NVT and NPT only): list [bool , int (> 0)] or "
"[Generate_data_bool , steps_per_data_output_int], default = {}. "
"bool = True enabling free energy calculation during the simulation, false disables "
"the calculation. The int/step frequency sets the frequency of calculating the free energy."
"WARNING: When using the free energy calculations, RcutLow needs to be set to zero (RcutLow=0);"
"otherwise, the free energy calculations can produce results that are slightly off or wrong."
"".format(_get_default_variables_dict()["FreeEnergyCalc"]),
"MoleculeType": "Free Energy Calcs (NVT and NPT only): list [str , int (> 0)] or "
'["residue_name" , residue_ID], '
"The user must set this variable as there is no working default (default = {}). "
'Note: ONLY 4 characters can be used for the string (i.e., "residue_name"). '
"Sets the solute molecule kind (residue name) and molecule number (residue ID), "
"which absolute solvation free will be calculated for."
"".format(_get_default_variables_dict()["MoleculeType"]),
"InitialState": "Free Energy Calcs (NVT and NPT only): int (>= 0), "
"The user must set this variable as there is no working default (default = {}). "
"The index of LambdaCoulomb and LambdaVDW vectors. Sets the index of the"
"LambdaCoulomb and LambdaVDW vectors, to determine the simulation lambda value for"
"VDW and Coulomb interactions. "
"WARNING : This must an integer within the vector count of the LambdaVDW and LambdaCoulomb, "
"in which the counting starts at 0. "
"".format(_get_default_variables_dict()["InitialState"]),
"LambdaVDW": "Free Energy Calcs (NVT and NPT only): list of floats (0 <= floats <= 1), "
"The user must set this variable as there is no working default (default = {}). "
"Lambda values for VDW interaction in ascending order. Sets the intermediate "
"lambda states to which solute-solvent VDW interactions are scaled. "
'WARNING : This list must be the same length as the "LambdaCoulomb" list length.'
"WARNING : All lambda values must be stated in the ascending order, "
"starting with 0.0 and ending with 1.0; otherwise, the program will terminate."
"Example of ascending order 1: [0.0, 0.1, 1.0] "
"Example of ascending order 2: [0.0, 0.1, 0.2, 0.4, 0.9, 1.0] "
"".format(_get_default_variables_dict()["LambdaVDW"]),
"LambdaCoulomb": "Free Energy Calcs (NVT and NPT only): list of floats (0 <= floats <= 1), "
"The user must set this variable as there is no working default (default = {}). "
"Lambda values for Coulombic interaction in ascending order. Sets the intermediate "
"lambda states to which solute-solvent Coulombic interactions are scaled. "
'GOMC defauts to the "LambdaVDW" values for the Coulombic interaction '
'if no "LambdaCoulomb" variable is set. '
'WARNING : This list must be the same length as the "LambdaVDW" list length.'
"WARNING : All lambda values must be stated in the ascending order, "
"starting with 0.0 and ending with 1.0; otherwise, the program will terminate."
"Example of ascending order 1: [0.0, 0.1, 1.0] "
"Example of ascending order 2: [0.0, 0.1, 0.2, 0.4, 0.9, 1.0] "
"".format(_get_default_variables_dict()["LambdaCoulomb"]),
"ScaleCoulomb": "Free Energy Calcs (NVT and NPT only): bool, default = {}, "
"Determines to scale the Coulombic interaction non-linearly (soft-core scheme) or not. "
"True if the Coulombic interaction needs to be scaled non-linearly. "
"False if the Coulombic interaction needs to be scaled linearly. "
"".format(_get_default_variables_dict()["ScaleCoulomb"]),
"ScalePower": "Free Energy Calcs (NVT and NPT only): int (>= 0), default = {}, "
"The p value in the soft-core scaling scheme, where the distance between "
"solute and solvent is scaled non-linearly."
"".format(_get_default_variables_dict()["ScalePower"]),
"ScaleAlpha": "Free Energy Calcs (NVT and NPT only): int or float (>= 0), default = {}, "
"The alpha value in the soft-core scaling scheme, where the distance "
"between solute and solvent is scaled non-linearly."
"".format(_get_default_variables_dict()["ScaleAlpha"]),
"MinSigma": "Free Energy Calcs (NVT and NPT only): int or float (>= 0), default = {}, "
"The minimum sigma value in the soft-core scaling scheme, where the "
"distance between solute and solvent is scaled non-linearly."
"".format(_get_default_variables_dict()["MinSigma"]),
# moves without MEMC
"DisFreq": "Std. MC moves (all ensembles) : "
"int or float (0 <= value <= 1), default are specific for each ensemble {}. "
"Fractional percentage at which the displacement move will occur "
"(i.e., fraction of displacement moves). Note: all of the move types"
"are not available in for every ensemble. Note: all of the move fractions"
"must sum to 1, or the control file writer will fail. "
"".format(_get_default_variables_dict()["DisFreq"]),
"RotFreq": "Std. MC moves (all ensembles) : "
"int or float (0 <= value <= 1), default are specific for each ensemble {}. "
"Fractional percentage at which the rotation move will occur "
"(i.e., fraction of rotation moves). Note: all of the move types"
"are not available in for every ensemble. Note: all of the move fractions"
"must sum to 1, or the control file writer will fail. "
"".format(_get_default_variables_dict()["RotFreq"]),
"IntraSwapFreq": "Std. MC moves (all ensembles) : "
"int or float (0 <= value <= 1), default are specific for each ensemble {}. "
"Fractional percentage at which the molecule will be removed from a "
"box and inserted into the same box using coupled-decoupled configurational-bias"
"algorithm. (i.e., fraction of intra-molecule swap moves). Note: all of the move types"
"are not available in for every ensemble. Note: all of the move fractions"
"must sum to 1, or the control file writer will fail. "
"".format(_get_default_variables_dict()["IntraSwapFreq"]),
"SwapFreq": "Std. MC moves (only GEMC_NPT, GEMC_NVT, and GCMC) : "
"int or float (0 <= value <= 1), default are specific for each ensemble {}. "
"For Gibbs and Grand Canonical (GC) ensemble runs only: Fractional "
"percentage at which molecule swap move will occur using coupled-decoupled "
"configurational-bias. (i.e., fraction of molecule swaps moves). Note: all of the move types"
"are not available in for every ensemble. Note: all of the move fractions"
"must sum to 1, or the control file writer will fail. "
"".format(_get_default_variables_dict()["SwapFreq"]),
"RegrowthFreq": "Std. MC moves (all ensembles) : "
"int or float (0 <= value <= 1), default are specific for each ensemble {}. "
"Fractional percentage at which part of the molecule will be "
"deleted and then regrown using coupled- decoupled configurational-bias algorithm "
"(i.e., fraction of molecular growth moves). Note: all of the move types"
"are not available in for every ensemble. Note: all of the move fractions"
"must sum to 1, or the control file writer will fail. "
"".format(_get_default_variables_dict()["RegrowthFreq"]),
"CrankShaftFreq": "Std. MC moves (all ensembles) : "
"int or float (0 <= value <= 1), default are specific for each ensemble {}. "
"Fractional percentage at which crankshaft move will occur. "
"In this move, two atoms that are forming angle or dihedral are selected randomly and "
"form a shaft. Then any atoms or group that are within these two selected atoms, will "
"rotate around the shaft to sample intra-molecular degree of freedom "
"(i.e., fraction of crankshaft moves). Note: all of the move types"
"are not available in for every ensemble. Note: all of the move fractions"
"must sum to 1, or the control file writer will fail. "
"".format(_get_default_variables_dict()["CrankShaftFreq"]),
"VolFreq": "Std. MC moves (only GEMC_NPT and NPT ) : "
"int or float (0 <= value <= 1), default are specific for each ensemble {}. "
"Fractional percentage at which a volume move will occur "
"(i.e., fraction of Volume moves). "
"Note: all of the move types are not available in for every ensemble. "
"Note: all of the move fractions must sum to 1, or the control file writer will fail. "
"".format(_get_default_variables_dict()["VolFreq"]),
"MultiParticleFreq": "Std. MC moves (all ensembles) : "
"int or float (0 <= value <= 1), default are specific for each ensemble {}. "
"Fractional percentage at which multi-particle move will "
"occur. In this move, all molecules in the selected simulation box will be rigidly "
"rotated or displaced simultaneously, along the calculated torque or force "
"respectively (i.e., fraction of multi-particle moves). Note: all of the move types"
"are not available in for every ensemble. Note: all of the move fractions"
"must sum to 1, or the control file writer will fail. "
"".format(_get_default_variables_dict()["MultiParticleFreq"]),
# MEMC moves
"IntraMEMC-1Freq": "MEMC MC moves (all ensembles) : "
"int or float (0 <= value <= 1), default are specific for each ensemble {}. "
"Fractional percentage at which specified number of small molecule kind will be "
"exchanged with a specified large molecule kind in defined sub-volume within "
"same simulation box. This move need additional information such as "
"ExchangeVolumeDim, ExchangeRatio, ExchangeSmallKind, and ExchangeLargeKind."
"Note: all of the move types are not available in for every ensemble."
"Note: all of the move fractions must sum to 1, or the control file writer will fail. "
"".format(_get_default_variables_dict()["IntraMEMC-1Freq"]),
"MEMC-1Freq": "MEMC MC moves (only GEMC_NPT, GEMC_NVT, and GCMC) : "
"int or float (0 <= value <= 1), default are specific for each ensemble {}. "
"Fractional percentage at which specified number of small molecule kind will be exchanged "
"with a specified large molecule kind in defined sub-volume, between simulation boxes. "
"This move needs additional information such as ExchangeVolumeDim, ExchangeRatio, "
"ExchangeSmallKind, and ExchangeLargeKind."
"Note: all of the move types are not available in for every ensemble."
"Note: all of the move fractions must sum to 1, or the control file writer will fail. "
"".format(_get_default_variables_dict()["MEMC-1Freq"]),
"IntraMEMC-2Freq": "MEMC MC moves (all ensembles) : "
"int or float (0 <= value <= 1), default are specific for each ensemble {}. "
"Fractional percentage at which specified number of small molecule kind "
"will be exchanged with a specified large molecule kind in defined sub-volume "
"within same simulation box. Backbone of small and large molecule kind will be "
"used to insert the large molecule more efficiently. This move need additional "
"information such as ExchangeVolumeDim, ExchangeRatio, ExchangeSmallKind, "
"ExchangeLargeKind, SmallKindBackBone, and LargeKindBackBone. "
"Note: all of the move types are not available in for every ensemble."
"Note: all of the move fractions must sum to 1, or the control file writer will fail. "
"".format(_get_default_variables_dict()["IntraMEMC-2Freq"]),
"MEMC-2Freq": "MEMC MC moves (only GEMC_NPT, GEMC_NVT, and GCMC) : "
"int or float (0 <= value <= 1), default are specific for each ensemble {}. "
"Fractional percentage at which specified number of small molecule kind will be "
"exchanged with a specified large molecule kind in defined sub-volume, between"
"simulation boxes. Backbone of small and large molecule kind will be used to insert "
"the large molecule more efficiently. "
"This move needs additional information such as ExchangeVolumeDim, ExchangeRatio, "
"ExchangeSmallKind, ExchangeLargeKind, SmallKindBackBone, and LargeKindBackBone. "
"Note: all of the move types are not available in for every ensemble."
"Note: all of the move fractions must sum to 1, or the control file writer will fail. "
"".format(_get_default_variables_dict()["MEMC-2Freq"]),
"IntraMEMC-3Freq": "MEMC MC moves (all ensembles) : "
"int or float (0 <= value <= 1), default are specific for each ensemble {}. "
"Fractional percentage at which specified number of small molecule kind will be "
"exchanged with a specified large molecule kind in defined sub-volume within same "
"simulation box. Specified atom of the large molecule kind will be used to insert "
"the large molecule using coupled-decoupled configurational-bias. This move needs "
"additional information such as ExchangeVolumeDim, ExchangeRatio, ExchangeSmallKind, "
"ExchangeLargeKind, and LargeKindBackBone. "
"Note: all of the move types are not available in for every ensemble."
"Note: all of the move fractions must sum to 1, or the control file writer will fail. "
"".format(_get_default_variables_dict()["IntraMEMC-3Freq"]),
"MEMC-3Freq": "MEMC MC moves (only GEMC_NPT, GEMC_NVT, and GCMC) : "
"int or float (0 <= value <= 1), default are specific for each ensemble {}. "
"Fractional percentage at which specified number of small molecule kind will be exchanged "
"with a specified large molecule kind in defined sub-volume, between simulation boxes. "
"Specified atom of the large molecule kind will be used to insert the large molecule "
"using coupled-decoupled configurational-bias. This move need additional information "
"such as ExchangeVolumeDim, ExchangeRatio, ExchangeSmallKind, ExchangeLargeKind, "
"and LargeKindBackBone. "
"Note: all of the move types are not available in for every ensemble."
"Note: all of the move fractions must sum to 1, or the control file writer will fail. "
"".format(_get_default_variables_dict()["MEMC-3Freq"]),
# MEMC move parameters
"ExchangeVolumeDim": "MEMC parameters (all ensembles) : "
"list of 3 floats or integers "
"[int or float (> 0), int or float (> 0), int or float (> 0)]"
" or [X-dimension, Y-dimension, Z-dimension)], default = {}. "
"To use all variation of MEMC and Intra-MEMC Monte Carlo moves, the exchange "
"subvolume must be defined. The exchange sub-volume is defined as an orthogonal box "
"with x, y, and z-dimensions, where small molecule/molecules kind will be selected "
"from to be exchanged with a large molecule kind. "
"Note: Currently, the X and Y dimension cannot be set independently (X = Y = max(X, Y)). "
"Note: A heuristic for setting good values of the x, y, and z-dimensions is to use "
"the geometric size of the large molecule plus 1-2 Å in each dimension. "
"Note: In case of exchanging 1 small molecule kind with 1 large molecule kind in "
"IntraMEMC-2, IntraMEMC-3, MEMC-2, MEMC-3 Monte Carlo moves, the sub-volume "
"dimension has no effect on acceptance rate. "
"".format(_get_default_variables_dict()["ExchangeVolumeDim"]),
"MEMC_DataInput": "MEMC parameters (availablity based on selelection): nested lists, "
+ "default = {}. ".format(
_get_default_variables_dict()["MEMC_DataInput"]
)
+ "Enter data as a list with some sub-lists as follows: "
"[[ExchangeRatio_int (> 0), ExchangeLargeKind_str, "
"[LargeKindBackBone_atom_1_str_or_NONE, LargeKindBackBone_atom_2_str_or_NONE ], "
"ExchangeSmallKind_str, "
"[SmallKindBackBone_atom_1_str_or_NONE, SmallKindBackBone_atom_2_str_or_NONE ]], ..., "
"[ExchangeRatio_int (> 0), ExchangeLargeKind_str, "
"[LargeKindBackBone_atom_1_str_or_NONE, LargeKindBackBone_atom_2_str_or_NONE ], "
"ExchangeSmallKind_str, "
"[SmallKindBackBone_atom_1_str_or_NONE, SmallKindBackBone_atom_2_str_or_NONE ]. "
"NOTE: CURRENTLY ALL THESE INPUTS NEED TO BE SPECIFIED, REGARDLESS OF THE MEMC TYPE "
"SELECTION. IF THE SmallKindBackBone or LargeKindBackBone IS NOT REQUIRED FOR THE "
"MEMC TYPE, None CAN BE USED IN PLACE OF A STRING. "
"Note: These strings must match the residue in the psf and psb files or it will fail. "
"It is recommended that the user print the Charmm object psf and pdb files "
"and review the residue names that match the atom name before using the in "
"the MEMC_DataInput variable input."
"Note: see the below data explanations for the ExchangeRatio, ExchangeSmallKind, "
"ExchangeLargeKind, LargeKindBackBone, SmallKindBackBone. "
"Example 1 (MEMC-1) : [ [1, 'WAT', [None, None], 'wat', [None, None]] , "
"[1, 'WAT', [None, None], 'wat', [None, None]] . "
"Example 2 (MEMC-2): [ [1, 'WAT', ['O1', 'H1'], 'wat', ['O1', 'H1' ]] , "
"[1, 'WAT', ['H1', 'H2'], 'wat', ['H1', 'H2' ]] . "
"Example 3 (MEMC-3) : [ [2, 'WAT', 'O1', 'H1'], 'wat', [None, None]] , "
"[2, 'WAT', ['H1', 'H2'], 'wat', [None, None]] .\n"
"\t\t\t\t\t\t\t\t\t\t\t\t\t --- ExchangeRatio = MEMC parameters (all ensembles): "
"int (> 0), default = None. The Ratio of exchanging "
"small molecule/molecules with 1 large molecule. "
"To use all variation of MEMC and Intra-MEMC Monte Carlo moves, "
"the exchange ratio must be defined. "
"The exchange ratio defines how many small molecule will be "
"exchanged with 1 large molecule. For each large-small molecule pairs, "
"one exchange ratio must be defined. \n"
"\t\t\t\t\t\t\t\t\t\t\t\t\t --- ExchangeSmallKind = MEMC parameters (all ensembles): "
"str, default = None. The small molecule "
"kind (resname) to be exchanged. "
"Note: ONLY 4 characters can be used for the strings. "
"To use all variation of MEMC and Intra-MEMC Monte Carlo moves, "
"the small molecule kind to be exchanged with a large molecule "
"kind must be defined. Multiple small molecule kind can be specified. \n"
"\t\t\t\t\t\t\t\t\t\t\t\t\t --- ExchangeLargeKind = MEMC parameters (all ensembles): "
"str, default = None. The large molecule "
"kind (resname) to be exchanged. "
"Note: ONLY 4 characters can be used for the strings. "
"To use all variations of MEMC and Intra-MEMC Monte Carlo moves, "
"the large molecule kind to be exchanged with small molecule "
"kind must be defined. Multiple large molecule kind can be specified. \n"
"\t\t\t\t\t\t\t\t\t\t\t\t\t --- LargeKindBackBone = MEMC parameters (all ensembles): "
"list [str, str] or [None, None], default = None "
"Note: ONLY 4 characters can be used for the strings. "
"The [None, None] values can only be used if that MEMC type does not require them. "
"The strings for the the atom name 1 and atom name 2 that belong to the large "
"molecule’s backbone (i.e., [str_for_atom_name_1, str_for_atom_name_2]) "
"To use MEMC-2, MEMC-3, IntraMEMC-2, and IntraMEMC-3 Monte Carlo moves, the "
"large molecule backbone must be defined. The backbone of the molecule is defined "
"as a vector that connects two atoms belong to the large molecule. The large "
"molecule backbone will be used to align the sub-volume in MEMC-2 and IntraMEMC-2 "
"moves, while in MEMC-3 and IntraMEMC-3 moves, it uses the atom name to start "
"growing the large molecule using coupled-decoupled configurational-bias. For "
"each large-small molecule pairs, two atom names must be defined. "
"Note: all atom names in the molecule must be unique. "
"Note: In MEMC-3 and IntraMEMC-3 Monte Carlo moves, both atom names must be same, "
"otherwise program will be terminated. "
"Note: If the large molecule has only one atom (mono atomic molecules), "
"same atom name must be used for str_for_atom_name_1 and str_for_atom_name_2 "
"of the LargeKindBackBone. \n"
"\t\t\t\t\t\t\t\t\t\t\t\t\t --- SmallKindBackBone = MEMC parameters (all ensembles): "
" list [str, str] or [None, None], default = None "
"Note: ONLY 4 characters can be used for the strings. "
"The [None, None] values can only be used if that MEMC type does not require them."
"The strings for the the atom name 1 and atom name 2 that belong to the small "
"molecule’s backbone (i.e., [str_for_atom_name_1, str_for_atom_name_2]) "
"To use MEMC-2, and IntraMEMC-2 Monte Carlo moves, the small molecule backbone "
"must be defined. The backbone of the molecule is defined as a vector that "
"connects two atoms belong to the small molecule and will be used to align the "
"sub-volume. For each large-small molecule pairs, two atom names must be defined. "
"Note: all atom names in the molecule must be unique. "
"Note: If the small molecule has only one atom (mono atomic molecules), same atom "
"name must be used str_for_atom_name_1 and str_for_atom_name_2 "
"of the SmallKindBackBone. ",
"TargetedSwapFreq": "int or float (0 <= value <= 1), default are specific for each ensemble "
"{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.0, 'GCMC': 0} "
"Fractional percentage at which targeted swap move will occur. "
"Note: This is only usable with the 'GCMC', 'GEMC_NVT', and 'GEMC_NPT' ensembles., "
"Note: This is used in conjunction with the 'TargetedSwap_DataInput' variables. ",
"IntraTargetedSwapFreq": "int or float (0 <= value <= 1), default are specific for each ensemble "
"{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.0, 'GCMC': 0} "
'Note: This is used in conjunction with the "TargetedSwap_DataInput" variables. ',
"TargetedSwap_DataInput": "dict, default=None. "
"A dictionary which can contain one or several targeted swap regions, each designated with "
"their own tag ID number (aka, subvolume number). "
"A few examples for TargetedSwap_DataInput input is provided below. "
"NOTE: MULTIPLE SIMULATION BOXES CAN BE UTILIZED BY SETTING MULTIPLE tag_ID_integer VALUES (INTEGERS VALUES), "
'NOTE: THIS IS REQUIRED WHEN USING EITHER THE "TargetedSwapFreq" OR "IntraTargetedSwapFreq" MC MOVES. '
"WARNING: THE tag_ID_integer VALUES MUST BE UNIQUE FOR EACH SUBVOLUME, "
"OR THE DICTIONARY WILL OVERWRITE THE PREVIOUS SUBVOLUME (tag_ID_integer) SECTION "
"WITH THE CURRENT tag_ID_integer AND ITS RESPECTIVE VALUES. "
'The details of each key and value for the "TargetedSwap_DataInput" are provided below. '
'\t\t\t\t\t\t\t\t\t\t\t\t\t --- "SubVolumeType" : str ("static" or "dynamic"), No default is provided. '
"The type of targeted swap box (subvolume) that will be created. "
'The "static" type will maintain the box (subvolume) in a fixed location during the whole simulation, '
"with the center of the box determined by the coordinates set in the "
'"SubvolumeCenter" parameter. '
'The "dynamic" type will allow for dynamic movement of the box (subvolume) based atom indices '
'provided in the SubvolumeCenterList variable. For the "dynamic" type, the user must define a '
'list of atom indices using "SubVolumeCenterList" keyword; the geometric center of the '
"provided atom indices will be used as the center of subVolume. User must ensure that the "
"atoms defined in the atom list remain in the simulation box (by setting the Beta value to 2 in PDB file). "
'\t\t\t\t\t\t\t\t\t\t\t\t\t --- "SubVolumeBox" : int (0 or 1), No default is provided. '
"The simulation box in which the targeted swap subvolume will be applied. "
"NOTE: Only box zero (0) can be used for the GCMC, NPT, and NVT ensembles. "
'\t\t\t\t\t\t\t\t\t\t\t\t\t --- "SubVolumeCenter" : list of three (3) int or float, [x-axis, y-axis, z-axis], '
"No default is provided. "
"The simulation box is centered on this x, y, and z-axis points (in Angstroms), which is only "
'utilized when "SubVolumeType" is set to "static". '
'\t\t\t\t\t\t\t\t\t\t\t\t\t --- "SubVolumeCenterList" : list of int and/or str (>=0), '
"[atom_index, ..., atom_index], No default is provided. "
"The simulation box subVolume is centered on the geometric center of the provided atom indices, which is "
'only used when the "SubVolumeType" is set to "dynamic". For example, ["0-10", 12, 15] means that '
"atom indices 0 to 10, 12 and 15 are used as the geometric center of the simulation box subVolume. "
'NOTE: THE ATOM INDICES RANGES MUST BE A STRING IN THE FORM "2-20", WITH THE FIRST ATOM INDICES BEING '
'SMALLER THAN THE SECOND (i.e, "a-b", where a < b). ALL SINGULAR ATOM INDICES MUST BE INTEGERS. '
"NOTE: THE SAME ATOM INDICES CAN BE USED 2, 3 OR X TIMES TO WEIGHT that atom 2, 3, OR X TIMES MORE "
"IN THE GEOMETRIC CENTERING CALCULATION. "
"NOTE: THE ATOM INDICES START AT ZERO (0), WHILE THE PDB AND PSF FILES START AT ONE (1). "
"THEREFORE, YOU NEED TO BE CAREFUL WHEN SETTING THE INDICES FROM THE PDB OR PSF VALUES AS THEY ARE "
"ONE (1) NUMBER OFF. "
'\t\t\t\t\t\t\t\t\t\t\t\t\t --- "SubVolumeDim" : list of three (3) int or float (>0), '
"[x-axis, y-axis, z-axis], No default is provided. "
"This sets the size of the simulation box (subVolume) in the x, y, and z-axis (in Angstroms). "
'\t\t\t\t\t\t\t\t\t\t\t\t\t --- "SubVolumeResidueKind" : str or list of str, "ALL" or "residue" '
'or ["ALL"] or [residue_str, ..., residue_str], No default is provided. '
'The residues that will be used in the "TargetedSwap_DataInput" subvolume. '
'Alternatively, the user can just set the value to ["ALL"] or "ALL", which covers all the residues. '
'\t\t\t\t\t\t\t\t\t\t\t\t\t --- "SubVolumeRigidSwap" : bool, '
+ "default = {} ".format(
_get_default_variables_dict()["SubVolumeRigidSwap".lower()]
)
+ "Choose whether to use a rigid or flexible molecule insertion using CD-CBMC for the subVolume. "
"True uses a rigid molecule insertion, while False uses a flexible molecule insertion "
'\t\t\t\t\t\t\t\t\t\t\t\t\t --- "SubVolumePBC" : str ("X", "XY", "XZ", "XYZ", "Y", "YZ", or "Z"), '
+ "default = {} ".format(
_get_default_variables_dict()["SubVolumePBC".lower()]
)
+ "Apply periodic boundary condition (PBC) in selected axes for the subVolume. "
'Example 1, "X" applies PBC only in the X axis. Example 2, "XY" applies PBC only in the X and Y axes. '
'Example 3, "XYZ" applies PBC in the X, Y, and Z axes. '
'\t\t\t\t\t\t\t\t\t\t\t\t\t --- "SubVolumeChemPot" : dict {str (4 dig limit) , int or float}, '
"No default is provided. "
"The chemical potentials in GOMC units of energy, K. If no SubVolumeChemPot is provided "
"the default system chemical potential values are used. "
"There is a 4 character limit for the string/residue name since the PDB/PSF "
"files have a 4 character limitation and require an exact match in the conf file. "
"Note: These strings must match the residue in the psf and psb files or it will fail. "
"The name of the residues and their corresponding chemical potential must be specified "
'for every residue in the system (i.e., {"residue_name" : chemical_potential}). '
"Note: THIS IS ONLY REQUIRED FOR THE GCMC ENSEMBLE. "
"Note: IF 2 KEYS WITH THE SAME STRING/RESIDUE ARE PROVIDED, ONE WILL BE AUTOMATICALLY "
"OVERWRITTEN AND NO ERROR WILL BE THROWN IN THIS CONTROL FILE WRITER. "
'Note: ONLY THE "SubVolumeChemPot" OR THE "SubVolumeFugacity" CAN BE USED FOR ALL THE '
'TARGET SWAP BOXES (SUBVOLUMES). IF MIX OF "SubVolumeChemPot" AND "SubVolumeFugacity" ARE '
"USED THE CONTROL FILE WRITER WILL THROW AN ERROR. "
'\t\t\t\t\t\t\t\t\t\t\t\t\t --- "SubVolumeFugacity" : dict {str , int or float (>= 0)}, '
"No default is provided. "
'The fugacity in GOMC units of pressure, bar. If no "SubVolumeFugacity" is provided '
"the default system fugacity values are used. "
"There is a 4 character limit for the string/residue name since the PDB/PSF "
"files have a 4 character limitation and require an exact match in the conf file. "
"Note: These strings must match the residue in the psf and psb files or it will fail. "
"The name of the residues and their corresponding fugacity must be specified "
'for every residue in the system (i.e., {"residue_name" : fugacity}). '
"Note: THIS IS ONLY REQUIRED FOR THE GCMC ENSEMBLE. "
"Note: IF 2 KEYS WITH THE SAME STRING/RESIDUE ARE PROVIDED, ONE WILL BE AUTOMATICALLY "
"OVERWRITTEN AND NO ERROR WILL BE THROWN IN THIS CONTROL FILE WRITER. "
'Note: ONLY THE "SubVolumeChemPot" OR THE "SubVolumeFugacity" CAN BE USED FOR ALL THE '
'TARGET SWAP BOXES (SUBVOLUMES). IF MIX OF "SubVolumeChemPot" AND "SubVolumeFugacity" ARE '
"USED THE CONTROL FILE WRITER WILL THROW AN ERROR. ",
# ******************************************************************************************************
# Definitions in this function are copied to a large extent from the GOMC manual release version 2.60 (end)
# insert citation here:
# ******************************************************************************************************
}
if description:
return valid_input_variables
else:
return list(valid_input_variables.keys())
def _get_default_variables_dict():
"""
Provides a dictionary of the default variables inputs and their default settings (user optional).
Returns
---------
default_input_variables_dict : dict
Provides a dict of the default variables inputs (user optional)
"""
default_input_variables_dict = {
"PRNG": "RANDOM",
"ParaTypeCHARMM": True,
"ParaTypeMie": False,
"ParaTypeMARTINI": False,
"RcutCoulomb_box_0": None,
"RcutCoulomb_box_1": None,
"Pressure": 1.01325,
"Rcut": 10,
"RcutLow": 0,
"LRC": True,
"IPC": False,
"Exclude": "1-3",
"coul_1_4_scaling": None,
"Potential": "VDW",
"Rswitch": 9,
"ElectroStatic": True,
"Ewald": True,
"CachedFourier": False,
"Tolerance": 0.00001,
"Dielectric": 15,
"PressureCalc": [True, 10000],
"EqSteps": 1000000,
"AdjSteps": 1000,
"VDWGeometricSigma": False,
"useConstantArea": False,
"FixVolBox0": False,
# GCMC only properties
"ChemPot": None,
"Fugacity": None,
# CBMC inputs
"CBMC_First": 12,
"CBMC_Nth": 10,
"CBMC_Ang": 50,
"CBMC_Dih": 50,
# Control file (.conf file ) output controls/parameters
"OutputName": "Output_data",
"CoordinatesFreq": [True, 1000000],
"DCDFreq": [
False,
1000000,
], # set to False until this is in the new official GOMC software release
"RestartFreq": [True, 1000000],
"CheckpointFreq": [True, 1000000],
"ConsoleFreq": [True, 10000],
"BlockAverageFreq": [True, 10000],
"HistogramFreq": [True, 10000],
# Histogram data
"DistName": "dis",
"HistName": "his",
"RunNumber": 1,
"RunLetter": "a",
"SampleFreq": 500,
# Data output for the console and bulk properties calculations
"OutEnergy": [True, True],
"OutPressure": [True, True],
"OutMolNum": [True, True],
"OutDensity": [True, True],
"OutVolume": [True, True],
"OutSurfaceTension": [False, False],
# free energy calculation in NVT and NPT ensembles.
"FreeEnergyCalc": None,
"MoleculeType": None,
"InitialState": None,
"LambdaVDW": None,
"LambdaCoulomb": None,
"ScaleCoulomb": False,
"ScalePower": 2,
"ScaleAlpha": 0.5,
"MinSigma": 3,
# MEMC move info
"ExchangeVolumeDim": [1.0, 1.0, 1.0],
"MEMC_DataInput": None,
"TargetedSwap_DataInput": None,
# TargetedSwap_DataInput default values (these need to be all lower case)
"subvolumerigidswap": True,
"subvolumepbc": "XYZ",
# moves without MEMC
"DisFreq": {
"NVT": 0.15,
"NPT": 0.15,
"GEMC_NVT": 0.20,
"GEMC_NPT": 0.19,
"GCMC": 0.15,
},
"RotFreq": {
"NVT": 0.15,
"NPT": 0.15,
"GEMC_NVT": 0.20,
"GEMC_NPT": 0.20,
"GCMC": 0.15,
},
"IntraSwapFreq": {
"NVT": 0.30,
"NPT": 0.29,
"GEMC_NVT": 0.10,
"GEMC_NPT": 0.10,
"GCMC": 0.10,
},
"SwapFreq": {
"NVT": 0.00,
"NPT": 0.00,
"GEMC_NVT": 0.20,
"GEMC_NPT": 0.20,
"GCMC": 0.35,
},
"RegrowthFreq": {
"NVT": 0.30,
"NPT": 0.30,
"GEMC_NVT": 0.20,
"GEMC_NPT": 0.20,
"GCMC": 0.15,
},
"CrankShaftFreq": {
"NVT": 0.10,
"NPT": 0.10,
"GEMC_NVT": 0.10,
"GEMC_NPT": 0.10,
"GCMC": 0.10,
},
"VolFreq": {
"NVT": 0.00,
"NPT": 0.01,
"GEMC_NVT": 0.00,
"GEMC_NPT": 0.01,
"GCMC": 0.00,
},
"MultiParticleFreq": {
"NVT": 0.00,
"NPT": 0.00,
"GEMC_NVT": 0.00,
"GEMC_NPT": 0.00,
"GCMC": 0.00,
},
# MEMC moves
"IntraMEMC-1Freq": {
"NVT": 0.00,
"NPT": 0.00,
"GEMC_NVT": 0.00,
"GEMC_NPT": 0.00,
"GCMC": 0.00,
},
"MEMC-1Freq": {
"NVT": 0.00,
"NPT": 0.00,
"GEMC_NVT": 0.00,
"GEMC_NPT": 0.00,
"GCMC": 0.00,
},
"IntraMEMC-2Freq": {
"NVT": 0.00,
"NPT": 0.00,
"GEMC_NVT": 0.00,
"GEMC_NPT": 0.00,
"GCMC": 0.00,
},
"MEMC-2Freq": {
"NVT": 0.00,
"NPT": 0.00,
"GEMC_NVT": 0.00,
"GEMC_NPT": 0.00,
"GCMC": 0.00,
},
"IntraMEMC-3Freq": {
"NVT": 0.00,
"NPT": 0.00,
"GEMC_NVT": 0.00,
"GEMC_NPT": 0.00,
"GCMC": 0.00,
},
"MEMC-3Freq": {
"NVT": 0.00,
"NPT": 0.00,
"GEMC_NVT": 0.00,
"GEMC_NPT": 0.00,
"GCMC": 0.00,
},
"TargetedSwapFreq": {
"NVT": 0.00,
"NPT": 0.00,
"GEMC_NVT": 0.00,
"GEMC_NPT": 0.00,
"GCMC": 0.00,
},
"IntraTargetedSwapFreq": {
"NVT": 0.00,
"NPT": 0.00,
"GEMC_NVT": 0.00,
"GEMC_NPT": 0.00,
"GCMC": 0.00,
},
}
return default_input_variables_dict
def print_required_input(description=False):
"""
Prints the required ensemble arguments with an optional description based on the ensemble type
Parameters
----------
description : bool, default = False.
If True, it prints the descriptions of the required ensemble inputs (i.e. dict),
If False, it only prints the required ensemble inputs without the descriptions (i.e. list)
Returns
---------
Prints the required ensemble arguments with an optional description based on the ensemble type
"""
required_data_dict = _get_required_data(description=True)
required_data_list = _get_required_data(description=False)
ensemble_has_all_valid_required_data = True
required_data = _get_required_data()
for iter in range(0, len(required_data_list)):
if required_data_list[iter] not in required_data:
ensemble_has_all_valid_required_data = False
if ensemble_has_all_valid_required_data:
for iter_2 in range(0, len(required_data_list)):
required_data_iter = required_data_list[iter_2]
if description is False:
print(
"{:10s}: {}".format(str(iter_2), str(required_data_iter))
)
elif description is True:
print(
"{:10s}: {:30s} {}".format(
str(iter_2),
str(required_data_iter),
str(required_data_dict[required_data_iter]),
)
)
else:
print(
"ERROR: Some files in this ensemble are not in the required file list"
)
def check_valid_ensemble_input_variables(
ensemble_type, testing_input_variables_list
):
"""
Checks if all the input variables (user optional) inputs are valid for the given
ensemble, and provides a list of the bad variables in the printed output.
Parameters
----------
ensemble_type : str, valid options are 'NVT', 'NPT', 'GEMC_NVT', 'GEMC_NPT', 'GCMC'
The ensemble type of the simulation.
testing_input_variables_list : list
List containing the optional ensemble input variables which will be
tested for to see if they are valid.
Returns
---------
bool:
Returns a bool (True or False) depending on if all variables
are valid or not.
"""
bad_key_inputs_list = []
valid_input_variables_list = _get_possible_ensemble_input_variables(
ensemble_type
)
ensemble_has_valid_input_variables_list = True
for iter in range(0, len(testing_input_variables_list)):
if testing_input_variables_list[iter] not in valid_input_variables_list:
bad_key_inputs_list.append(testing_input_variables_list[iter])
ensemble_has_valid_input_variables_list = False
if ensemble_has_valid_input_variables_list:
return [True, bad_key_inputs_list]
else:
return [False, bad_key_inputs_list]
def print_valid_ensemble_input_variables(ensemble_type, description=False):
"""
Prints the arguments for optional variables brief description based on the ensemble type
Parameters
----------
ensemble_type = str, valid options are 'NVT', 'NPT', 'GEMC_NVT', 'GEMC_NPT', 'GCMC'
The ensemble type of the simulation.
description = bool, default = False.
If True, it prints the descriptions of the optional variable ensemble inputs (i.e. dict),
If False, it only prints the optional variable ensemble inputs without the
descriptions (i.e. list)
Returns
---------
Prints the arguments for optional variables brief description based on the ensemble type
"""
valid_input_variables_dict = _get_all_possible_input_variables(
description=True
)
ensemble_has_all_valid_input_variables = True
all_valid_input_variables = _get_all_possible_input_variables()
valid_input_variables_list = _get_possible_ensemble_input_variables(
ensemble_type
)
for iter in range(0, len(valid_input_variables_list)):
if valid_input_variables_list[iter] not in all_valid_input_variables:
ensemble_has_all_valid_input_variables = False
if ensemble_has_all_valid_input_variables:
for iter_2 in range(0, len(valid_input_variables_list)):
ensemble_kwarg_iter = valid_input_variables_list[iter_2]
if description is False:
print(
"{:10s}: {}".format(
str(iter_2), str(ensemble_kwarg_iter)
)
)
elif description is True:
print(
"{:10s}: {:30s} {}".format(
str(iter_2),
str(ensemble_kwarg_iter),
str(valid_input_variables_dict[ensemble_kwarg_iter]),
)
)
else:
print(
"ERROR: Some input_variables in the ensemble are not in the main input_variables list"
)
def _get_possible_ensemble_input_variables(ensemble_type):
"""
Provides list of the possible optional input variables based on the ensemble type
Parameters
----------
ensemble_type : str, valid options are 'NVT', 'NPT', 'GEMC_NVT', 'GEMC_NPT', 'GCMC'
The ensemble type of the simulation.
Returns
---------
valid_input_variables_list : list
A list possible optional input variables for the provided ensemble type.
"""
histogram_output_variables_list = [
"DistName",
"HistName",
"RunNumber",
"RunLetter",
"SampleFreq",
]
cbmc_variables_list = ["CBMC_First", "CBMC_Nth", "CBMC_Ang", "CBMC_Dih"]
output_freq_variables_list = [
"OutputName",
"CoordinatesFreq",
"DCDFreq",
"RestartFreq",
"CheckpointFreq",
"ConsoleFreq",
"BlockAverageFreq",
"HistogramFreq",
]
output_data_variables_list = [
"OutEnergy",
"OutPressure",
"OutMolNum",
"OutDensity",
"OutVolume",
"OutSurfaceTension",
]
std_mc_moves_variables_list = [
"DisFreq",
"RotFreq",
"IntraSwapFreq",
"SwapFreq",
"RegrowthFreq",
"CrankShaftFreq",
"VolFreq",
"MultiParticleFreq",
"TargetedSwapFreq",
"IntraTargetedSwapFreq",
]
memc_target_swap_mc_moves_variables_list = [
"IntraMEMC-1Freq",
"MEMC-1Freq",
"IntraMEMC-2Freq",
"MEMC-2Freq",
"IntraMEMC-3Freq",
"MEMC-3Freq",
"ExchangeVolumeDim",
"MEMC_DataInput",
"TargetedSwap_DataInput",
]
basic_sim_info_variables_list = [
"PRNG",
"ParaTypeCHARMM",
"ParaTypeMie",
"ParaTypeMARTINI",
"RcutCoulomb_box_0",
"Pressure",
"Rcut",
"RcutLow",
"LRC",
"IPC",
"Exclude",
"Potential",
"Rswitch",
"ElectroStatic",
"Ewald",
"CachedFourier",
"Tolerance",
"Dielectric",
"PressureCalc",
"EqSteps",
"AdjSteps",
"VDWGeometricSigma",
"useConstantArea",
]
if ensemble_type in ["NPT", "NVT"]:
extra_sim_info_variables_list = []
free_energy_variables_list = [
"FreeEnergyCalc",
"MoleculeType",
"InitialState",
"LambdaVDW",
"LambdaCoulomb",
"ScaleCoulomb",
"ScalePower",
"ScaleAlpha",
"MinSigma",
]
elif ensemble_type in ["GEMC_NPT", "GEMC_NVT"]:
extra_sim_info_variables_list = ["RcutCoulomb_box_1", "FixVolBox0"]
free_energy_variables_list = [] # always empty for GEMC
elif ensemble_type == "GCMC":
extra_sim_info_variables_list = ["ChemPot", "Fugacity"]
free_energy_variables_list = [] # always empty for GCMC
if ensemble_type in ["NPT", "NVT", "GEMC_NPT", "GEMC_NVT", "GCMC"]:
valid_input_variables_list = (
basic_sim_info_variables_list
+ extra_sim_info_variables_list
+ cbmc_variables_list
+ output_freq_variables_list
+ histogram_output_variables_list
+ output_data_variables_list
+ free_energy_variables_list
+ std_mc_moves_variables_list
+ memc_target_swap_mc_moves_variables_list
)
else:
warn(
"WARNING: The ensemble_type selected for the _get_possible_ensemble_input_variables "
"function is not valid."
)
valid_input_variables_list = None
return valid_input_variables_list
class GOMCControl:
"""
Constructs the GOMC control file with user selected variables.
The selected variables and Class attributes are mostly or nearly identical to the
GOMC command names. For many ensembles, the user may use the default input_variables_dict
variables, unless they are required for the specific ensemble (Example:
the GCMC ensemble requires the user to input the Chempot or Fugacity variables,
or the build will fail.)
Default settings for the GOMC configuration files are based upon
an educated guess, which should result in appropriate sampling for a
given ensemble/simulation type. However, there is no guarantee that
the default setting will provide the best or adequate sampling for
the selected system. The user can modify the configuration/control files
based on the simulation specifics or optimize the system beyond the standard
settings. These override options are available via the keyword arguments
in input_variable_dict.
Parameters
----------
charmm_object : Charmm object
Charmm object is has been parameterized from the selected force field.,
ensemble_typ : str, ['NVT', 'NPT', 'GEMC_NPT', 'GCMC-NVT', 'GCMC']
The ensemble type of the simulation.
RunSteps : int (>0), must be an integer greater than zero.
Sets the total number of simulation steps.
Temperature : float or int (>0), must be an integer greater than zero.
Temperature of system in Kelvin (K)
ff_psf_pdb_file_directory : str (optional), default=None (i.e., the current directory).
The full or relative directory added to the force field, psf, and pdb
file names, created via the Charmm object.
check_input_files_exist : bool, (default=True)
Check if the force field, psf, and pdb files exist.
If the files are checked and do not exist, the writer will throw a ValueError.
True, check if the force field, psf, and pdb files exist.
False, do not check if the force field, psf, and pdb files exist.
Restart : boolean, default = False
Determines whether to restart the simulation from restart file
(``*_restart.pdb`` and ``*_restart.psf``) or not.
RestartCheckpoint : boolean, default = False
Determines whether to restart the simulation with the checkpoint
file (checkpoint.dat) or not. Restarting the simulation with checkpoint.dat
would result in an identical outcome, as if previous simulation was continued.
ExpertMode : boolean, default = False
This allows the move ratios to be any value, regardless of the ensemble,
provided all the move ratios sum to 1. For example, this mode is utilized
to easily equilibrate a GCMC or GEMC ensemble in a pseudo NVT mode by removing
the requirement that the volume and swap moves must be non-zero.
In other words, when the volume and swap moves are zero, the GCMC and GEMC
ensembles will run pseudo NVT simulations in 1 and 2 simulation boxes, respectively.
The simulation's output and restart files will keep their original output structure
for the selected ensemble, which is advantageous when automating a workflow.
Parameters : str, (default=None)
Override all other force field directory and filename input with the correct extension (.inp or .par).
Note: the default directory is the current directory with the Charmm object file name.
Coordinates_box_0 : str, (default=None)
Override all other box 0 pdb directory and filename inputs with the correct extension.
Note: the default directory is the current directory with the Charmm object file name.
Structure_box_0 : str, (default=None)
Override all other box 0 psf directory and filename inputs with the correct extension.
Note: the default directory is the current directory with the Charmm object file name.
Coordinates_box_1 : str, (default=None)
Override all other box 1 pdb directory and filename inputs with the correct extension.
Note: the default directory is the current directory with the Charmm object file name.
Structure_box_1 : str, (default=None)
Override all other box 1 psf directory and filename inputs with the correct extension.
Note: the default directory is the current directory with the Charmm object file name.
binCoordinates_box_0 : str, (default=None)
The box 0 binary coordinate file is used only for restarting a GOMC simulation,
which provides increased numerical accuracy.
extendedSystem_box_0 : str, (default=None)
The box 0 vectors and origin file is used only for restarting a GOMC simulation.
binVelocities_box_0 : str, (default=None)
The box 0 binary velocity file is used only for restarting a GOMC simulation,
which provides increased numerical accuracy. These velocities are only passed thru
GOMC since Monte Carlo simulations do not utilize any velocity information.
binCoordinates_box_1 : str, (default=None)
The box 1 binary coordinate file is used only for restarting a GOMC simulation,
which provides increased numerical accuracy.
extendedSystem_box_1 : str, (default=None)
The box 1 vectors and origin file is used only for restarting a GOMC simulation.
binVelocities_box_1 : str, (default=None)
The box 1 binary velocity file is used only for restarting a GOMC simulation,
which provides increased numerical accuracy. These velocities are only passed thru
GOMC since Monte Carlo simulations do not utilize any velocity information.
input_variables_dict: dict, default = None
These input variables are optional and override the default settings.
Changing these variables likely required for more advanced systems.
The details of the acceptable input variables for the selected
ensembles can be found by running the code below in python,
>>> print_valid_ensemble_input_variables('GCMC', description = True)
which prints the input_variables with their subsection description
for the selected 'GCMC' ensemble (other ensembles can be set as well).
Example : input_variables_dict = {'PRNG' : 123,
'ParaTypeCHARMM' : True }
# *******************************************************************
# input_variables_dict options (keys and values) - (start)
# Note: the input_variables_dict keys are also attributes
# *******************************************************************
PRNG : string or int (>= 0) ("RANDOM" or int), default = "RANDOM"
PRNG = Pseudo-Random Number Generator (PRNG). There are two (2) options, entering
the string, "RANDOM", or a integer.
--- "RANDOM": selects a random seed number. This will enter the line
"PRNG RANDOM" in the gomc configuration file.
--- integer: which defines the integer seed number for the simulation. This is
equivalent to entering the following two lines in the configuration file
line 1 = PRNG INTSEED
line 2 = Random_Seed user_selected_integer.
Example 1: for a random seed enter the string "RANDOM".
Example 2: for a specific seed number enter a integer of your choosing.
ParaTypeCHARMM : boolean, default = True
True if a CHARMM forcefield, False otherwise.
ParaTypeMie : boolean, default = False
True if a Mie forcefield type, False otherwise.
ParaTypeMARTINI : boolean, default = False
True if a MARTINI forcefield, False otherwise.
RcutCoulomb_box_0 : int or float (>= 0), default = None
Sets a specific radius in box 0 where the short-range electrostatic
energy will be calculated (i.e., The distance to truncate the
short-range electrostatic energy in box 0.)
Note: if None, GOMC will default to the Rcut value
RcutCoulomb_box_1 : int or float (>= 0), default = None
Sets a specific radius in box 1 where the short-range electrostatic
energy will be calculated (i.e., The distance to truncate the
short-range electrostatic energy in box 0.)
Note: if None, GOMC will default to the Rcut value
Pressure : int or float (>= 0), default = 1.01325
The pressure in bar utilized for the NPT and GEMC_NPT simulations.
Rcut : int or float (>= 0 and RcutLow < Rswitch < Rcut), default = 10
Sets a specific radius in Angstroms that non-bonded interaction
energy and force will be considered and calculated using defined potential function.
The distance in Angstoms to truncate the LJ, Mie, or other VDW type potential at.
Note: Rswitch is only used when the "Potential" = SWITCH.
RcutLow : int or float (>= 0 and RcutLow < Rswitch < Rcut), default = 0
Sets a specific minimum possible distance in Angstroms that reject
any move that places any atom closer than specified distance.
The minimum possible distance between any atoms.
Sets a specific radius in Angstroms that non-bonded interaction
Note: Rswitch is only used when the "Potential" = SWITCH.
WARNING: When using a molecule that has charge atoms with non-bonded epsilon values of zero (i.e., water),
the RcutLow need to be greater than zero, typically 1 angstrom.
WARNING: When using the free energy calculations, RcutLow needs to be set to zero (RcutLow=0);
otherwise, the free energy calculations can produce results that are slightly off or wrong.
LRC : boolean, default = True
If True, the simulation considers the long range tail corrections for the
non-bonded VDW or dispersion interactions.
Note: In case of using SHIFT or SWITCH potential functions, LRC will be ignored.
IPC : boolean, default = False
If True, the simulation adds the impulse correction term to the pressure,
which considers to correct for the discontinuous Rcut potential
(i.e., a hard cutoff potential, meaning a potential without tail corrections)
the long range tail corrections for the non-bonded VDW or dispersion interactions.
If False, the impulse correction term to the pressure is not applied.
Note: This can not be used if LRC is True or the Potential is set to SWITCH, or SHIFT.
Exclude : str ["1-2", "1-3", or "1-4"], default = "1-3"
Note: In CHARMM force field, the 1-4 interaction needs to be considered.
Choosing "Excude 1-3", will modify 1-4 interaction based on 1-4 parameters
in parameter file. If a kind force field is used, where 1-4 interaction
needs to be ignored, such as TraPPE, either Exclude "1-4" needs to be
chosen or 1-4 parameter needs to be assigned to zero in the parameter file.
--- "1-2": All interaction pairs of bonded atoms, except the ones that
separated with one bond, will be considered and modified using 1-4
parameters defined in parameter file.
--- "1-3": All interaction pairs of bonded atoms, except the ones that
separated with one or two bonds, will be considered and modified using
1-4 parameters defined in parameter file.
--- "1-4": All interaction pairs of bonded atoms, except the ones that
separated with one, two or three bonds, will be considered using
non-bonded parameters defined in parameter file.
Potential : str, ["VDW", "EXP6", "SHIFT" or "SWITCH"], default = "VDW"
Defines the potential function type to calculate non-bonded dispersion
interaction energy and force between atoms.
--- "VDW": Non-bonded dispersion interaction energy and force
calculated based on n-6 (Lennard - Jones) equation. This
function will be discussed further in the Intermolecular energy
and Virial calculation section.
--- "EXP6": Non-bonded dispersion interaction energy and force calculated
based on exp-6 (Buckingham potential) equation.
--- "SHIFT": This option forces the potential energy to be zero at Rcut distance.
--- "SWITCH": This option smoothly forces the potential energy to be zero at
Rcut distance and starts modifying the potential at Rswitch
distance. Depending on force field type, specific potential
function will be applied.
Rswitch : int or float (>= 0 and RcutLow < Rswitch < Rcut), default = 9
Note: Rswitch is only used when the SWITCH function is used
(i.e., "Potential" = SWITCH). The Rswitch distance is in Angstrom. If the
“SWITCH” function is chosen, Rswitch needs to be defined, otherwise, the
program will be terminated. When using choosing "SWITCH" as potential function,
the Rswitch distance defines where the non-bonded interaction energy
modification is started, which is eventually truncated smoothly at Rcut
distance.
ElectroStatic : boolean, default = True
Considers the coulomb interactions or not. If True, coulomb interactions are
considered and false if not. Note: To simulate the polar molecule in MARTINI
force field, ElectroStatic needs to be turn on (i.e., True). The MARTINI force
field uses short-range coulomb interaction with constant Dielectric of 15.0.
Ewald : boolean, default = True
Considers the standard Ewald summation method for electrostatic calculations.
If True, Ewald summation calculation needs to be considered and false if not.
Note: By default, GOMC will set ElectroStatic to True if Ewald summation
method was used to calculate coulomb interaction.
CachedFourier : boolean, default = False
Considers storing the reciprocal terms for Ewald summation calculation in
order to improve the code performance. This option would increase the code
performance with the cost of memory usage. If True, to store reciprocal
terms of Ewald summation calculation and False if not.
Warning: Monte Carlo moves, such as MEMC-1, MEMC-2, MEMC-3,
IntraMEMC-1, IntraMEMC-2, and IntraMEMC-3 are not support with CachedFourier.
Tolerance : float (0.0 < float < 1.0), default = 1e-05
Sets the accuracy in Ewald summation calculation. Ewald separation parameter
and number of reciprocal vectors for the Ewald summation are determined
based on the accuracy parameter.
Dielectric : int or float (>= 0.0), default = 15
Sets dielectric value used in coulomb interaction when the Martini
force field is used. Note: In MARTINI force field, Dielectric needs to
be set to 15.0.
PressureCalc : list [bool , int (> 0)] or [bool , step_frequency],
default = [True, 10k] or [True , set via formula based on the number of RunSteps or 10k max]
Calculate the system pressure or not. bool = True, enables the pressure calculation
during the simulation, false disables the calculation. The int/step frequency sets the
frequency of calculating the pressure.
EqSteps : int (> 0), default = set via formula based on the number of RunSteps or 1M max
Sets the number of steps necessary to equilibrate the system.
Averaging will begin at this step.
Note: In GCMC simulations, the Histogram files will be outputed at EqSteps.
AdjSteps : int (> 0), default = set via formula based on the number of RunSteps or 1k max
Sets the number of steps per adjustment of the parameter associated with each move
(e.g. maximum translate distance, maximum rotation, maximum volume exchange, etc.).
VDWGeometricSigma: boolean, default = False
Use geometric mean, as required by OPLS force field, to combining
Lennard-Jones sigma parameters for different atom types.
If set to True, GOMC uses geometric mean to combine Lennard-Jones or VDW sigmas.
Note: The default setting of VDWGeometricSigma is false, which uses the arithmetic
mean when combining Lennard-Jones or VDW sigma parameters for different atom types.
useConstantArea : boolean, default = False
Changes the volume of the simulation box by fixing the cross-sectional
area (x-y plane). If True, the volume will change only in z axis,
If False, the volume of the box will change in a way to maintain the constant
axis ratio.
FixVolBox0 : boolean, default = False
Changing the volume of fluid phase (Box 1) to maintain the constant imposed
pressure and Temperature, while keeping the volume of adsorbed phase (Box 0) fixed.
Note: By default, GOMC will set useConstantArea to False if no value was set.
It means, the volume of the box will change in a way to maintain the constant
axis ratio.
ChemPot : dict {str (4 dig limit) , int or float}, default = None
The chemical potentials in GOMC units of energy, K.
There is a 4 character limit for the string/residue name since the PDB/PSF
files have a 4 character limitation and require and exact match in the conf file.
Note: These strings must match the residue in the psf and psb files or it will fail.
The name of the residues and their corresponding chemical potential must specified
for every residue in the system (i.e., {"residue_name" : chemical_potential}).
Note: IF 2 KEYS WITH THE SAME STRING/RESIDUE ARE PROVIDED, ONE WILL BE AUTOMATICALLY
OVERWRITTEN AND NO ERROR WILL BE THROWN IN THIS CONTROL FILE WRITER.
Example 1 (system with only water): {"H2O" : -4000}
Example 2 (system with water and ethanol): {"H2O" : -4000, "ETH" : -8000}
Fugacity : dict {str , int or float (>= 0)}, default = None
The fugacity in GOMC units of pressure, bar.
There is a 4 character limit for the string/residue name since the PDB/PSF
files have a 4 character limitation and require and exact match in the conf file.
Note: These strings must match the residue in the psf and psb files or it will fail.
The name of the residues and their corresponding fugacity must specified
for every residue in the system (i.e., {"residue_name" : fugacity}).
Note: IF 2 KEYS WITH THE SAME STRING/RESIDUE ARE PROVIDED, ONE WILL BE AUTOMATICALLY
OVERWRITTEN AND NO ERROR WILL BE THROWN IN THIS CONTROL FILE WRITER.
Example 1 (system with only water): {"H2O" : 1}
Example 2 (system with water and ethanol): {"H2O" : 0.5, "ETH" : 10}
CBMC_First : int (>= 0), default = 12
The number of CD-CBMC trials to choose the first atom position
(Lennard-Jones trials for first seed growth).
CBMC_Nth : int (>= 0), default = 10
The Number of CD-CBMC trials to choose the later atom positions
(Lennard-Jones trials for first seed growth).
CBMC_Ang : int (>= 0), default = 50
The Number of CD-CBMC bending angle trials to perform for geometry
(per the coupled-decoupled CBMC scheme).
CBMC_Dih : int (>= 0), default = 50
The Number of CD-CBMC dihedral angle trials to perform for geometry
(per the coupled-decoupled CBMC scheme).
OutputName : str (NO SPACES), , default = "Output_data", default = [True, 1M] or
[True , set via formula based on the number of RunSteps or 1M max]
The UNIQUE STRING NAME, WITH NO SPACES, which is used for the
output block average, PDB, and PSF file names.
CoordinatesFreq : list [bool , int (> 0)] or [Generate_data_bool , steps_per_data_output_int],
default = [True, 1M] or [True , set via formula based on the number of RunSteps or M max]
Controls output of PDB file (coordinates). If bool is True, this
enables outputting the coordinate files at the integer frequency
(set steps_per_data_output_int), while "False" disables outputting
the coordinates.
DCDFreq : list [bool , int (> 0)] or [Generate_data_bool , steps_per_data_output_int],
default = [True, 1M] or [True , set via formula based on the number of RunSteps or M max]
Controls output of DCD file (coordinates). If bool is True, this
enables outputting the coordinate files at the integer frequency
(set steps_per_data_output_int), while "False" disables outputting
the coordinates.
RestartFreq : list [bool , int (> 0)] or [Generate_data_bool , steps_per_data_output_int],
default = [True, 1M] or [True , set via formula based on the number of RunSteps or 1M max]
This creates the PDB and PSF (coordinate and topology) files for
restarting the system at the set steps_per_data_output_int (frequency)
If bool is True, this enables outputting the PDB/PSF restart files at the
integer frequency (set steps_per_data_output_int), while “false”
disables outputting the PDB/PSF restart files.
CheckpointFreq : list [bool , int (> 0)] or [Generate_data_bool , steps_per_data_output_int],
default = [True, 1M] or [True , set via formula based on the number of RunSteps or 1M max]
Controls the output of the last state of simulation at a specified step,
in a binary file format (checkpoint.dat). Checkpoint file contains the
following information in full precision:
(1) Last simulation step that saved into checkpoint file
(2) Simulation cell dimensions and angles
(3) Maximum amount of displacement (Å), rotation (δ), and volume (Å^3)
that is used in the Displacement, Rotation, MultiParticle, and Volume moves
(4) Number of Monte Carlo move trial and acceptance
(5) All molecule’s coordinates
(6) Random number sequence
If bool is True, this enables outputing the checkpoint file at the
integer frequency (set steps_per_data_ouput_int),
while "False" disables outputting the checkpoint file.
ConsoleFreq : list [bool , int (> 0)] or [Generate_data_bool , steps_per_data_output_int],
default = [True, 10k] or [True , set via formula based on the number of RunSteps or 10k max]
Controls the output to the "console" or log file, which prints the
acceptance statistics, and run timing info. In addition, instantaneously-selected
thermodynamic properties will be output to this file. If bool is True,
this enables outputting the console data at the integer frequency
(set steps_per_data_output_int), while "False" disables outputting the console
data file.
BlockAverageFreq : list [bool , int (> 0)] or [Generate_data_bool , steps_per_data_output_int],
default = [True, 10k] or [True , set via formula based on the number of RunSteps or 10k max]
Controls the block averages output of selected thermodynamic properties.
Block averages are averages of thermodynamic values of interest for chunks of the
simulation (for post-processing of averages or std. dev. in those values).
If bool is True, this enables outputting the block averaging data/file at the
integer frequency (set steps_per_data_output_int), while "False"
disables outputting the block averaging data/file.
HistogramFreq : list [bool , int (> 0)] or [Generate_data_bool , steps_per_data_output_int],
default = [True, 10k] or [True , set via formula based on the number of RunSteps or 10k max]
Controls the histograms. Histograms are a binned listing of observation frequency
for a specific thermodynamic variable. In the GOMC code, they also control the output
of a file containing energy/molecule samples, which is only used for the "GCMC"
ensemble simulations for histogram reweighting purposes. If bool is True, this
enables outputting the data to the histogram data at the integer frequency
(set steps_per_data_output_int), while "False" disables outputting the histogram
data.
DistName : str (NO SPACES), default = "dis"
Short phrase which will be combined with RunNumber and RunLetter
to use in the name of the binned histogram for molecule distribution.
HistName : str (NO SPACES), default = "his"
Short phrase, which will be combined with RunNumber and RunLetter,
to use in the name of the energy/molecule count sample file.
RunNumber : int ( > 0 ), default = 1
Sets a number, which is a part of DistName and HistName file name.
RunLetter : str (1 alphabetic character only), default = "a"
Sets a letter, which is a part of DistName and HistName file name.
SampleFreq : int ( > 0 ), default = 500
The number of steps per histogram sample or frequency.
OutEnergy : [bool, bool], default = [True, True]
The list provides the booleans to [block_averages_bool, console_output_bool].
This outputs the energy data into the block averages and console output/log
OutPressure : [bool, bool], default = [True, True]
The list provides the booleans to [block_averages_bool, console_output_bool].
This outputs the pressure data into the block averages and console output/log files.
OutMolNum : [bool, bool], default = [True, True]
The list provides the booleans to [block_averages_bool, console_output_bool].
This outputs the number of molecules data into the block averages and console
output/log files.
OutDensity : [bool, bool], default = [True, True]
The list provides the booleans to [block_averages_bool, console_output_bool].
This outputs the density data into the block averages and console output/log files.
OutVolume : [bool, bool], default = [True, True]
The list provides the booleans to [block_averages_bool, console_output_bool].
This outputs the volume data into the block averages and console output/log files.
OutSurfaceTension : [bool, bool], default = [False, False]
The list provides the booleans to [block_averages_bool, console_output_bool].
This outputs the surface tension data into the block averages and console
output/log files.
FreeEnergyCalc : list [bool , int (> 0)] or [Generate_data_bool , steps_per_data_output_int],
default = None
bool = True enabling free energy calculation during the simulation, false disables
the calculation. The int/step frequency sets the frequency of calculating the free energy.
WARNING: When using the free energy calculations, RcutLow needs to be set to zero (RcutLow=0);
otherwise, the free energy calculations can produce results that are slightly off or wrong.
MoleculeType : list [str , int (> 0)] or ["residue_name" , residue_ID], default = None
The user must set this variable as there is no working default.
Note: ONLY 4 characters can be used for the string (i.e., "residue_name").
Sets the solute molecule kind (residue name) and molecule number (residue ID),
which absolute solvation free will be calculated for.
InitialState : int (>= 0), default = None
The user must set this variable as there is no working default.
The index of LambdaCoulomb and LambdaVDW vectors. Sets the index of the
LambdaCoulomb and LambdaVDW vectors, to determine the simulation lambda value for
VDW and Coulomb interactions.
WARNING : This must an integer within the vector count of the LambdaVDW and LambdaCoulomb,
in which the counting starts at 0.
LambdaVDW : list of floats (0 <= floats <= 1), default = None
The user must set this variable as there is no working default (default = {}).
Lambda values for VDW interaction in ascending order. Sets the intermediate
lambda states to which solute-solvent VDW interactions are scaled.
WARNING : This list must be the same length as the "LambdaCoulomb" list length.
WARNING : All lambda values must be stated in the ascending order,
starting with 0.0 and ending with 1.0; otherwise, the program will terminate.
Example of ascending order 1: [0.0, 0.1, 1.0]
Example of ascending order 2: [0.0, 0.1, 0.2, 0.4, 0.9, 1.0]
LambdaCoulomb : list of floats (0 <= floats <= 1), default = None
Lambda values for Coulombic interaction in ascending order. Sets the intermediate
lambda states to which solute-solvent Coulombic interactions are scaled.
GOMC defauts to the "LambdaVDW" values for the Coulombic interaction
if no "LambdaCoulomb" variable is set.
WARNING : This list must be the same length as the "LambdaVDW" list length.
WARNING : All lambda values must be stated in the ascending order,
starting with 0.0 and ending with 1.0; otherwise, the program will terminate.
Example of ascending order 1: [0.0, 0.1, 1.0]
Example of ascending order 2: [0.0, 0.1, 0.2, 0.4, 0.9, 1.0]
ScaleCoulomb : bool, default = False
Determines to scale the Coulombic interaction non-linearly
(soft-core scheme) or not.
True if the Coulombic interaction needs to be scaled non-linearly.
False if the Coulombic interaction needs to be scaled linearly.
ScalePower : int (>= 0), default = 2
The p value in the soft-core scaling scheme, where the distance
between solute and solvent is scaled non-linearly.
ScaleAlpha : int or float (>= 0), default = 0.5
The alpha value in the soft-core scaling scheme, where the distance
between solute and solvent is scaled non-linearly.
MinSigma : int or float (>= 0), default = 3
The minimum sigma value in the soft-core scaling scheme, where the
distance between solute and solvent is scaled non-linearly.
DisFreq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.15, 'NPT': 0.15, 'GEMC_NVT': 0.2, 'GEMC_NPT': 0.19, 'GCMC': 0.15}
Fractional percentage at which the displacement move will occur
(i.e., fraction of displacement moves).
RotFreq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.15, 'NPT': 0.15, 'GEMC_NVT': 0.2, 'GEMC_NPT': 0.2, 'GCMC': 0.15}
Fractional percentage at which the rotation move will occur.
(i.e., fraction of rotation moves).
IntraSwapFreq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.3, 'NPT': 0.29, 'GEMC_NVT': 0.1, 'GEMC_NPT': 0.1, 'GCMC': 0.1}
Fractional percentage at which the molecule will be removed from a
box and inserted into the same box using coupled-decoupled configurational-bias
algorithm. (i.e., fraction of intra-molecule swap moves).
SwapFreq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.2, 'GEMC_NPT': 0.2, 'GCMC': 0.35}
For Gibbs and Grand Canonical (GC) ensemble runs only: Fractional
percentage at which molecule swap move will occur using coupled-decoupled
configurational-bias. (i.e., fraction of molecule swaps moves).
RegrowthFreq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.3, 'NPT': 0.3, 'GEMC_NVT': 0.2, 'GEMC_NPT': 0.2, 'GCMC': 0.15}
Fractional percentage at which part of the molecule will be deleted and
then regrown using coupled- decoupled configurational-bias algorithm
(i.e., fraction of molecular growth moves).
CrankShaftFreq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.1, 'NPT': 0.1, 'GEMC_NVT': 0.1, 'GEMC_NPT': 0.1, 'GCMC': 0.1}
Fractional percentage at which crankshaft move will occur.
In this move, two atoms that are forming angle or dihedral are selected
randomly and form a shaft. Then any atoms or group that are within these
two selected atoms, will rotate around the shaft to sample intra-molecular
degree of freedom (i.e., fraction of crankshaft moves).
VolFreq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.01, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.01, 'GCMC': 0.0}
For isobaric-isothermal (NPT) ensemble and Gibbs ensemble
(GEMC_NPT and GEMC_NVT) runs only: Fractional percentage at
which a volume move will occur (i.e., fraction of Volume moves).
MultiParticleFreq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.0, 'GCMC': 0.0}
Fractional percentage at which multi-particle move will occur.
In this move, all molecules in the selected simulation box will be rigidly
rotated or displaced simultaneously, along the calculated torque or force
respectively (i.e., fraction of multi-particle moves).
IntraMEMC-1Freq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.0, 'GCMC': 0.0}
Fractional percentage at which specified number of small molecule kind will be
exchanged with a specified large molecule kind in defined sub-volume within
same simulation box. This move need additional information such as
ExchangeVolumeDim, ExchangeRatio, ExchangeSmallKind, and ExchangeLargeKind.
MEMC-1Freq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.0, 'GCMC': 0.0}
Fractional percentage at which specified number of small molecule kind will
be exchanged with a specified large molecule kind in defined sub-volume,
between simulation boxes. This move need additional information such as
ExchangeVolumeDim, ExchangeRatio, ExchangeSmallKind, and ExchangeLargeKind.
IntraMEMC-2Freq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.0, 'GCMC': 0.0}
Fractional percentage at which specified number of small molecule kind
will be exchanged with a specified large molecule kind in defined sub-volume
within same simulation box. Backbone of small and large molecule kind will be
used to insert the large molecule more efficiently. This move need additional
information such as ExchangeVolumeDim, ExchangeRatio, ExchangeSmallKind,
ExchangeLargeKind, SmallKindBackBone, and LargeKindBackBone.
MEMC-2Freq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.0, 'GCMC': 0.0}
Fractional percentage at which specified number of small molecule kind will be
exchanged with a specified large molecule kind in defined sub-volume,
between simulation boxes. Backbone of small and large molecule kind will be
used to insert the large molecule more efficiently. This move need additional
information such as ExchangeVolumeDim, ExchangeRatio, ExchangeSmallKind,
ExchangeLargeKind, SmallKindBackBone, and LargeKindBackBone.
IntraMEMC-3Freq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.0, 'GCMC': 0.0}
Fractional percentage at which specified number of small molecule kind will be
exchanged with a specified large molecule kind in defined sub-volume within same
simulation box. Specified atom of the large molecule kind will be used to insert
the large molecule using coupled-decoupled configurational-bias. This move need
additional information such as ExchangeVolumeDim, ExchangeRatio, ExchangeSmallKind,
ExchangeLargeKind, and LargeKindBackBone.
MEMC-3Freq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.0, 'GCMC': 0.0}
Fractional percentage at which specified number of small molecule kind will be
exchanged with a specified large molecule kind in defined sub-volume,
between simulation boxes. Specified atom of the large molecule kind will be
used to insert the large molecule using coupled-decoupled configurational-bias.
This move need additional information such as ExchangeVolumeDim,
ExchangeRatio, ExchangeSmallKind, ExchangeLargeKind, and LargeKindBackBone.
TargetedSwapFreq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.0, 'GCMC': 0}
Fractional percentage at which targeted swap move will occur.
Note: This is only usable with the 'GCMC', 'GEMC_NVT', and 'GEMC_NPT' ensembles.
Note: This is used in conjunction with the "TargetedSwap_DataInput" variables.
IntraTargetedSwapFreq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.0, 'GCMC': 0}
Note: This is used in conjunction with the "TargetedSwap_DataInput" variables.
TargetedSwap_DataInput : dict, default=None
A dictionary which can contain one or several targeted swap regions, each designated with
their own tag ID number (aka, subvolume number).
A few examples for TargetedSwap_DataInput input is provided below.
NOTE: MULTIPLE SIMULATION BOXES CAN BE UTILIZED BY SETTING MULTIPLE tag_ID_integer VALUES (INTEGERS VALUES),
NOTE: THIS IS REQUIRED WHEN USING EITHER THE "TargetedSwapFreq" OR "IntraTargetedSwapFreq" MC MOVES.
WARNING: THE tag_ID_integer VALUES MUST BE UNIQUE FOR EACH SUBVOLUME,
OR THE DICTIONARY WILL OVERWRITE THE PREVIOUS SUBVOLUME (tag_ID_integer) SECTION
WITH THE CURRENT tag_ID_integer AND ITS RESPECTIVE VALUES.
Example 1
input_variables_dict={"TargetedSwap_DataInput": {tag_ID_integer: {"SubVolumeType": "dynamic",
"SubVolumeBox": 0, "SubVolumeCenterList": ['0-10', 12, 15, '22-40'], "SubVolumeDim": [1, 2, 3],
"SubVolumeResidueKind": "ALL", "SubVolumeRigidSwap": False, "SubVolumePBC": "XY",
"SubVolumeChemPot": {"MET": -21, "met": -31}}}
Example 2
input_variables_dict={"TargetedSwap_DataInput": {tag_ID_integer: {"SubVolumeType": "static",
"SubVolumeBox": 0, "SubVolumeCenter": [1, 12, 15], "SubVolumeDim": [3, 3, 3],
"SubVolumeResidueKind": ["MET", "met"], "SubVolumeRigidSwap": False, "SubVolumePBC": "XYZ",
"SubVolumeFugacity": {"MET": 0.1, "met": 1}}}
The details of each key and value for the "TargetedSwap_DataInput" are provided below.
--- "SubVolumeType" : str ("static" or "dynamic"), No default is provided.
The type of targeted swap box (subvolume) that will be created.
The "static" type will maintain the box (subvolume) in a fixed location during the whole simulation,
with the center of the box determined by the coordinates set in the
"SubvolumeCenter" parameter.
The "dynamic" type will allow for dynamic movement of the box (subvolume) based atom indices
provided in the SubvolumeCenterList variable. For the "dynamic" type, the user must define a
list of atom indices using "SubVolumeCenterList" keyword; the geometric center of the
provided atom indices will be used as the center of subVolume. User must ensure that the
atoms defined in the atom list remain in the simulation box (by setting the Beta value to 2 in PDB file).
--- "SubVolumeBox" : int (0 or 1), No default is provided.
The simulation box in which the targeted swap subvolume will be applied.
NOTE: Only box zero (0) can be used for the GCMC, NPT, and NVT ensembles.
--- "SubVolumeCenter" : list of three (3) int or float, [x-axis, y-axis, z-axis], No default is provided.
The simulation box is centered on this x, y, and z-axis points (in Angstroms), which is only
utilized when "SubVolumeType" is set to "static".
--- "SubVolumeCenterList" : list of int and/or str (>=0), [atom_index, ..., atom_index], No default is provided.
The simulation box subVolume is centered on the geometric center of the provided atom indices, which is
only used when the "SubVolumeType" is set to "dynamic". For example, [0-10', 12, 15] means that
atom indices 0 to 10, 12 and 15 are used as the geometric center of the simulation box subVolume.
NOTE: THE ATOM INDICES RANGES MUST BE A STRING IN THE FORM '2-20', WITH THE FIRST ATOM INDICES BEING
SMALLER THAN THE SECOND (i.e, 'a-b', where a < b). ALL SINGULAR ATOM INDICES MUST BE INTEGERS.
NOTE: THE SAME ATOM INDICES CAN BE USED 2, 3 OR X TIMES TO WEIGHT that atom 2, 3, OR X TIMES MORE
IN THE GEOMETRIC CENTERING CALCULATION.
NOTE: THE ATOM INDICES START AT ZERO (0), WHILE THE PDB AND PSF FILES START AT ONE (1).
THEREFORE, YOU NEED TO BE CAREFUL WHEN SETTING THE INDICES FROM THE PDB OR PSF VALUES AS THEY ARE
ONE (1) NUMBER OFF.
--- "SubVolumeDim" : list of three (3) int or float (>0), [x-axis, y-axis, z-axis], No default is provided.
This sets the size of the simulation box (subVolume) in the x, y, and z-axis (in Angstroms).
--- "SubVolumeResidueKind" : str or list of str, "ALL" or "residue"
or ["ALL"] or [residue_str, ..., residue_str], No default is provided.
The residues that will be used in the "TargetedSwap_DataInput" subvolume.
Alternatively, the user can just set the value to ["ALL"] or "ALL", which covers all the residues.
--- "SubVolumeRigidSwap" : bool, default = True
Choose whether to use a rigid or flexible molecule insertion using CD-CBMC for the subVolume.
True uses a rigid molecule insertion, while False uses a flexible molecule insertion
--- "SubVolumePBC" : str ('X', 'XY', 'XZ', 'XYZ', 'Y', 'YZ', or 'Z'), default = 'XYZ'.
Apply periodic boundary condition (PBC) in selected axes for the subVolume.
Example 1, 'X' applies PBC only in the X axis. Example 2, 'XY' applies PBC only in the X and Y axes.
Example 3, 'XYZ' applies PBC in the X, Y, and Z axes.
--- "SubVolumeChemPot" : dict {str (4 dig limit) , int or float}, No default is provided.
The chemical potentials in GOMC units of energy, K. If no SubVolumeChemPot is provided
the default system chemical potential values are used.
There is a 4 character limit for the string/residue name since the PDB/PSF
files have a 4 character limitation and require an exact match in the conf file.
Note: These strings must match the residue in the psf and psb files or it will fail.
The name of the residues and their corresponding chemical potential must be specified
for every residue in the system (i.e., {"residue_name" : chemical_potential}).
Note: THIS IS ONLY REQUIRED FOR THE GCMC ENSEMBLE.
Note: IF 2 KEYS WITH THE SAME STRING/RESIDUE ARE PROVIDED, ONE WILL BE AUTOMATICALLY
OVERWRITTEN AND NO ERROR WILL BE THROWN IN THIS CONTROL FILE WRITER.
Note: ONLY THE "SubVolumeChemPot" OR THE "SubVolumeFugacity" CAN BE USED FOR ALL THE
TARGET SWAP BOXES (SUBVOLUMES). IF MIX OF "SubVolumeChemPot" AND "SubVolumeFugacity" ARE
USED THE CONTROL FILE WRITER WILL THROW AN ERROR.
--- "SubVolumeFugacity" : dict {str , int or float (>= 0)}, No default is provided.
The fugacity in GOMC units of pressure, bar. If no "SubVolumeFugacity" is provided
the default system fugacity values are used.
There is a 4 character limit for the string/residue name since the PDB/PSF
files have a 4 character limitation and require an exact match in the conf file.
Note: These strings must match the residue in the psf and psb files or it will fail.
The name of the residues and their corresponding fugacity must be specified
for every residue in the system (i.e., {"residue_name" : fugacity}).
Note: THIS IS ONLY REQUIRED FOR THE GCMC ENSEMBLE.
Note: IF 2 KEYS WITH THE SAME STRING/RESIDUE ARE PROVIDED, ONE WILL BE AUTOMATICALLY
OVERWRITTEN AND NO ERROR WILL BE THROWN IN THIS CONTROL FILE WRITER.
Note: ONLY THE "SubVolumeChemPot" OR THE "SubVolumeFugacity" CAN BE USED FOR ALL THE
TARGET SWAP BOXES (SUBVOLUMES). IF MIX OF "SubVolumeChemPot" AND "SubVolumeFugacity" ARE
USED THE CONTROL FILE WRITER WILL THROW AN ERROR.
ExchangeVolumeDim : list of 3 floats or integers or [X-dimension, Y-dimension, Z-dimension],
default = [1.0, 1.0, 1.0]
To use all variations of MEMC and Intra-MEMC Monte Carlo moves, the exchange
subvolume must be defined. The exchange sub-volume is defined as an orthogonal box
with x, y, and z-dimensions, where small molecule/molecules kind will be selected
from to be exchanged with a large molecule kind.
Note: Currently, the X and Y dimension cannot be set independently (X = Y = max(X, Y)).
Note: A heuristic for setting good values of the x, y, and z-dimensions is to use
the geometric size of the large molecule plus 1-2 Å in each dimension.
Note: In case of exchanging 1 small molecule kind with 1 large molecule kind in
IntraMEMC-2, IntraMEMC-3, MEMC-2, MEMC-3 Monte Carlo moves, the sub-volume
dimension has no effect on acceptance rate.
MEMC_DataInput : nested lists, default = None
Enter data as a list with some sub-lists as follows:
[[ExchangeRatio_int (> 0), ExchangeLargeKind_str,
[LargeKindBackBone_atom_1_str_or_NONE, LargeKindBackBone_atom_2_str_or_NONE ],
ExchangeSmallKind_str, [SmallKindBackBone_atom_1_str_or_NONE, SmallKindBackBone_atom_2_str_or_NONE ]],
...,
[ExchangeRatio_int (> 0), ExchangeLargeKind_str,
[LargeKindBackBone_atom_1_str_or_NONE, LargeKindBackBone_atom_2_str_or_NONE ],
ExchangeSmallKind_str, [SmallKindBackBone_atom_1_str_or_NONE, SmallKindBackBone_atom_2_str_or_NONE ].
NOTE: CURRENTLY ALL THESE INPUTS NEED TO BE SPECIFIED, REGARDLESS OF THE MEMC TYPE
SELECTION. IF THE SmallKindBackBone or LargeKindBackBone IS NOT REQUIRED FOR THE
MEMC TYPE, None CAN BE USED IN PLACE OF A STRING.
Note: These strings must match the residue in the psf and psb files or it will fail.
It is recommended that the user print the Charmm object psf and pdb files
and review the residue names that match the atom name before using the in
the MEMC_DataInput variable input.
Note: see the below data explanations for the ExchangeRatio, ExchangeSmallKind,
ExchangeLargeKind, LargeKindBackBone, SmallKindBackBone.
Example 1 (MEMC-1) : [ [1, 'WAT', [None, None], 'wat', [None, None]] ,
[1, 'WAT', [None, None], 'wat', [None, None]]
Example 2 (MEMC-2): [ [1, 'WAT', ['O1', 'H1'], 'wat', ['O1', 'H1' ]] ,
[1, 'WAT', ['H1', 'H2'], 'wat', ['H1', 'H2' ]]
Example 3 (MEMC-3) : [ [2, 'WAT', 'O1', 'H1'], 'wat', [None, None]] ,
[2, 'WAT', ['H1', 'H2'], 'wat', [None, None]]
--- ExchangeRatio = MEMC parameters (all ensembles): int (> 0), default = None
The Ratio of exchanging small molecule/molecules with 1 large molecule.
To use all variation of MEMC and Intra-MEMC Monte Carlo moves,
the exchange ratio must be defined. The exchange ratio defines how
many small molecule will be exchanged with 1 large molecule. For each
large-small molecule pairs, one exchange ratio must be defined.
--- ExchangeSmallKind = MEMC parameters (all ensembles): str, default = None
The small molecule kind (resname) to be exchanged.
Note: ONLY 4 characters can be used for the strings.
To use all variation of MEMC and Intra-MEMC Monte Carlo moves,
the small molecule kind to be exchanged with a large molecule
kind must be defined. Multiple small molecule kind can be specified.
--- ExchangeLargeKind = MEMC parameters (all ensembles): str, default = None
The large molecule kind (resname) to be exchanged.
Note: ONLY 4 characters can be used for the strings.
To use all variation of MEMC and Intra-MEMC Monte Carlo moves,
the large molecule kind to be exchanged with small molecule
kind must be defined. Multiple large molecule kind can be specified.
--- LargeKindBackBone = MEMC parameters (all ensembles): list [str, str] or [None, None], default = None
Note: ONLY 4 characters can be used for the strings.
The [None, None] values can only be used if that MEMC type does
not require them. The strings for the the atom name 1 and atom name 2
that belong to the large molecule’s backbone
(i.e., [str_for_atom_name_1, str_for_atom_name_2])
To use MEMC-2, MEMC-3, IntraMEMC-2, and IntraMEMC-3 Monte Carlo moves, the
large molecule backbone must be defined. The backbone of the molecule is defined
as a vector that connects two atoms belong to the large molecule. The large
molecule backbone will be used to align the sub-volume in MEMC-2 and IntraMEMC-2
moves, while in MEMC-3 and IntraMEMC-3 moves, it uses the atom name to start
growing the large molecule using coupled-decoupled configurational-bias. For
each large-small molecule pairs, two atom names must be defined.
Note: all atom names in the molecule must be unique.
Note: In MEMC-3 and IntraMEMC-3 Monte Carlo moves, both atom names must be same,
otherwise program will be terminated.
Note: If the large molecule has only one atom (mono atomic molecules),
same atom name must be used for str_for_atom_name_1 and str_for_atom_name_2
of the LargeKindBackBone.
--- SmallKindBackBone = MEMC parameters (all ensembles): list [str, str] or [None, None], default = None
Note: ONLY 4 characters can be used for the strings.
The [None, None] values can only be used if that MEMC type does not
require them. The strings for the the atom name 1 and atom name 2 that
belong to the small molecule’s backbone
(i.e., [str_for_atom_name_1, str_for_atom_name_2])
To use MEMC-2, and IntraMEMC-2 Monte Carlo moves, the small molecule backbone
must be defined. The backbone of the molecule is defined as a vector that
connects two atoms belong to the small molecule and will be used to align the
sub-volume. For each large-small molecule pairs, two atom names must be defined.
Note: all atom names in the molecule must be unique.
Note: If the small molecule has only one atom (mono atomic molecules), same atom
name must be used str_for_atom_name_1 and str_for_atom_name_2
of the SmallKindBackBone.
# *******************************************************************
# input_variables_dict options (keys and values) - (end)
# Note: the input_variables_dict keys are also attributes
# *******************************************************************
Attributes
----------
input_error : bool
This error is typically incurred from an error in the user input values.
However, it could also be due to a bug, provided the user is inputting
the data as this Class intends.
all_failed_input_List : list
A list of all the inputs that failed, but there may be some inputs that
are not possible to put on this list.
ensemble_typ : str, ['NVT', 'NPT', 'GEMC_NPT', 'GCMC-NVT', 'GCMC']
The ensemble type of the simulation.
RunSteps : int (>0), must be an integer greater than zero.
Sets the total number of simulation steps.
Temperature : float or int (>0), must be an integer greater than zero.
Temperature of system in Kelvin (K)
ff_psf_pdb_file_directory : str (optional), default=None (i.e., the current directory).
The full or relative directory added to the force field, psf, and pdb
file names, created via the Charmm object.
check_input_files_exist : bool, (default=True)
Check if the force field, psf, and pdb files exist.
If the files are checked and do not exist, the writer will throw a ValueError.
True, check if the force field, psf, and pdb files exist.
False, do not check if the force field, psf, and pdb files exist.
Restart : boolean, default = False
Determines whether to restart the simulation from restart file
(``*_restart.pdb`` and ``*_restart.psf``) or not.
RestartCheckpoint : boolean, default = False
Determines whether to restart the simulation with the checkpoint
file (checkpoint.dat) or not. Restarting the simulation with checkpoint.dat
would result in an identical outcome, as if previous simulation was continued.
Parameters : str, (default=None)
Override all other force field directory and filename input with the correct extension (.inp or .par).
Note: the default directory is the current directory with the Charmm object file name.
Coordinates_box_0 : str, (default=None)
Override all other box 0 pdb directory and filename inputs with the correct extension.
Note: the default directory is the current directory with the Charmm object file name.
Structure_box_0 : str, (default=None)
Override all other box 0 psf directory and filename inputs with the correct extension.
Note: the default directory is the current directory with the Charmm object file name.
Coordinates_box_1 : str, (default=None)
Override all other box 1 pdb directory and filename inputs with the correct extension.
Note: the default directory is the current directory with the Charmm object file name.
Structure_box_1 : str, (default=None)
Override all other box 1 psf directory and filename inputs with the correct extension.
Note: the default directory is the current directory with the Charmm object file name.
binCoordinates_box_0 : str, (default=None)
The box 0 binary coordinate file is used only for restarting a GOMC simulation,
which provides increased numerical accuracy.
extendedSystem_box_0 : str, (default=None)
The box 0 vectors and origin file is used only for restarting a GOMC simulation.
binVelocities_box_0 : str, (default=None)
The box 0 binary velocity file is used only for restarting a GOMC simulation,
which provides increased numerical accuracy. These velocities are only passed thru
GOMC since Monte Carlo simulations do not utilize any velocity information.
binCoordinates_box_1 : str, (default=None)
The box 1 binary coordinate file is used only for restarting a GOMC simulation,
which provides increased numerical accuracy.
extendedSystem_box_1 : str, (default=None)
The box 1 vectors and origin file is used only for restarting a GOMC simulation.
binVelocities_box_1 : str, (default=None)
The box 1 binary velocity file is used only for restarting a GOMC simulation,
which provides increased numerical accuracy. These velocities are only passed thru
GOMC since Monte Carlo simulations do not utilize any velocity information.
input_variables_dict: dict, default = None
These input variables are optional and override the default settings.
Changing these variables likely required for more advanced systems.
The details of the acceptable input variables for the selected
ensembles can be found by running the code below in python,
>>> print_valid_ensemble_input_variables('GCMC', description = True)
which prints the input_variables with their subsection description
for the selected 'GCMC' ensemble (other ensembles can be set as well).
Example : input_variables_dict = {'PRNG' : 123,
'ParaTypeCHARMM' : True }
conf_filename : str
The name of the GOMC contol file, which will be created. The extension
of the GOMC control file can be .conf, or no extension can be provided.
If no extension is provided, this writer will automatically add the
.conf extension to the provided string.
box_0_vectors : numpy.ndarray, [[float float float], [float float float], [float float float]]
Three (3) sets vectors for box 0 each with 3 float values, which represent
the vectors for the Charmm-style systems (units in Angstroms (Ang))
box_1_vectors : numpy.ndarray, [[float float float], [float float float], [float float float]]
Three (3) sets vectors for box 1 each with 3 float values, which represent
the vectors for the Charmm-style systems (units in Angstroms (Ang))
coul_1_4 : float or int
The non-bonded 1-4 coulombic scaling factor, which is the
same for all the residues/molecules, regardless if
differenct force fields are utilized.
residues : list, [str, ..., str]
Labels of unique residues in the Compound. Residues are assigned by
checking against Compound.name. Only supply residue names as 4 character
strings, as the residue names are truncated to 4 characters to fit in the
psf and pdb file.
all_res_unique_atom_name_dict : dict, {str : [str, ..., str]}
A dictionary that provides the residue names (keys) and a list
of the unique atom names in the residue (value), for the
combined structures (box 0 and box 1 (if supplied)).
any input_variables_dict key : varies (see each input_variables_dict key and value)
Any of the input variables keys is also an Attribute and can be called
the same way. Please see the input_variables_dict keys in the
Parameters section above for all the available attributes.
Notes
-------
The user input variables (input_variables_dict) and the specific
ensembles.
The details of the required inputs for the selected
ensembles can be found by running this python workbook,
>>> print_valid_required_input_variables('NVT', description = True)
which prints the required inputs with their subsection description
for the selected 'NVT' ensemble (other ensembles can be set as well).
The details of the input variables for the selected
ensembles can be found by running this python workbook,
>>> print_valid_ensemble_input_variables('NPT', description = True)
which prints the input variables with their subsection description
for the selected 'NPT' ensemble (other ensembles can be set as well).
Note: The box units imported are in nm (standard MoSDeF units).
The units for this writer are auto-scaled to Angstroms, so they
can be directly used in the GOMC or NAMD engines.
Note: all of the move types are not available in for every ensemble.
Note: all of the move fractions must sum to 1, or the control file
writer will fail.
The input variables (input_variables_dict) and text extracted with permission from
the GOMC manual version 2.60. Some of the text was modified from its original version.
Cite: Potoff, Jeffrey; Schwiebert, Loren; et. al. GOMC Documentation.
https://raw.githubusercontent.com/GOMC-WSU/GOMC/master/GOMC_Manual.pdf, 2021.
"""
def __init__(
self,
charmm_object,
ensemble_type,
RunSteps,
Temperature,
ff_psf_pdb_file_directory=None,
check_input_files_exist=True,
Restart=False,
RestartCheckpoint=False,
ExpertMode=False,
Parameters=None,
Coordinates_box_0=None,
Structure_box_0=None,
Coordinates_box_1=None,
Structure_box_1=None,
binCoordinates_box_0=None,
extendedSystem_box_0=None,
binVelocities_box_0=None,
binCoordinates_box_1=None,
extendedSystem_box_1=None,
binVelocities_box_1=None,
input_variables_dict=None,
):
# set this to check and see if all the input pass
self.input_error = False
# set this to check and see if all the input pass
self.all_failed_input_List = []
# Check if charmm_object is really a Charmm() object
if not isinstance(charmm_object, mf_charmm.Charmm):
self.input_error = True
print_error_message = (
"ERROR: The variable supplied is a ({}), not a charmm_object ({})"
"".format(type(charmm_object), type(mf_charmm.Charmm))
)
raise TypeError(print_error_message)
# check ensemble is a correct type
if ensemble_type in ["GEMC_NVT", "GEMC-NVT"]:
ensemble_type = "GEMC_NVT"
elif ensemble_type in ["GEMC_NPT", "GEMC-NPT"]:
ensemble_type = "GEMC_NPT"
print("INFO: ensemble_type = " + str(ensemble_type))
if ensemble_type in ["NPT", "NVT", "GCMC", "GEMC_NVT", "GEMC_NPT"]:
self.ensemble_type = ensemble_type
print(
"INFO: All the ensemble (ensemble_type) input passed the initial error checking"
)
else:
self.input_error = True
print_error_message = (
"ERROR: The ensemble type selection of '{}' is not a valid ensemble option. "
"Please choose the 'NPT', 'NVT', 'GEMC_NVT', 'GEMC_NPT', or 'GCMC' "
"ensembles".format(ensemble_type)
)
raise ValueError(print_error_message)
# check if check_input_files_exist is a boolean
_check_if_bool("check_input_files_exist", check_input_files_exist)
# set and check valid inputs for the Restart attribute
_check_if_bool("Restart", Restart)
self.Restart = Restart
# set and check valid inputs for the RestartCheckpoint attribute
_check_if_bool("RestartCheckpoint", RestartCheckpoint)
self.RestartCheckpoint = RestartCheckpoint
# set ExpertMode
_check_if_bool("ExpertMode", ExpertMode)
self.ExpertMode = ExpertMode
self.binCoordinates_box_0 = binCoordinates_box_0
self.extendedSystem_box_0 = extendedSystem_box_0
self.binVelocities_box_0 = binVelocities_box_0
self.binCoordinates_box_1 = binCoordinates_box_1
self.extendedSystem_box_1 = extendedSystem_box_1
self.binVelocities_box_1 = binVelocities_box_1
# check if the binary restart files are provided correctly
if self.Restart and self.ensemble_type in ["NVT", "NPT"]:
if (
self.binCoordinates_box_0 is not None
or self.extendedSystem_box_0 is not None
) and (
self.binCoordinates_box_0 is None
or self.extendedSystem_box_0 is None
):
print_error_message = (
"ERROR: To restart a simulation with the binary files both the coor and "
"xsc files for box 0 must be provided."
)
raise ValueError(print_error_message)
elif self.binVelocities_box_0 is not None and (
self.binCoordinates_box_0 is None
or self.extendedSystem_box_0 is None
):
print_error_message = (
'ERROR: To restart a "NVT", "NPT" simulation with the '
"velocity binary files, the velocity files for box 0 "
"must be provided."
)
raise ValueError(print_error_message)
if self.Restart is True and self.ensemble_type in [
"GEMC_NPT",
"GEMC_NVT",
"GCMC",
]:
if (
self.binCoordinates_box_0 is not None
or self.extendedSystem_box_0 is not None
or self.binCoordinates_box_1 is not None
or self.extendedSystem_box_1 is not None
) and (
self.binCoordinates_box_0 is None
or self.extendedSystem_box_0 is None
or self.binCoordinates_box_1 is None
or self.extendedSystem_box_1 is None
):
print_error_message = (
"ERROR: To restart a simulation with the binary files both the coor and "
"xsc files for box 0 and box 1 must be provided."
)
raise ValueError(print_error_message)
elif (
self.binVelocities_box_0 is not None
or self.binVelocities_box_1 is not None
) and (
self.binVelocities_box_0 is None
or self.binVelocities_box_1 is None
):
print_error_message = (
'ERROR: To restart a "GEMC_NPT", "GEMC_NVT", "GCMC" simulation with the '
"velocity binary files, both the velocity files for box 0 and box 1 "
"must be provided."
)
raise ValueError(print_error_message)
elif (
self.binVelocities_box_0 is not None
or self.binVelocities_box_1 is not None
) and (
self.binCoordinates_box_0 is None
or self.extendedSystem_box_0 is None
or self.binCoordinates_box_1 is None
or self.extendedSystem_box_1 is None
):
print_error_message = (
'ERROR: To restart a "GEMC_NPT", "GEMC_NVT", "GCMC" simulation with the '
"velocity binary files, both the coor and xsc files files for box 0 "
"and box 1 must be provided."
)
raise ValueError(print_error_message)
self.RunSteps = RunSteps
self.Temperature = Temperature
self.ff_psf_pdb_file_directory = ff_psf_pdb_file_directory
if (
not isinstance(self.ff_psf_pdb_file_directory, str)
and self.ff_psf_pdb_file_directory is not None
):
_check_if_string_and_extension(
"ff_psf_pdb_file_directory",
self.ff_psf_pdb_file_directory,
"force field, pdb, and psf",
expected_file_extension=None,
)
if (
charmm_object.ff_filename is not None
and isinstance(charmm_object.ff_filename, str) is True
):
if Parameters is not None:
_check_if_string_and_extension(
"Parameters",
Parameters,
"force field",
expected_file_extension=[".inp", ".par"],
)
self.ff_filename = Parameters
elif self.ff_psf_pdb_file_directory is None:
self.ff_filename = charmm_object.ff_filename
else:
self.ff_filename = "{}/{}".format(
self.ff_psf_pdb_file_directory,
charmm_object.ff_filename,
)
# check if the FF file exist:
_check_if_input_files_exist(
self.ff_filename,
"force field file or parameter file",
check_input_files_exist=check_input_files_exist,
)
elif (
charmm_object.ff_filename is None
or isinstance(charmm_object.ff_filename, str) is False
):
self.input_error = True
print_error_message = (
"The force field file name was not specified and in the Charmm object ({})."
"Therefore, the force field file (.inp) can not be written, and thus, the "
"GOMC control file (.conf) can not be created. Please use the force field file "
"name when building the Charmm object".format(
type(mf_charmm.Charmm)
)
)
raise ValueError(print_error_message)
if (
charmm_object.filename_box_0 is not None
and isinstance(charmm_object.filename_box_0, str) is True
):
if Coordinates_box_0 is not None:
_check_if_string_and_extension(
"Coordinates_box_0",
Coordinates_box_0,
"pdb",
expected_file_extension=[".pdb"],
)
self.Coordinates_box_0 = Coordinates_box_0
elif self.ff_psf_pdb_file_directory is None:
self.Coordinates_box_0 = "{}.pdb".format(
charmm_object.filename_box_0
)
else:
self.Coordinates_box_0 = "{}/{}.pdb".format(
self.ff_psf_pdb_file_directory, charmm_object.filename_box_0
)
if Structure_box_0 is not None:
_check_if_string_and_extension(
"Structure_box_0",
Structure_box_0,
"psf",
expected_file_extension=[".psf"],
)
self.Structure_box_0 = Structure_box_0
elif self.ff_psf_pdb_file_directory is None:
self.Structure_box_0 = "{}.psf".format(
charmm_object.filename_box_0
)
else:
self.Structure_box_0 = "{}/{}.psf".format(
self.ff_psf_pdb_file_directory, charmm_object.filename_box_0
)
_check_if_input_files_exist(
self.Coordinates_box_0,
"box 0 pdb file",
check_input_files_exist=check_input_files_exist,
)
_check_if_input_files_exist(
self.Structure_box_0,
"box 0 psf file",
check_input_files_exist=check_input_files_exist,
)
# Box 0 restarting files with increased accuracy (coor, xsc) and a velocity passing input
if (
self.binCoordinates_box_0 is not None
and self.extendedSystem_box_0 is not None
):
_check_if_string_and_extension(
"binCoordinates_box_0",
self.binCoordinates_box_0,
"coor",
expected_file_extension=[".coor"],
)
_check_if_string_and_extension(
"extendedSystem_box_0",
self.extendedSystem_box_0,
"xsc",
expected_file_extension=[".xsc"],
)
_check_if_input_files_exist(
self.binCoordinates_box_0,
"box 0 coor file",
check_input_files_exist=check_input_files_exist,
)
_check_if_input_files_exist(
self.extendedSystem_box_0,
"box 0 xsc file",
check_input_files_exist=check_input_files_exist,
)
if self.binVelocities_box_0 is not None:
_check_if_string_and_extension(
"binVelocities_box_0",
self.binVelocities_box_0,
"velocity",
expected_file_extension=[".vel"],
)
_check_if_input_files_exist(
self.binVelocities_box_0,
"box 0 velocity file",
check_input_files_exist=check_input_files_exist,
)
if (
charmm_object.filename_box_1 is not None
and isinstance(charmm_object.filename_box_1, str) is True
):
if Coordinates_box_1 is not None:
_check_if_string_and_extension(
"Coordinates_box_1",
Coordinates_box_1,
"pdb",
expected_file_extension=[".pdb"],
)
self.Coordinates_box_1 = Coordinates_box_1
elif self.ff_psf_pdb_file_directory is None:
self.Coordinates_box_1 = "{}.pdb".format(
charmm_object.filename_box_1
)
else:
self.Coordinates_box_1 = "{}/{}.pdb".format(
self.ff_psf_pdb_file_directory, charmm_object.filename_box_1
)
if Structure_box_1 is not None:
_check_if_string_and_extension(
"Structure_box_1",
Structure_box_1,
"psf",
expected_file_extension=[".psf"],
)
self.Structure_box_1 = Structure_box_1
elif self.ff_psf_pdb_file_directory is None:
self.Structure_box_1 = "{}.psf".format(
charmm_object.filename_box_1
)
else:
self.Structure_box_1 = "{}/{}.psf".format(
self.ff_psf_pdb_file_directory, charmm_object.filename_box_1
)
_check_if_input_files_exist(
self.Coordinates_box_1,
"box 1 pdb file",
check_input_files_exist=check_input_files_exist,
)
_check_if_input_files_exist(
self.Structure_box_1,
"box 1 psf file",
check_input_files_exist=check_input_files_exist,
)
# Box 1 restarting files with increased accuracy (coor, xsc) and a velocity passing input
if (
self.binCoordinates_box_1 is not None
and self.extendedSystem_box_1 is not None
):
_check_if_string_and_extension(
"binCoordinates_box_1",
self.binCoordinates_box_1,
"coor",
expected_file_extension=[".coor"],
)
_check_if_string_and_extension(
"extendedSystem_box_1",
self.extendedSystem_box_1,
"xsc",
expected_file_extension=[".xsc"],
)
_check_if_input_files_exist(
self.binCoordinates_box_1,
"box 1 coor file",
check_input_files_exist=check_input_files_exist,
)
_check_if_input_files_exist(
self.extendedSystem_box_1,
"box 1 xsc file",
check_input_files_exist=check_input_files_exist,
)
if self.binVelocities_box_1 is not None:
_check_if_string_and_extension(
"binVelocities_box_1",
self.binVelocities_box_1,
"velocity",
expected_file_extension=[".vel"],
)
_check_if_input_files_exist(
self.binVelocities_box_1,
"box 0 velocity file",
check_input_files_exist=check_input_files_exist,
)
else:
self.Coordinates_box_1 = None
self.Structure_box_1 = None
self.coul_1_4 = charmm_object.coul_1_4
self.input_variables_dict = input_variables_dict
self.residues = charmm_object.residues
self.all_residues_unique_atom_name_dict = (
charmm_object.all_res_unique_atom_name_dict
)
# Get and test and make sure vectors are not too large for the 16 spaces allotted
box_vectors_char_limit = 16
self.box_0_vectors = charmm_object.box_0_vectors
box_0_vectors_char_ok = _check_box_vectors_char_limit(
self.box_0_vectors, box_vectors_char_limit
)
if box_0_vectors_char_ok == False:
self.input_error = True
print_error_message = (
"ERROR: At lease one of the individual box {} vectors are too large "
"or greater than {} characters."
"".format(
0,
box_vectors_char_limit,
)
)
raise ValueError(print_error_message)
if self.ensemble_type in ["GEMC_NVT", "GEMC_NPT", "GCMC"]:
if (
charmm_object.filename_box_1 is not None
and isinstance(charmm_object.filename_box_1, str) is True
):
self.box_1_vectors = charmm_object.box_1_vectors
box_1_vectors_char_ok = _check_box_vectors_char_limit(
self.box_1_vectors, box_vectors_char_limit
)
if box_1_vectors_char_ok == False:
self.input_error = True
print_error_message = (
"ERROR: At lease one of the individual box {} vectors are too large "
"or greater than {} characters."
"".format(
1,
box_vectors_char_limit,
)
)
raise ValueError(print_error_message)
else:
self.box_1_vectors = None
# check if the ensembles have the correct number of boxes in the charmm object
if (
self.ensemble_type in ["NVT", "NPT"]
and self.Coordinates_box_1 is not None
and self.Structure_box_1 is not None
):
self.input_error = True
print_error_message = (
"ERROR: The ensemble type selection of {} is using a Charmm "
"object with two simulation boxes, and the {} ensemble only accepts "
"one box (box 0)."
"".format(ensemble_type, ensemble_type)
)
raise ValueError(print_error_message)
if (
self.ensemble_type in ["GEMC_NVT", "GEMC_NPT", "GCMC"]
and self.Coordinates_box_1 is None
and self.Structure_box_1 is None
):
self.input_error = True
print_error_message = (
"ERROR: The ensemble type selection of {} is using a Charmm "
"object with one simulation boxes, and the {} ensemble only accepts "
"two boxes (box 0 and box 1)."
"".format(ensemble_type, ensemble_type)
)
raise ValueError(print_error_message)
# the future control file name is entered now as None
self.conf_filename = None
# list of bad variable inputs
bad_input_variables_values_list = []
# set all the other variable initally to None (they are corrected to their set or default values later)
default_input_variables_dict = _get_default_variables_dict()
self.PRNG = default_input_variables_dict["PRNG"]
self.ParaTypeCHARMM = default_input_variables_dict["ParaTypeCHARMM"]
self.ParaTypeMie = default_input_variables_dict["ParaTypeMie"]
self.ParaTypeMARTINI = default_input_variables_dict["ParaTypeMARTINI"]
self.RcutCoulomb_box_0 = default_input_variables_dict[
"RcutCoulomb_box_0"
]
self.RcutCoulomb_box_1 = default_input_variables_dict[
"RcutCoulomb_box_1"
]
self.Pressure = default_input_variables_dict["Pressure"]
self.Rcut = default_input_variables_dict["Rcut"]
self.RcutLow = default_input_variables_dict["RcutLow"]
self.LRC = default_input_variables_dict["LRC"]
self.IPC = default_input_variables_dict["IPC"]
self.Exclude = default_input_variables_dict["Exclude"]
self.Potential = default_input_variables_dict["Potential"]
self.Rswitch = default_input_variables_dict["Rswitch"]
self.ElectroStatic = default_input_variables_dict["ElectroStatic"]
self.Ewald = default_input_variables_dict["Ewald"]
self.CachedFourier = default_input_variables_dict["CachedFourier"]
self.Tolerance = default_input_variables_dict["Tolerance"]
self.Dielectric = default_input_variables_dict["Dielectric"]
self.VDWGeometricSigma = default_input_variables_dict[
"VDWGeometricSigma"
]
self.useConstantArea = default_input_variables_dict["useConstantArea"]
self.FixVolBox0 = default_input_variables_dict["FixVolBox0"]
self.ChemPot = default_input_variables_dict["ChemPot"]
self.Fugacity = default_input_variables_dict["Fugacity"]
self.CBMC_First = default_input_variables_dict["CBMC_First"]
self.CBMC_Nth = default_input_variables_dict["CBMC_Nth"]
self.CBMC_Ang = default_input_variables_dict["CBMC_Ang"]
self.CBMC_Dih = default_input_variables_dict["CBMC_Dih"]
self.OutputName = default_input_variables_dict["OutputName"]
self.DistName = default_input_variables_dict["DistName"]
self.HistName = default_input_variables_dict["HistName"]
self.RunNumber = default_input_variables_dict["RunNumber"]
self.RunLetter = default_input_variables_dict["RunLetter"]
self.OutEnergy = default_input_variables_dict["OutEnergy"]
self.OutPressure = default_input_variables_dict["OutPressure"]
self.OutMolNum = default_input_variables_dict["OutMolNum"]
self.OutDensity = default_input_variables_dict["OutDensity"]
self.OutVolume = default_input_variables_dict["OutVolume"]
self.OutSurfaceTension = default_input_variables_dict[
"OutSurfaceTension"
]
self.FreeEnergyCalc = default_input_variables_dict["FreeEnergyCalc"]
self.MoleculeType = default_input_variables_dict["MoleculeType"]
self.InitialState = default_input_variables_dict["InitialState"]
self.LambdaVDW = default_input_variables_dict["LambdaVDW"]
self.LambdaCoulomb = default_input_variables_dict["LambdaCoulomb"]
self.ScaleCoulomb = default_input_variables_dict["ScaleCoulomb"]
self.ScalePower = default_input_variables_dict["ScalePower"]
self.ScaleAlpha = default_input_variables_dict["ScaleAlpha"]
self.MinSigma = default_input_variables_dict["MinSigma"]
# standard moves
self.DisFreq = default_input_variables_dict["DisFreq"][
self.ensemble_type
]
self.RotFreq = default_input_variables_dict["RotFreq"][
self.ensemble_type
]
self.IntraSwapFreq = default_input_variables_dict["IntraSwapFreq"][
self.ensemble_type
]
self.SwapFreq = default_input_variables_dict["SwapFreq"][
self.ensemble_type
]
self.RegrowthFreq = default_input_variables_dict["RegrowthFreq"][
self.ensemble_type
]
self.CrankShaftFreq = default_input_variables_dict["CrankShaftFreq"][
self.ensemble_type
]
self.VolFreq = default_input_variables_dict["VolFreq"][
self.ensemble_type
]
self.MultiParticleFreq = default_input_variables_dict[
"MultiParticleFreq"
][self.ensemble_type]
self.IntraMEMC_1Freq = default_input_variables_dict["IntraMEMC-1Freq"][
self.ensemble_type
]
self.MEMC_1Freq = default_input_variables_dict["MEMC-1Freq"][
self.ensemble_type
]
self.IntraMEMC_2Freq = default_input_variables_dict["IntraMEMC-2Freq"][
self.ensemble_type
]
self.MEMC_2Freq = default_input_variables_dict["MEMC-2Freq"][
self.ensemble_type
]
self.IntraMEMC_3Freq = default_input_variables_dict["IntraMEMC-3Freq"][
self.ensemble_type
]
self.MEMC_3Freq = default_input_variables_dict["MEMC-3Freq"][
self.ensemble_type
]
self.TargetedSwapFreq = default_input_variables_dict[
"TargetedSwapFreq"
][self.ensemble_type]
self.IntraTargetedSwapFreq = default_input_variables_dict[
"IntraTargetedSwapFreq"
][self.ensemble_type]
# MEMC data input
self.ExchangeVolumeDim = default_input_variables_dict[
"ExchangeVolumeDim"
]
self.MEMC_DataInput = default_input_variables_dict["MEMC_DataInput"]
self.TargetedSwap_DataInput = default_input_variables_dict[
"TargetedSwap_DataInput"
]
# auto calculate the best EqSteps (number of Equilbrium Steps) and Adj_Steps (number of AdjSteps Steps)
self.EqSteps = _scale_gen_freq_for_run_steps_int(
"EqSteps", default_input_variables_dict["EqSteps"], self.RunSteps
)
self.AdjSteps = _scale_gen_freq_for_run_steps_int(
"AdjSteps", default_input_variables_dict["AdjSteps"], self.RunSteps
)
# auto calculate the best RestartFreq for the number of self.RunSteps
self.RestartFreq = _scale_gen_freq_for_run_steps_list_bool_int(
"RestartFreq",
default_input_variables_dict["RestartFreq"],
self.RunSteps,
)
# auto calculate the best CheckpointFreq for the number of self.RunSteps
self.CheckpointFreq = _scale_gen_freq_for_run_steps_list_bool_int(
"CheckpointFreq",
default_input_variables_dict["CheckpointFreq"],
self.RunSteps,
)
# auto calculate the best CoordinatesFreq for the number of self.RunSteps
self.CoordinatesFreq = _scale_gen_freq_for_run_steps_list_bool_int(
"CoordinatesFreq",
default_input_variables_dict["CoordinatesFreq"],
self.RunSteps,
)
# auto calculate the best DCDFreq for the number of self.RunSteps
self.DCDFreq = _scale_gen_freq_for_run_steps_list_bool_int(
"DCDFreq", default_input_variables_dict["DCDFreq"], self.RunSteps
)
# auto calculate the best ConsoleFreq for the number of self.RunSteps
self.ConsoleFreq = _scale_gen_freq_for_run_steps_list_bool_int(
"ConsoleFreq",
default_input_variables_dict["ConsoleFreq"],
self.RunSteps,
)
# auto calculate the best PressureCalc for the number of self.RunSteps
self.PressureCalc = _scale_gen_freq_for_run_steps_list_bool_int(
"PressureCalc",
default_input_variables_dict["PressureCalc"],
self.RunSteps,
)
# auto calculate the best BlockAverageFreq for the number of self.RunSteps
self.BlockAverageFreq = _scale_gen_freq_for_run_steps_list_bool_int(
"BlockAverageFreq",
default_input_variables_dict["BlockAverageFreq"],
self.RunSteps,
)
# auto calculate the best HistogramFreq for the number of self.RunSteps
self.HistogramFreq = _scale_gen_freq_for_run_steps_list_bool_int(
"HistogramFreq",
default_input_variables_dict["HistogramFreq"],
self.RunSteps,
)
# auto calculate the best SampleFreq for the number of self.RunSteps
self.SampleFreq = _scale_gen_freq_for_run_steps_int(
"SampleFreq",
default_input_variables_dict["SampleFreq"],
self.RunSteps,
)
if input_variables_dict is None:
self.input_variables_dict = {}
elif isinstance(input_variables_dict, dict) is True:
self.input_variables_dict = input_variables_dict
else:
self.input_error = True
print_error_message = "ERROR: The input_variables_dict variable is not None or a dictionary."
raise ValueError(print_error_message)
# Create all lower case spelled keywords, and return case specific keywords
# Also, creates a dict to convert the lower case keys to case sensitive keys
all_input_var_case_spec_list = _get_all_possible_input_variables(
description=False
)
all_input_var_case_unspec_list = []
all_input_var_case_unspec_to_spec_dict = {}
for var_i in all_input_var_case_spec_list:
all_input_var_case_unspec_list.append(var_i.lower())
all_input_var_case_unspec_to_spec_dict.update(
{var_i.lower(): var_i}
)
# create/fix user case insensitive input variables (input_variables_dict) keys to case sensitive keys
input_var_dict_orig_keys_list = dict_keys_to_list(
self.input_variables_dict
)
for z_j in range(0, len(input_var_dict_orig_keys_list)):
key_lower = input_var_dict_orig_keys_list[z_j].lower()
if key_lower in all_input_var_case_unspec_list:
input_variables_dict[
all_input_var_case_unspec_to_spec_dict[key_lower]
] = input_variables_dict.pop(input_var_dict_orig_keys_list[z_j])
# check that the coulombic 1-4 scalar is : 0 =< 1-4 scalar <=1
if (
(
isinstance(self.coul_1_4, int) is False
and isinstance(self.coul_1_4, float) is False
)
or self.coul_1_4 < 0
or self.coul_1_4 > 1
):
self.input_error = True
print_error_message = (
"ERROR: The selected 1-4 Coulombic scalar ({{) is not correct. "
"The 1-4 Coulombic scalar need to be an integer or float from "
"0 to 1.".format(self.coul_1_4)
)
raise ValueError(print_error_message)
# check that the Temperature is valid
if self.Temperature <= 1:
self.input_error = True
print_error_message = (
"ERROR: The selected Temperature ({}) is equal to or less than 1 Kelvin. "
"Please select a valid Temperature".format(self.Temperature)
)
raise ValueError(print_error_message)
else:
print(
"INFO: All the Temperature (Temperature) input passed the initial error checking"
)
# RunSteps
if not isinstance(self.RunSteps, int) or self.RunSteps <= 0:
self.input_error = True
print_error_message = (
"ERROR: The selected run steps (RunSteps variable = {}) is not "
"an integer or is less than or equal to 0.".format(
self.RunSteps
)
)
raise ValueError(print_error_message)
# create a list of the possible required files and check them based on the ensemble
required_data_list = [
self.ff_filename,
self.Coordinates_box_0,
self.Structure_box_0,
]
if self.Coordinates_box_1 is not None:
required_data_list.append(self.Coordinates_box_1)
if self.Structure_box_1 is not None:
required_data_list.append(self.Structure_box_1)
if self.ensemble_type in ["NVT", "NPT"]:
if (
len(required_data_list) != 3
or os.path.splitext(self.ff_filename)[1] not in [".inp", ".par"]
or os.path.splitext(self.Coordinates_box_0)[1] != ".pdb"
or os.path.splitext(self.Structure_box_0)[1] != ".psf"
):
self.input_error = True
print_error_message = (
"ERROR: The proper force field, PDB, and psf files were not provided, "
"or at least their extentions are not correct "
"(i.e., not .inp, .par, .pdb, or .psf). Or box 1 PSF and PDB files were "
"provided for the NVT or NPT simulations, which is not allowed"
)
raise ValueError(print_error_message)
else:
print(
"INFO: All the required force field, pdb, and psf files for box 0 (.inp, .pdb, and .psf) all "
"passed the intial error checking. Note: the file names and their existance is not confirmed."
)
if self.ensemble_type in ["GEMC_NVT", "GEMC_NPT", "GCMC"]:
if (
len(required_data_list) != 5
or os.path.splitext(self.ff_filename)[1] not in [".inp", ".par"]
or os.path.splitext(self.Coordinates_box_0)[1] != ".pdb"
or os.path.splitext(self.Structure_box_0)[1] != ".psf"
or os.path.splitext(self.Coordinates_box_1)[1] != ".pdb"
or os.path.splitext(self.Structure_box_1)[1] != ".psf"
):
print_error_message = (
"ERROR: The proper force field, PDB, and psf files were not provided, "
"or at least their extentions are not correct "
"(i.e., not .inp, .par, .pdb, or .psf). Or box 1 PSF and PDB files were not provided "
"for the GEMC_NVT, GEMC_NPT or GCMC simulations, which is not allowed"
)
self.input_error = True
raise ValueError(print_error_message)
else:
print(
"INFO: All the required force field, pdb, and psf files for box 0 and 1 (.inp, .pdb, and .psf) all "
"passed the intial error checking. Note: the file names and their existance is not confirmed."
)
# verify all input variables keys are valid
input_variables_dict_keys_list = dict_keys_to_list(
self.input_variables_dict
)
if (
check_valid_ensemble_input_variables(
self.ensemble_type, input_variables_dict_keys_list
)[0]
is False
):
returned_ck_bad_inputs_list = check_valid_ensemble_input_variables(
self.ensemble_type, input_variables_dict_keys_list
)[1]
self.input_error = True
print_error_message = (
"ERROR: All the correct input variables where not provided for the {} "
"ensemble. Please be sure to check that the keys in the "
"input variables dictionary (input_variables_dict) is correct, and be aware "
"that added spaces before or after the variable in any keys "
"will also give this warning. The bad variable inputs "
"ensemble inputs = {}".format(
self.ensemble_type, returned_ck_bad_inputs_list
)
)
raise ValueError(print_error_message)
# verify all input variable values are valid, for their keys
input_var_all_keys_list = dict_keys_to_list(self.input_variables_dict)
# sort to only values that are not None
input_var_keys_list = []
for all_keys_i in input_var_all_keys_list:
if self.input_variables_dict[all_keys_i] is not None:
input_var_keys_list.append(all_keys_i)
possible_ensemble_variables_list = (
_get_possible_ensemble_input_variables(self.ensemble_type)
)
# check to make sure the VDW FF (ParaTypeCHARMM) is set true for multiple ones by the user
# (i.e., ParaTypeCHARMM, ParaTypeMie, ParaTypeMARTINI)
vdw_ck_list = []
for vdw_ck_inter in range(0, len(input_var_keys_list)):
if (
input_var_keys_list[vdw_ck_inter]
in ["ParaTypeCHARMM", "ParaTypeMie", "ParaTypeMARTINI"]
and self.input_variables_dict[input_var_keys_list[vdw_ck_inter]]
is True
):
vdw_ck_list.append(True)
if sum(vdw_ck_list) > 1:
self.input_error = True
print_error_message = (
"ERROR: there can only be 1 VDW set to true. Please set only one of the "
"ParaTypeCHARMM, ParaTypeMie, ParaTypeMARTINI types to True in the "
"user variable input"
)
raise ValueError(print_error_message)
# check for MC move ratios and zero all of them if any are in the input variables
for var_iter in range(0, len(input_var_keys_list)):
# standard MC moves
key_move_list = [
"DisFreq",
"RotFreq",
"IntraSwapFreq",
"SwapFreq",
"RegrowthFreq",
"CrankShaftFreq",
"VolFreq",
"MultiParticleFreq",
"IntraMEMC-1Freq",
"MEMC-1Freq",
"IntraMEMC-2Freq",
"MEMC-2Freq",
"IntraMEMC-3Freq",
"MEMC-3Freq",
"TargetedSwapFreq",
"IntraTargetedSwapFreq",
]
if input_var_keys_list[var_iter] in key_move_list:
self.DisFreq = 0.00
self.RotFreq = 0.00
self.IntraSwapFreq = 0.00
self.SwapFreq = 0.00
self.RegrowthFreq = 0.00
self.CrankShaftFreq = 0.00
self.VolFreq = 0.00
self.MultiParticleFreq = 0.00
self.IntraMEMC_1Freq = 0.00
self.MEMC_1Freq = 0.00
self.IntraMEMC_2Freq = 0.00
self.MEMC_2Freq = 0.00
self.IntraMEMC_3Freq = 0.00
self.MEMC_3Freq = 0.00
self.TargetedSwapFreq = 0.00
self.IntraTargetedSwapFreq = 0.00
# set all the "RcutLow", "Rcut", "Rswitch" variable ahead of time so they can check the values
# relative to each other in the next interation, regardless of their user entered order
if input_var_keys_list[var_iter] == "Rcut":
self.Rcut = self.input_variables_dict["Rcut"]
if input_var_keys_list[var_iter] == "RcutLow":
self.RcutLow = self.input_variables_dict["RcutLow"]
if input_var_keys_list[var_iter] == "Rswitch":
self.Rswitch = self.input_variables_dict["Rswitch"]
if input_var_keys_list[var_iter] == "Potential":
self.Potential = self.input_variables_dict["Potential"]
# check for bad input variables and list the bad ones
for var_iter in range(0, len(input_var_keys_list)):
key = "PRNG"
if input_var_keys_list[var_iter] == key:
if (
self.input_variables_dict[key] != "RANDOM"
and isinstance(self.input_variables_dict[key], int)
is not True
):
bad_input_variables_values_list.append(key)
if isinstance(self.input_variables_dict[key], int) is True:
if self.input_variables_dict[key] < 0:
bad_input_variables_values_list.append(key)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.PRNG = self.input_variables_dict[key]
key = "ParaTypeCHARMM"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_true_or_false(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.ParaTypeCHARMM = self.input_variables_dict[key]
if self.input_variables_dict[key] is True:
self.ParaTypeMie = False
self.ParaTypeMARTINI = False
key = "ParaTypeMie"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_true_or_false(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.ParaTypeMie = self.input_variables_dict[key]
if self.input_variables_dict[key] is True:
self.ParaTypeCHARMM = False
key = "ParaTypeMARTINI"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_true_or_false(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.ParaTypeMARTINI = self.input_variables_dict[key]
if self.input_variables_dict[key] is True:
self.ParaTypeCHARMM = False
key = "RcutCoulomb_box_0"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_or_greater(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.RcutCoulomb_box_0 = self.input_variables_dict[key]
key = "RcutCoulomb_box_1"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_or_greater(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.RcutCoulomb_box_1 = self.input_variables_dict[key]
key = "Pressure"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_or_greater(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.Pressure = self.input_variables_dict[key]
key = "Rcut"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_or_greater(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.Rcut = self.input_variables_dict[key]
key = "RcutLow"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_or_greater(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if isinstance(
self.input_variables_dict[key], float
) or isinstance(self.input_variables_dict[key], int):
if self.input_variables_dict[key] > self.Rcut:
bad_input_variables_values_list.append(key)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.RcutLow = self.input_variables_dict[key]
key = "LRC"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_true_or_false(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.LRC = self.input_variables_dict[key]
key = "IPC"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_true_or_false(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.IPC = self.input_variables_dict[key]
key = "Exclude"
if input_var_keys_list[var_iter] == key:
if (
self.input_variables_dict[key] != "1-2"
and self.input_variables_dict[key] != "1-3"
and self.input_variables_dict[key] != "1-4"
):
bad_input_variables_values_list.append(key)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.Exclude = self.input_variables_dict[key]
key = "Potential"
if input_var_keys_list[var_iter] == key:
if (
self.input_variables_dict[key] != "VDW"
and self.input_variables_dict[key] != "EXP6"
and self.input_variables_dict[key] != "SHIFT"
and self.input_variables_dict[key] != "SWITCH"
):
bad_input_variables_values_list.append(key)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.Potential = self.input_variables_dict[key]
key = "Rswitch"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_or_greater(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
(
isinstance(self.input_variables_dict[key], float)
or isinstance(self.input_variables_dict[key], int)
)
and (
isinstance(self.RcutLow, float)
or isinstance(self.RcutLow, int)
)
and (
isinstance(self.Rcut, float)
or isinstance(self.Rcut, int)
)
and self.Potential == "SWITCH"
):
if (
self.input_variables_dict[key] <= self.RcutLow
or self.input_variables_dict[key] >= self.Rcut
):
bad_input_variables_values_list.append(key)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.Rswitch = self.input_variables_dict[key]
key = "ElectroStatic"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_true_or_false(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.ElectroStatic = self.input_variables_dict[key]
key = "Ewald"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_true_or_false(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.Ewald = self.input_variables_dict[key]
key = "CachedFourier"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_true_or_false(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.CachedFourier = self.input_variables_dict[key]
key = "Tolerance"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_float_greater_zero_less_1(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.Tolerance = self.input_variables_dict[key]
key = "Dielectric"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_or_greater(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.Dielectric = self.input_variables_dict[key]
key = "PressureCalc"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_list_bool_int_zero_or_greater(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.PressureCalc = self.input_variables_dict[key]
key = "EqSteps"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_greater_zero(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.EqSteps = self.input_variables_dict[key]
key = "AdjSteps"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_greater_zero(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.AdjSteps = self.input_variables_dict[key]
key = "VDWGeometricSigma"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_true_or_false(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.VDWGeometricSigma = self.input_variables_dict[key]
key = "useConstantArea"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_true_or_false(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.useConstantArea = self.input_variables_dict[key]
key = "FixVolBox0"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_true_or_false(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.FixVolBox0 = self.input_variables_dict[key]
# ChemPot and Fugacity are only for GCMC
key = "ChemPot"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_GCMC_dict_str_int_or_float(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.ChemPot = self.input_variables_dict[key]
key = "Fugacity"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_GCMC_dict_str_int_or_float_zero_or_greater(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.Fugacity = self.input_variables_dict[key]
key = "CBMC_First"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_zero_or_greater(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.CBMC_First = self.input_variables_dict[key]
key = "CBMC_Nth"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_zero_or_greater(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.CBMC_Nth = self.input_variables_dict[key]
key = "CBMC_Ang"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_zero_or_greater(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.CBMC_Ang = self.input_variables_dict[key]
key = "CBMC_Dih"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_zero_or_greater(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.CBMC_Dih = self.input_variables_dict[key]
key = "OutputName"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_str_with_no_spaces(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.OutputName = self.input_variables_dict[key]
key = "CoordinatesFreq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_list_bool_int_greater_zero(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.CoordinatesFreq = self.input_variables_dict[key]
key = "DCDFreq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_list_bool_int_greater_zero(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.DCDFreq = self.input_variables_dict[key]
key = "RestartFreq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_list_bool_int_greater_zero(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.RestartFreq = self.input_variables_dict[key]
key = "CheckpointFreq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_list_bool_int_greater_zero(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.CheckpointFreq = self.input_variables_dict[key]
key = "ConsoleFreq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_list_bool_int_greater_zero(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.ConsoleFreq = self.input_variables_dict[key]
key = "BlockAverageFreq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_list_bool_int_greater_zero(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.BlockAverageFreq = self.input_variables_dict[key]
key = "HistogramFreq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_list_bool_int_greater_zero(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.HistogramFreq = self.input_variables_dict[key]
key = "DistName"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_str_with_no_spaces(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.DistName = self.input_variables_dict[key]
key = "HistName"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_str_with_no_spaces(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.HistName = self.input_variables_dict[key]
key = "RunNumber"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_greater_zero(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.RunNumber = self.input_variables_dict[key]
key = "RunLetter"
if input_var_keys_list[var_iter] == key:
if isinstance(self.input_variables_dict[key], str) is not True:
bad_input_variables_values_list.append(key)
if isinstance(self.input_variables_dict[key], str) is True:
if len(self.input_variables_dict[key]) != 1:
bad_input_variables_values_list.append(key)
elif len(self.input_variables_dict[key]) == 1:
is_run_letter_alphabet_char = self.input_variables_dict[
key
].isalpha()
if is_run_letter_alphabet_char is False:
bad_input_variables_values_list.append(key)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.RunLetter = self.input_variables_dict[key]
key = "SampleFreq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_greater_zero(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.SampleFreq = self.input_variables_dict[key]
key = "OutEnergy"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_list_bool_bool(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.OutEnergy = self.input_variables_dict[key]
key = "OutPressure"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_list_bool_bool(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.OutPressure = self.input_variables_dict[key]
key = "OutMolNum"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_list_bool_bool(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.OutMolNum = self.input_variables_dict[key]
key = "OutDensity"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_list_bool_bool(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.OutDensity = self.input_variables_dict[key]
key = "OutVolume"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_list_bool_bool(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.OutVolume = self.input_variables_dict[key]
key = "OutSurfaceTension"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_list_bool_bool(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.OutSurfaceTension = self.input_variables_dict[key]
key = "FreeEnergyCalc"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_list_bool_int_greater_zero(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.FreeEnergyCalc = self.input_variables_dict[key]
key = "MoleculeType"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_list_residue_str_int_greater_zero(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.MoleculeType = self.input_variables_dict[key]
key = "InitialState"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_zero_or_greater(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.InitialState = self.input_variables_dict[key]
key = "LambdaVDW"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_list_of_floats_zero_to_1(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.LambdaVDW = self.input_variables_dict[key]
key = "LambdaCoulomb"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_list_of_floats_zero_to_1(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.LambdaCoulomb = self.input_variables_dict[key]
key = "ScaleCoulomb"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_true_or_false(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.ScaleCoulomb = self.input_variables_dict[key]
key = "ScalePower"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_zero_or_greater(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.ScalePower = self.input_variables_dict[key]
key = "ScaleAlpha"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_or_greater(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.ScaleAlpha = self.input_variables_dict[key]
key = "MinSigma"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_or_greater(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.MinSigma = self.input_variables_dict[key]
# standard MC moves
key = "DisFreq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_to_1(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.DisFreq = self.input_variables_dict[key]
key = "RotFreq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_to_1(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.RotFreq = self.input_variables_dict[key]
key = "IntraSwapFreq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_to_1(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.IntraSwapFreq = self.input_variables_dict[key]
key = "SwapFreq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_to_1(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.SwapFreq = self.input_variables_dict[key]
else:
self.VolFreq = 0.00
key = "RegrowthFreq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_to_1(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.RegrowthFreq = self.input_variables_dict[key]
key = "CrankShaftFreq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_to_1(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.CrankShaftFreq = self.input_variables_dict[key]
key = "VolFreq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_to_1(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.VolFreq = self.input_variables_dict[key]
else:
self.VolFreq = 0.00
key = "MultiParticleFreq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_to_1(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.MultiParticleFreq = self.input_variables_dict[key]
# MEMC moves freqencies
key = "IntraMEMC-1Freq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_to_1(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.IntraMEMC_1Freq = self.input_variables_dict[key]
else:
self.IntraMEMC_1Freq = 0.00
key = "MEMC-1Freq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_to_1(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.MEMC_1Freq = self.input_variables_dict[key]
else:
self.MEMC_1Freq = 0.00
key = "IntraMEMC-2Freq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_to_1(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.IntraMEMC_2Freq = self.input_variables_dict[key]
else:
self.IntraMEMC_2Freq = 0.00
key = "MEMC-2Freq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_to_1(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.MEMC_2Freq = self.input_variables_dict[key]
else:
self.MEMC_2Freq = 0.00
key = "IntraMEMC-3Freq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_to_1(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.IntraMEMC_3Freq = self.input_variables_dict[key]
else:
self.IntraMEMC_3Freq = 0.00
key = "MEMC-3Freq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_to_1(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.MEMC_3Freq = self.input_variables_dict[key]
else:
self.MEMC_3Freq = 0.00
key = "ExchangeVolumeDim"
if input_var_keys_list[var_iter] == key:
if isinstance(self.input_variables_dict[key], list) is False:
bad_input_variables_values_list.append(key)
elif isinstance(self.input_variables_dict[key], list) is True:
if (
len(self.input_variables_dict[key]) != 3
or (
isinstance(self.input_variables_dict[key][0], float)
is not True
and isinstance(
self.input_variables_dict[key][0], int
)
is not True
)
or (
isinstance(self.input_variables_dict[key][1], float)
is not True
and isinstance(
self.input_variables_dict[key][1], int
)
is not True
)
or (
isinstance(self.input_variables_dict[key][2], float)
is not True
and isinstance(
self.input_variables_dict[key][2], int
)
is not True
)
or str(self.input_variables_dict[key][0]) == str(True)
or str(self.input_variables_dict[key][0]) == str(False)
or str(self.input_variables_dict[key][1]) == str(True)
or str(self.input_variables_dict[key][1]) == str(False)
or str(self.input_variables_dict[key][2]) == str(True)
or str(self.input_variables_dict[key][2]) == str(False)
):
bad_input_variables_values_list.append(key)
elif len(self.input_variables_dict[key]) == 3:
if (
(
isinstance(
self.input_variables_dict[key][0], float
)
is True
or isinstance(
self.input_variables_dict[key][0], int
)
is True
)
and (
isinstance(
self.input_variables_dict[key][1], float
)
is True
or isinstance(
self.input_variables_dict[key][1], int
)
is True
)
and (
isinstance(
self.input_variables_dict[key][2], float
)
is True
or isinstance(
self.input_variables_dict[key][2], int
)
is True
)
):
if (
self.input_variables_dict[key][0] <= 0
or self.input_variables_dict[key][1] <= 0
or self.input_variables_dict[key][2] <= 0
):
bad_input_variables_values_list.append(key)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.ExchangeVolumeDim = self.input_variables_dict[key]
key = "MEMC_DataInput"
if input_var_keys_list[var_iter] == key:
if isinstance(self.input_variables_dict[key], list) is False:
bad_input_variables_values_list.append(key)
elif isinstance(self.input_variables_dict[key], list) is True:
if len(self.input_variables_dict[key]) == 0:
bad_input_variables_values_list.append(key)
elif len(self.input_variables_dict[key]) > 0:
no_memc_combos = len(self.input_variables_dict[key])
for MEMC_iter in range(0, no_memc_combos):
if (
isinstance(
self.input_variables_dict[key][MEMC_iter],
list,
)
is False
):
bad_input_variables_values_list.append(key)
elif (
isinstance(
self.input_variables_dict[key][MEMC_iter],
list,
)
is True
and len(
self.input_variables_dict[key][MEMC_iter]
)
== 5
):
if (
isinstance(
self.input_variables_dict[key][
MEMC_iter
][2],
list,
)
is False
or isinstance(
self.input_variables_dict[key][
MEMC_iter
][4],
list,
)
is False
):
bad_input_variables_values_list.append(key)
elif (
isinstance(
self.input_variables_dict[key][
MEMC_iter
][2],
list,
)
is True
and isinstance(
self.input_variables_dict[key][
MEMC_iter
][4],
list,
)
is True
):
if (
len(
self.input_variables_dict[key][
MEMC_iter
][2]
)
!= 2
or len(
self.input_variables_dict[key][
MEMC_iter
][4]
)
!= 2
):
bad_input_variables_values_list.append(
key
)
elif (
len(
self.input_variables_dict[key][
MEMC_iter
][2]
)
== 2
and len(
self.input_variables_dict[key][
MEMC_iter
][4]
)
== 2
):
if (
isinstance(
self.input_variables_dict[key][
MEMC_iter
][0],
int,
)
is not True
or str(
self.input_variables_dict[key][
MEMC_iter
][0]
)
== str(True)
or str(
self.input_variables_dict[key][
MEMC_iter
][0]
)
== str(False)
or isinstance(
self.input_variables_dict[key][
MEMC_iter
][1],
str,
)
is False
or (
isinstance(
self.input_variables_dict[
key
][MEMC_iter][2][0],
str,
)
is False
and self.input_variables_dict[
key
][MEMC_iter][2][0]
is not None
)
or (
isinstance(
self.input_variables_dict[
key
][MEMC_iter][2][1],
str,
)
is False
and self.input_variables_dict[
key
][MEMC_iter][2][1]
is not None
)
or isinstance(
self.input_variables_dict[key][
MEMC_iter
][3],
str,
)
is False
or (
isinstance(
self.input_variables_dict[
key
][MEMC_iter][4][0],
str,
)
is False
and self.input_variables_dict[
key
][MEMC_iter][4][0]
is not None
)
or (
isinstance(
self.input_variables_dict[
key
][MEMC_iter][4][1],
str,
)
is False
and self.input_variables_dict[
key
][MEMC_iter][4][1]
is not None
)
):
bad_input_variables_values_list.append(
key
)
else:
bad_input_variables_values_list.append(
key
)
all_atom_names_and_res_pairs_keys_list = list(
self.all_residues_unique_atom_name_dict.keys()
)
# check that the atom names match the residues that exist
if (
self.input_variables_dict[key][
MEMC_iter
][1]
not in all_atom_names_and_res_pairs_keys_list
):
bad_input_variables_values_list.append(
key
)
elif (
self.input_variables_dict[key][
MEMC_iter
][1]
in all_atom_names_and_res_pairs_keys_list
):
if (
self.input_variables_dict[key][
MEMC_iter
][2][0]
not in self.all_residues_unique_atom_name_dict[
self.input_variables_dict[key][
MEMC_iter
][1]
]
):
bad_input_variables_values_list.append(
key
)
if (
self.input_variables_dict[key][
MEMC_iter
][2][1]
not in self.all_residues_unique_atom_name_dict[
self.input_variables_dict[key][
MEMC_iter
][1]
]
):
bad_input_variables_values_list.append(
key
)
if (
self.input_variables_dict[key][
MEMC_iter
][3]
not in all_atom_names_and_res_pairs_keys_list
):
bad_input_variables_values_list.append(
key
)
elif (
self.input_variables_dict[key][
MEMC_iter
][3]
in all_atom_names_and_res_pairs_keys_list
):
if (
self.input_variables_dict[key][
MEMC_iter
][4][0]
not in self.all_residues_unique_atom_name_dict[
self.input_variables_dict[key][
MEMC_iter
][3]
]
):
bad_input_variables_values_list.append(
key
)
if (
self.input_variables_dict[key][
MEMC_iter
][4][1]
not in self.all_residues_unique_atom_name_dict[
self.input_variables_dict[key][
MEMC_iter
][3]
]
):
bad_input_variables_values_list.append(
key
)
if (
isinstance(
self.input_variables_dict[key][
MEMC_iter
][0],
int,
)
is True
):
if (
self.input_variables_dict[key][
MEMC_iter
][0]
<= 0
):
bad_input_variables_values_list.append(
key
)
else:
bad_input_variables_values_list.append(key)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.MEMC_DataInput = self.input_variables_dict[key]
key = "TargetedSwapFreq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_to_1(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.TargetedSwapFreq = self.input_variables_dict[key]
else:
self.TargetedSwapFreq = 0.00
key = "IntraTargetedSwapFreq"
if input_var_keys_list[var_iter] == key:
self.ck_input_variable_int_or_float_zero_to_1(
self.input_variables_dict,
key,
bad_input_variables_values_list,
)
if (
input_var_keys_list[var_iter] == key
and key in possible_ensemble_variables_list
):
self.IntraTargetedSwapFreq = self.input_variables_dict[key]
else:
self.IntraTargetedSwapFreq = 0.00
key = "TargetedSwap_DataInput"
if input_var_keys_list[var_iter] == key:
# get all residues
all_residue_names_list = list(
self.all_residues_unique_atom_name_dict.keys()
)
target_swap_dict = self.input_variables_dict[
input_var_keys_list[var_iter]
]
target_swap_input_error = (
"The TargetedSwap_DataInput is not formatted correctly as a dictionary"
" or has the wrong input keys, values, or types."
)
if isinstance(target_swap_dict, dict):
for tag_i in list(target_swap_dict.keys()):
# check all tag ids are integers
if not isinstance(tag_i, int):
raise ValueError(target_swap_input_error)
for ts_dict_key_i in list(
target_swap_dict[tag_i].keys()
):
# check all target swap data inputs keys are strings
if not isinstance(ts_dict_key_i, str):
raise ValueError(target_swap_input_error)
# force all keys to lower case
elif isinstance(ts_dict_key_i, str):
target_swap_dict[tag_i][
ts_dict_key_i.lower()
] = target_swap_dict[tag_i].pop(ts_dict_key_i)
# verify all Target swap keys are valid
valid_target_swap_keys = [
"subvolumetype",
"subvolumebox",
"subvolumecenter",
"subvolumecenterlist",
"subvolumedim",
"subvolumeresiduekind",
"subvolumerigidswap",
"subvolumepbc",
"subvolumechempot",
"subvolumefugacity",
]
if (
ts_dict_key_i.lower()
not in valid_target_swap_keys
):
raise ValueError(target_swap_input_error)
# check the SubVolumeResidueKind is list of n length or convert string to list
# this SubVolumeResidueKind reformating needs done first before the other checks,
# specifically, the SubVolumeFugacity and SubVolumeChemPot
if ts_dict_key_i.lower() in [
"subvolumeresiduekind"
]:
if not isinstance(
target_swap_dict[tag_i][
"subvolumeresiduekind"
],
list,
) and not isinstance(
target_swap_dict[tag_i][
"subvolumeresiduekind"
],
str,
):
bad_input_variables_values_list.append(
"subvolumeresiduekind"
)
elif (
isinstance(
target_swap_dict[tag_i][
"subvolumeresiduekind"
],
list,
)
and len(
target_swap_dict[tag_i][
"subvolumeresiduekind"
]
)
>= 1
):
for ts_residue_i in target_swap_dict[tag_i][
"subvolumeresiduekind"
]:
if not isinstance(ts_residue_i, str):
bad_input_variables_values_list.append(
"subvolumeresiduekind"
)
elif (
ts_residue_i
not in all_residue_names_list
and ts_residue_i.lower()
not in ["all"]
):
bad_input_variables_values_list.append(
"subvolumeresiduekind"
)
elif ts_residue_i.lower() in ["all"]:
self.input_variables_dict[
input_var_keys_list[var_iter]
][tag_i]["subvolumeresiduekind"] = [
"ALL"
]
elif (
target_swap_dict[tag_i][
"subvolumeresiduekind"
].lower()
== "all"
):
self.input_variables_dict[
input_var_keys_list[var_iter]
][tag_i]["subvolumeresiduekind"] = ["ALL"]
elif (
target_swap_dict[tag_i][
"subvolumeresiduekind"
]
in all_residue_names_list
):
self.input_variables_dict[
input_var_keys_list[var_iter]
][tag_i]["subvolumeresiduekind"] = [
target_swap_dict[tag_i][
"subvolumeresiduekind"
]
]
else:
bad_input_variables_values_list.append(
"subvolumeresiduekind"
)
else:
raise ValueError(target_swap_input_error)
if isinstance(target_swap_dict, dict):
for tag_id_keys_i in list(target_swap_dict.keys()):
target_swap_tag_id_dict_key_data = target_swap_dict[
tag_id_keys_i
]
for target_swap_dict_key_i_lower in list(
target_swap_tag_id_dict_key_data.keys()
):
# check the SubVolumeType are either "Static", or "Dynamic"
if target_swap_dict_key_i_lower in [
"subvolumetype"
]:
if not isinstance(
target_swap_tag_id_dict_key_data[
"subvolumetype"
],
str,
):
bad_input_variables_values_list.append(
"subvolumetype"
)
elif target_swap_tag_id_dict_key_data[
"subvolumetype"
].lower() not in ["static", "dynamic"]:
bad_input_variables_values_list.append(
"subvolumetype"
)
# check for the SubVolumeCenter if its a static box
elif target_swap_tag_id_dict_key_data[
"subvolumetype"
].lower() in ["static"]:
if (
"subvolumecenter"
in target_swap_tag_id_dict_key_data
):
if not isinstance(
target_swap_tag_id_dict_key_data[
"subvolumecenter"
],
list,
):
bad_input_variables_values_list.append(
"subvolumecenter"
)
elif (
isinstance(
target_swap_tag_id_dict_key_data[
"subvolumecenter"
],
list,
)
and len(
target_swap_tag_id_dict_key_data[
"subvolumecenter"
]
)
== 3
):
for (
x_y_z_dim_i
) in target_swap_tag_id_dict_key_data[
"subvolumecenter"
]:
if not isinstance(
x_y_z_dim_i, (int, float)
):
bad_input_variables_values_list.append(
"subvolumecenter"
)
else:
bad_input_variables_values_list.append(
"subvolumecenter"
)
else:
bad_input_variables_values_list.append(
"subvolumecenter"
)
# check for the SubVolumeCenterList if its a dynamic box
elif target_swap_tag_id_dict_key_data[
"subvolumetype"
].lower() in ["dynamic"]:
if (
"subvolumecenterlist"
in target_swap_tag_id_dict_key_data
):
if isinstance(
target_swap_tag_id_dict_key_data[
"subvolumecenterlist"
],
list,
):
for (
atom_index_dim_i
) in target_swap_tag_id_dict_key_data[
"subvolumecenterlist"
]:
if isinstance(
atom_index_dim_i, int
):
if atom_index_dim_i < 0:
bad_input_variables_values_list.append(
"subvolumecenterlist"
)
elif isinstance(
atom_index_dim_i, str
):
atom_index_split_str = (
atom_index_dim_i.split(
"-"
)
)
if (
len(
atom_index_split_str
)
== 2
and atom_index_dim_i.find(
"."
)
< 0
):
try:
if (
not isinstance(
int(
atom_index_split_str[
0
]
),
int,
)
or not isinstance(
int(
atom_index_split_str[
1
]
),
int,
)
or int(
atom_index_split_str[
0
]
)
>= int(
atom_index_split_str[
1
]
)
or atom_index_split_str[
0
]
== ""
or atom_index_split_str[
1
]
== ""
):
bad_input_variables_values_list.append(
"subvolumecenterlist"
)
except:
bad_input_variables_values_list.append(
"subvolumecenterlist"
)
else:
bad_input_variables_values_list.append(
"subvolumecenterlist"
)
else:
bad_input_variables_values_list.append(
"subvolumecenterlist"
)
else:
bad_input_variables_values_list.append(
"subvolumecenterlist"
)
else:
bad_input_variables_values_list.append(
"subvolumecenterlist"
)
# check the SubVolumeBox is an interger of 0 or 1
if target_swap_dict_key_i_lower in ["subvolumebox"]:
if isinstance(
target_swap_tag_id_dict_key_data[
"subvolumebox"
],
int,
):
if self.ensemble_type in [
"GEMC_NVT",
"GEMC_NPT",
]:
if (
target_swap_tag_id_dict_key_data[
"subvolumebox"
]
!= 0
and target_swap_tag_id_dict_key_data[
"subvolumebox"
]
!= 1
):
bad_input_variables_values_list.append(
"subvolumebox"
)
elif self.ensemble_type in [
"GCMC",
"NVT",
"NPT",
]:
if (
target_swap_tag_id_dict_key_data[
"subvolumebox"
]
!= 0
):
bad_input_variables_values_list.append(
"subvolumebox"
)
else:
bad_input_variables_values_list.append(
"subvolumebox"
)
# check the SubVolumeDim is list of length 3, [x-dim, y-dim, z-dim]
if target_swap_dict_key_i_lower in ["subvolumedim"]:
if not isinstance(
target_swap_tag_id_dict_key_data[
"subvolumedim"
],
list,
):
bad_input_variables_values_list.append(
"subvolumedim"
)
elif (
isinstance(
target_swap_tag_id_dict_key_data[
"subvolumedim"
],
list,
)
and len(
target_swap_tag_id_dict_key_data[
"subvolumedim"
]
)
== 3
):
for (
set_x_y_z_dim_i
) in target_swap_tag_id_dict_key_data[
"subvolumedim"
]:
if not isinstance(
set_x_y_z_dim_i, (int, float)
):
bad_input_variables_values_list.append(
"subvolumedim"
)
elif set_x_y_z_dim_i <= 0:
bad_input_variables_values_list.append(
"subvolumedim"
)
else:
bad_input_variables_values_list.append(
"subvolumedim"
)
# check the SubVolumeRigidSwap is bool
if target_swap_dict_key_i_lower in [
"subvolumerigidswap"
]:
if not isinstance(
target_swap_tag_id_dict_key_data[
"subvolumerigidswap"
],
bool,
):
bad_input_variables_values_list.append(
"subvolumerigidswap"
)
# check the SubVolumePBC is str of only 'X' 'XY' or 'XYZ'
if target_swap_dict_key_i_lower in ["subvolumepbc"]:
if not isinstance(
target_swap_tag_id_dict_key_data[
"subvolumepbc"
],
str,
):
bad_input_variables_values_list.append(
"subvolumepbc"
)
elif isinstance(
target_swap_tag_id_dict_key_data[
"subvolumepbc"
],
str,
) and target_swap_tag_id_dict_key_data[
"subvolumepbc"
].upper() in [
"X",
"XY",
"XZ",
"XYZ",
"Y",
"YZ",
"Z",
]:
self.input_variables_dict[
input_var_keys_list[var_iter]
][tag_id_keys_i][
"subvolumepbc"
] = target_swap_tag_id_dict_key_data[
"subvolumepbc"
].upper()
else:
bad_input_variables_values_list.append(
"subvolumepbc"
)
# check the SubVolumeChempot and is dict {'resname_str': value}
if target_swap_dict_key_i_lower in [
"subvolumechempot"
]:
if not isinstance(
target_swap_tag_id_dict_key_data[
"subvolumechempot"
],
dict,
):
bad_input_variables_values_list.append(
"subvolumechempot"
)
elif isinstance(
target_swap_tag_id_dict_key_data[
"subvolumechempot"
],
dict,
):
self.ck_input_variable_GCMC_dict_str_int_or_float(
target_swap_tag_id_dict_key_data,
"subvolumechempot",
bad_input_variables_values_list,
)
for res_in_sub_chempot_i in list(
target_swap_tag_id_dict_key_data[
"subvolumechempot"
].keys()
):
if (
res_in_sub_chempot_i
not in all_residue_names_list
):
bad_input_variables_values_list.append(
"subvolumechempot"
)
if "subvolumeresiduekind" in list(
target_swap_tag_id_dict_key_data.keys()
):
if isinstance(
target_swap_tag_id_dict_key_data[
"subvolumeresiduekind"
],
list,
):
subvolumechempot_res_list = list(
target_swap_tag_id_dict_key_data[
"subvolumechempot"
].keys()
)
subvolumeresiduekind_res_list = list(
target_swap_tag_id_dict_key_data[
"subvolumeresiduekind"
]
)
for (
subvolumechempot_res_iter
) in subvolumechempot_res_list:
if (
subvolumechempot_res_iter
not in subvolumeresiduekind_res_list
and subvolumeresiduekind_res_list
!= ["ALL"]
and subvolumechempot_res_iter
in all_residue_names_list
):
bad_input_variables_values_list.append(
"subvolumeresiduekind"
)
# check the SubVolumefugacity and is dict {'resname_str': value}
if target_swap_dict_key_i_lower in [
"subvolumefugacity"
]:
if not isinstance(
target_swap_tag_id_dict_key_data[
"subvolumefugacity"
],
dict,
):
bad_input_variables_values_list.append(
"subvolumefugacity"
)
elif isinstance(
target_swap_tag_id_dict_key_data[
"subvolumefugacity"
],
dict,
):
self.ck_input_variable_GCMC_dict_str_int_or_float_zero_or_greater(
target_swap_tag_id_dict_key_data,
"subvolumefugacity",
bad_input_variables_values_list,
)
for res_in_sub_chempot_i in list(
target_swap_tag_id_dict_key_data[
"subvolumefugacity"
].keys()
):
if (
res_in_sub_chempot_i
not in all_residue_names_list
):
bad_input_variables_values_list.append(
"subvolumefugacity"
)
if "subvolumeresiduekind" in list(
target_swap_tag_id_dict_key_data.keys()
):
if isinstance(
target_swap_tag_id_dict_key_data[
"subvolumeresiduekind"
],
list,
):
subvolumefugacity_res_list = list(
target_swap_tag_id_dict_key_data[
"subvolumefugacity"
].keys()
)
subvolumeresiduekind_res_list = list(
target_swap_tag_id_dict_key_data[
"subvolumeresiduekind"
]
)
for (
subvolumefugacity_res_iter
) in subvolumefugacity_res_list:
if (
subvolumefugacity_res_iter
not in subvolumeresiduekind_res_list
and subvolumeresiduekind_res_list
!= ["ALL"]
and subvolumefugacity_res_iter
in all_residue_names_list
):
bad_input_variables_values_list.append(
"subvolumeresiduekind"
)
self.TargetedSwap_DataInput = self.input_variables_dict[key]
# if not a dict
else:
bad_input_variables_values_list.append(key)
# Error out and print the bad input values
if len(bad_input_variables_values_list) > 0:
self.input_error = True
# create unique list
bad_input_variables_values_set = set(
bad_input_variables_values_list
)
bad_unique_input_variables_values_list = list(
bad_input_variables_values_set
)
print_error_message = (
"ERROR: The following input variables have "
"bad values (check spelling and for empty spaces in the keys or that "
"the values are in the correct form with the acceptable values): "
"{}".format(bad_unique_input_variables_values_list)
)
raise ValueError(print_error_message)
else:
print(
"INFO: All the input variable passed the initial error checking"
)
# For the impulse correction term (IPC) is True, check and make sure the LRC is False
# and the potenial is set to VDW or EXP6, otherwise error out.
# If the impulse correction term (IPC) is True and the potenial is set to
# "SHIFT", "SWITCH", or the LRC is True, then error out.
if self.IPC is True and (
self.LRC is True or (self.Potential in ["SHIFT", "SWITCH"])
):
print_error_message = (
"ERROR: The impulse correction term (IPC) can not be set as True "
"if the LRC=True or the Potential is SHIFT or SWITCH."
)
raise ValueError(print_error_message)
if (
self.IPC is False
and self.LRC is False
and (self.Potential in ["VDW", "EXP6"])
):
print_warning_message = (
"WARNING: The impulse correction term (IPC) is False, but likely needs to be True, "
"as the LRC=False when the Potential is VDW or EXP6."
)
warn(print_warning_message)
# check to make sure the VDW FF (ParaTypeCHARMM) is not true for multiple ones
# (i.e., ParaTypeCHARMM, ParaTypeMie, ParaTypeMARTINI)
if (
(self.ParaTypeCHARMM is True and self.ParaTypeMie is True)
or (self.ParaTypeCHARMM is True and self.ParaTypeMARTINI is True)
or self.ParaTypeMie is True
and self.ParaTypeMARTINI is True
):
self.input_error = True
print_error_message = (
"ERROR: there can only be 1 VDW type set to true. Please set only one of the "
"ParaTypeCHARMM = {}, ParaTypeMie = {}, ParaTypeMARTINI = {} types "
"to True".format(
self.ParaTypeCHARMM, self.ParaTypeMie, self.ParaTypeMARTINI
)
)
raise ValueError(print_error_message)
elif (
self.ParaTypeCHARMM is True
or self.ParaTypeMie is True
or self.ParaTypeMARTINI is True
):
if self.ParaTypeCHARMM is True:
self.VDW_type = "ParaTypeCHARMM"
elif self.ParaTypeMie is True:
self.VDW_type = "ParaTypeMie"
elif self.ParaTypeMARTINI is True:
self.VDW_type = "ParaTypeMARTINI"
else:
self.input_error = True
print_error_message = (
"ERROR: There no VDW types that are set as True. Please set only one of the "
"ParaTypeCHARMM = {}, ParaTypeMie = {}, ParaTypeMARTINI = {} types "
"to True".format(
self.ParaTypeCHARMM, self.ParaTypeMie, self.ParaTypeMARTINI
)
)
raise ValueError(print_error_message)
# check to see if the moves sum up to 1
if ensemble_type in ["NVT", "GCMC"]:
if self.VolFreq != 0 and self.ExpertMode is False:
self.input_error = True
print_error_message = (
"ERROR: The input variable VolFreq is non-zero (0). "
'VolFreq must be zero (0) for the "NVT", "GEMC_NVT", and "GCMC" ensembles.'
)
raise ValueError(print_error_message)
if ensemble_type in ["NVT", "NPT"]:
if (
self.SwapFreq != 0
or self.MEMC_1Freq != 0
or self.MEMC_2Freq != 0
or self.MEMC_3Freq != 0
):
self.input_error = True
print_error_message = (
"ERROR: All the MC move input variables must be non-zero (0) for the "
"SwapFreq, MEMC-1Freq, MEMC-2Freq, and MEMC-3Freq. "
"The SwapFreq, MEMC-1Freq, MEMC-2Freq, "
'and MEMC-3Freq need to be zero (0) for the "NVT" and "NPT" ensembles.'
)
raise ValueError(print_error_message)
moves_list = [
self.DisFreq,
self.RotFreq,
self.IntraSwapFreq,
self.SwapFreq,
self.RegrowthFreq,
self.CrankShaftFreq,
self.VolFreq,
self.MultiParticleFreq,
self.IntraMEMC_1Freq,
self.MEMC_1Freq,
self.IntraMEMC_2Freq,
self.MEMC_2Freq,
self.IntraMEMC_3Freq,
self.MEMC_3Freq,
self.TargetedSwapFreq,
self.IntraTargetedSwapFreq,
]
if sum(moves_list) <= 1 + 10 ** (-13) and sum(moves_list) >= 1 - 10 ** (
-13
):
print(
"INFO: The sum of the Monte Carlo move ratios = "
+ str("{:.12f}".format(sum(moves_list)))
)
else:
print(
"INFO: sum(moves_list) = "
+ str("{:.12f}".format(sum(moves_list)))
)
print("\t DisFreq = " + str(self.DisFreq))
print("\t RotFreq = " + str(self.RotFreq))
print("\t IntraSwapFreq = " + str(self.IntraSwapFreq))
print("\t SwapFreq = " + str(self.SwapFreq))
print("\t RegrowthFreq = " + str(self.RegrowthFreq))
print("\t CrankShaftFreq = " + str(self.CrankShaftFreq))
print("\t VolFreq = " + str(self.VolFreq))
print("\t MultiParticleFreq = " + str(self.MultiParticleFreq))
print("\t IntraMEMC-1Freq = " + str(self.IntraMEMC_1Freq))
print("\t MEMC-1Freq = " + str(self.MEMC_1Freq))
print("\t IntraMEMC-2Freq = " + str(self.IntraMEMC_2Freq))
print("\t MEMC-2Freq = " + str(self.MEMC_2Freq))
print("\t IntraMEMC-3Freq = " + str(self.IntraMEMC_3Freq))
print("\t MEMC-3Freq = " + str(self.MEMC_3Freq))
print("\t TargetedSwapFreq = " + str(self.TargetedSwapFreq))
print(
"\t IntraTargetedSwapFreq = " + str(self.IntraTargetedSwapFreq)
)
self.input_error = True
print_error_message = (
"ERROR: The sum of the Monte Carlo move ratios does not equal 1. "
"Note: The sum that was manually entered may equal 1, but some "
"moves may not be valid for the provided ensemble. The moves "
"that are invalid for a given ensemble are set to zero. If "
"the default moves are not being used, all the move frequencies "
"which do not have default values of zero will need to be set manually "
"so the sum equals (DisFreq, RotFreq, IntraSwapFreq, SwapFreq, "
"RegrowthFreq, CrankShaftFreq, and VolFreq)."
)
raise ValueError(print_error_message)
# Check that RunSteps > EqSteps >= AdjSteps
print("self.RunSteps = " + str(self.RunSteps))
if (
self.RunSteps <= self.EqSteps
or self.RunSteps < self.AdjSteps
or self.EqSteps < self.AdjSteps
) and self.Restart is False:
self.input_error = True
print_error_message = (
"ERROR: When starting a simulation, the values must be in this order RunSteps > EqSteps >= AdjSteps "
"({} > {} >= {})".format(
self.RunSteps, self.EqSteps, self.AdjSteps
)
)
raise ValueError(print_error_message)
elif (self.RunSteps <= self.EqSteps) and self.Restart is True:
self.input_error = True
print_error_message = (
"ERROR: When restarting a simulation, this must be true RunSteps > EqSteps "
"({} > {})".format(self.RunSteps, self.EqSteps)
)
raise ValueError(print_error_message)
# check if both the ChemPot and Fugacity are not set to None. Only one can be used
if (
self.Fugacity is not None
and self.ChemPot is not None
and self.ensemble_type == "GCMC"
):
self.input_error = True
print_error_message = (
"ERROR: In the GCMC ensemble, both Fugacity and ChemPot are provided. "
"Add a dictionary for either the Fugacity or ChemPot and set the other "
"variable to None. Note: Both the Fugacity or ChemPot and set to None by default"
)
raise ValueError(print_error_message)
# check that both the ChemPot and Fugacity are set to None. Only one can be used
if (
self.Fugacity is None
and self.ChemPot is None
and self.ensemble_type == "GCMC"
):
warn(
"ERROR: In the GCMC ensemble, neither Fugacity and ChemPot are provided (i.e., both are None). "
"Add a dictionary for either the Fugacity or ChemPot and set the other variable to None. "
"Note: Both the Fugacity or ChemPot and set to None by default"
)
self.input_error = True
print_error_message = (
"ERROR: In the GCMC ensemble, neither Fugacity and ChemPot are provided "
"(i.e., both are None). Add a dictionary for either the Fugacity or "
"ChemPot and set the other variable to None. "
"Note: Both the Fugacity or ChemPot and set to None by default"
)
raise ValueError(print_error_message)
# check that TargetedSwap_DataInput values are provided if self.TargetedSwapFreq
# and self.IntraTargetedSwapFreq is not zero
if self.TargetedSwap_DataInput is None and (
self.TargetedSwapFreq != 0 or self.IntraTargetedSwapFreq != 0
):
self.input_error = True
print_error_message = (
"ERROR: The TargetedSwap_DataInput variable is equal to None, "
"but the TargetedSwapFreq or IntraTargetedSwapFreq move ratio is non-zero."
)
raise ValueError(print_error_message)
# check that either the ChemPot or Fugacity are set for the Target swap moves
# only ChemPot or Fugacity can be set
if isinstance(self.TargetedSwap_DataInput, dict):
chempot_used = False
fugacity_used = False
for tag_id_keys_j in list(self.TargetedSwap_DataInput.keys()):
target_swap_tag_id_dict_key_data = self.TargetedSwap_DataInput[
tag_id_keys_j
]
for target_swap_dict_key_j_lower in list(
target_swap_tag_id_dict_key_data.keys()
):
if target_swap_dict_key_j_lower in ["subvolumechempot"]:
chempot_used = True
if target_swap_dict_key_j_lower in ["subvolumefugacity"]:
fugacity_used = True
if chempot_used is True and fugacity_used is True:
print_error_message = (
"Both ChemPot and Fugacity were used in the "
"TargetedSwap_DataInput dictionaries. "
"However, only ChemPot or Fugacity may be used, not both."
)
raise ValueError(print_error_message)
if (chempot_used is True and self.Fugacity is not None) or (
fugacity_used is True and self.ChemPot is not None
):
print_error_message = (
"Both ChemPot and Fugacity were used in the "
"TargetedSwap_DataInput dictionaries "
"and in the standard GOMC swap inputs. "
"However, only ChemPot or Fugacity may be used, not both."
)
raise ValueError(print_error_message)
if (
chempot_used is True or fugacity_used is True
) and self.ensemble_type in ["NPT", "NVT", "GEMC_NVT", "GEMC_NPT"]:
print_error_message = (
"Either the ChemPot and Fugacity were used in the "
"TargetedSwap_DataInput dictionaries, "
"which can not be used for the 'NPT', 'NVT', 'GEMC_NVT', "
"or 'GEMC_NPT' ensembles."
)
raise ValueError(print_error_message)
# check if every TargetedSwap_DataInput has all the required values
required_ts_datainput_keys_main = [
"subvolumetype",
"subvolumebox",
"subvolumedim",
"subvolumeresiduekind",
"subvolumerigidswap",
"subvolumepbc",
]
required_ts_datainput_keys_static_adder = ["subvolumecenter"]
required_ts_datainput_keys_dynamic_adder = ["subvolumecenterlist"]
required_ts_datainput_keys_GCMC_chempot_adder = ["subvolumechempot"]
required_ts_datainput_keys_GCMC_fugacity_adder = [
"subvolumefugacity"
]
for ts_tag_i in list(self.TargetedSwap_DataInput.keys()):
all_potential_keys = (
required_ts_datainput_keys_main
+ required_ts_datainput_keys_static_adder
+ required_ts_datainput_keys_dynamic_adder
+ required_ts_datainput_keys_GCMC_chempot_adder
+ required_ts_datainput_keys_GCMC_fugacity_adder
)
print_error_message = (
f"The TargetedSwap_DataInput dictionaries do not have all the required "
f"keys or inputs per the subvolumetype and specified ensemble. "
f"Remember that the 'subvolumetype' values are 'static' and 'dynamic', "
f"which must only have the cooresponding "
f"'subvolumecenter' and 'subvolumecenterlist' values, respectively,"
f" in each subvolume."
)
required_ts_datainput_total = []
if "subvolumetype" in self.TargetedSwap_DataInput[ts_tag_i]:
if (
self.TargetedSwap_DataInput[ts_tag_i]["subvolumetype"]
== "dynamic"
):
required_ts_datainput_total = (
required_ts_datainput_keys_main
+ required_ts_datainput_keys_dynamic_adder
)
elif (
self.TargetedSwap_DataInput[ts_tag_i]["subvolumetype"]
== "static"
):
required_ts_datainput_total = (
required_ts_datainput_keys_main
+ required_ts_datainput_keys_static_adder
)
if self.ensemble_type in ["GCMC"]:
if (
"subvolumefugacity"
in self.TargetedSwap_DataInput[ts_tag_i]
):
required_ts_datainput_total += (
required_ts_datainput_keys_GCMC_fugacity_adder
)
elif (
"subvolumechempot"
in self.TargetedSwap_DataInput[ts_tag_i]
):
required_ts_datainput_total += (
required_ts_datainput_keys_GCMC_chempot_adder
)
# fail build if all subvolume keys are not provided,
# set default values of SubVolumeRigidSwap and SubVolumePBC if not found
for subvolume_keys_j in required_ts_datainput_total:
if subvolume_keys_j not in list(
self.TargetedSwap_DataInput[ts_tag_i].keys()
):
# set default values of SubVolumeRigidSwap or SubVolumePBC to
# default value, if not provided
if subvolume_keys_j in [
"subvolumerigidswap",
"subvolumepbc",
]:
self.TargetedSwap_DataInput[ts_tag_i].update(
{
subvolume_keys_j: _get_default_variables_dict()[
subvolume_keys_j
]
}
)
else:
raise ValueError(print_error_message)
else:
raise ValueError(print_error_message)
# check that MEMC moves rations are > 0 if MEMC_DataInput is used
if self.MEMC_DataInput is not None and (
self.MEMC_1Freq == 0
and self.MEMC_2Freq == 0
and self.MEMC_3Freq == 0
and self.IntraMEMC_1Freq == 0
and self.IntraMEMC_2Freq == 0
and self.IntraMEMC_3Freq == 0
):
self.input_error = True
print_error_message = (
"ERROR: The MEMC_DataInput variable is not equal to None, "
"but all the MEMC move ratios are "
"zero (IntraMEMC-1Freq, MEMC-1Freq, IntraMEMC-2Freq, MEMC-2Freq, "
"IntraMEMC-3Freq, and MEMC-3Freq)."
)
raise ValueError(print_error_message)
if self.MEMC_DataInput is None and (
self.MEMC_1Freq != 0
or self.MEMC_2Freq != 0
or self.MEMC_3Freq != 0
or self.IntraMEMC_1Freq != 0
or self.IntraMEMC_2Freq != 0
or self.IntraMEMC_3Freq != 0
):
self.input_error = True
print_error_message = (
"ERROR: The MEMC_DataInput variable is equal to None, "
"but at least one of the MEMC move ratios are "
"all non-zero (IntraMEMC-1Freq, MEMC-1Freq, IntraMEMC-2Freq, MEMC-2Freq, "
"IntraMEMC-3Freq, and MEMC-3Freq)."
)
raise ValueError(print_error_message)
# ensure the LargeKindBackBone and SmallKindBackBones are provided as appropriate for MEMC-1, MEMC-2, MEMC-3
if self.MEMC_DataInput is not None and (
self.MEMC_2Freq > 0 or self.IntraMEMC_2Freq > 0
):
for MEMC_2_i in range(0, len(self.MEMC_DataInput)):
if (
self.MEMC_DataInput[MEMC_2_i][2][0] is None
or self.MEMC_DataInput[MEMC_2_i][2][1] is None
or self.MEMC_DataInput[MEMC_2_i][4][0] is None
or self.MEMC_DataInput[MEMC_2_i][4][1] is None
):
self.input_error = True
print_error_message = (
"ERROR: The LargeKindBackBone and SmallKindBackBones unique "
"atom names, strings, both must be provided when using the "
"IntraMEMC-2Freq or MEMC-2Freq moves "
"(i.e., the LargeKindBackBone and SmallKindBackBones can not be None). "
)
raise ValueError(print_error_message)
if self.MEMC_DataInput is not None and (
self.MEMC_3Freq > 0 or self.IntraMEMC_3Freq > 0
):
for MEMC_3_i in range(0, len(self.MEMC_DataInput)):
if (
self.MEMC_DataInput[MEMC_3_i][2][0] is None
or self.MEMC_DataInput[MEMC_3_i][2][1] is None
):
self.input_error = True
print_error_message = (
"ERROR: The LargeKindBackBone unique atom names, strings, "
"both must be provided when using the IntraMEMC-3Freq or MEMC-3Freq moves "
"(i.e., the LargeKindBackBone can not be None)."
)
raise ValueError(print_error_message)
# check that all required free energy values are provided and RcutLow is zero (0)
if (
self.FreeEnergyCalc is not None
or self.MoleculeType is not None
or self.InitialState is not None
or self.LambdaVDW is not None
):
if (
self.FreeEnergyCalc is None
or self.MoleculeType is None
or self.InitialState is None
or self.LambdaVDW is None
):
self.input_error = True
print_error_message = (
"ERROR: To utilize the free energy calculations all the following "
"variables need to be set, and not equal to None: "
"FreeEnergyCalc, MoleculeType, InitialState, LambdaVDW."
)
raise ValueError(print_error_message)
if self.RcutLow != 0:
print_warning_message = (
"WARNING: The free energy calculations are being used when RcutLow is not zero (0), "
"which can produce free energy results that are slightly off or wrong. "
"Please set RcutLow to zero (RcutLow=0) when using the free energy calculations."
)
warn(print_warning_message)
if (
self.LambdaVDW is not None
and self.LambdaCoulomb is not None
and isinstance(self.LambdaVDW, list) is True
and (isinstance(self.LambdaCoulomb, list)) is True
):
if len(self.LambdaVDW) == len(self.LambdaCoulomb):
if self.InitialState + 1 <= len(self.LambdaVDW):
for lam_i in range(1, len(self.LambdaVDW)):
if self.LambdaVDW[lam_i] < self.LambdaVDW[lam_i - 1]:
self.input_error = True
print_error_message = "ERROR: The LambdaVDW list is not in accending order."
raise ValueError(print_error_message)
if (
self.LambdaCoulomb[lam_i]
< self.LambdaCoulomb[lam_i - 1]
):
self.input_error = True
print_error_message = "ERROR: The LambdaCoulomb list is not in accending order."
raise ValueError(print_error_message)
else:
self.input_error = True
print_error_message = (
"ERROR: The InitialState integer is greater than the LambdaVDW and "
"LambdaCoulomb list length. Note: the InitialState integer starts at 0."
)
raise ValueError(print_error_message)
else:
self.input_error = True
print_error_message = "ERROR: The LambdaVDW and LambdaCoulomb list must be of equal length."
raise ValueError(print_error_message)
# check self.LambdaVDW and LambdaCoulomb last value is 1.0
if self.ensemble_type in ["NVT", "NPT"]:
if isinstance(self.LambdaVDW, list):
if len(self.LambdaVDW) > 0:
if self.LambdaVDW[-1] != 1.0:
print_error_message = "ERROR: The last value in the LambdaVDW variable list must be a 1.0"
raise ValueError(print_error_message)
if self.LambdaVDW[0] != 0.0:
print_error_message = "ERROR: The first value in the LambdaVDW variable list must be a 0.0"
raise ValueError(print_error_message)
if isinstance(self.LambdaCoulomb, list):
if len(self.LambdaCoulomb) > 0:
if self.LambdaCoulomb[-1] != 1.0:
print_error_message = "ERROR: The last value in the LambdaCoulomb variable list must be a 1.0"
raise ValueError(print_error_message)
if self.LambdaCoulomb[0] != 0.0:
print_error_message = "ERROR: The first value in the LambdaCoulomb variable list must be a 0.0"
raise ValueError(print_error_message)
# write the control file
def write_conf_file(self, conf_filename):
"""
Writes the GOMC control file.
Parameters
----------
conf_filename: str
The path and file name for the control file name, with
the .conf extension, or no extension. If no extension is provided, the
code will add the .conf extension to the provided file name.
Returns
---------
Writes the GOMC control file with the name provided via conf_filename
If completed without errors: str, "PASSED
If completed with errors : None
"""
# check to see if it is OK to proceed writing the control file
if self.input_error is True:
print_error_message = (
"ERROR: The control file was not written as at least 1 input to the "
"control file writer was bad."
)
raise ValueError(print_error_message)
date_time = datetime.datetime.today()
self.conf_filename = conf_filename
if (
isinstance(self.conf_filename, str) is False
or isinstance(self.conf_filename, str) is None
):
self.input_error = True
print_error_message = "ERROR: The control file name (conf_filename) is not provided as a string. "
raise ValueError(print_error_message)
if os.path.splitext(self.conf_filename)[1] == ".conf":
self.conf_filename = conf_filename
print(
"INFO: the correct extension for the control file was provided in the file name, .conf "
"with control file name = " + str(self.conf_filename)
)
elif os.path.splitext(self.conf_filename)[1] == "":
self.conf_filename = self.conf_filename + ".conf"
print(
"INFO: No extension name was provided for the control file. Therefore, the proper "
"extension, .conf, was added. The new total control file name = {}".format(
self.conf_filename
)
)
else:
self.input_error = True
print_error_message = (
"ERROR: No extension name or the wrong extension name was provided. "
"Please enter a proper extension name, .conf or no extension in the conf_filename "
"The control file as provided name = {}".format(
self.conf_filename
)
)
raise ValueError(print_error_message)
# get and open the control file file
data_control_file = open(self.conf_filename, "w")
data_control_file.write(
"#######################################################"
"#########################################\n"
)
data_control_file.write(
"## This file ({}) - was created by mBuild "
"using the on {}\n".format(self.conf_filename, date_time)
)
data_control_file.write(
"#######################################################"
"#########################################\n"
)
data_control_file.write("\n")
data_control_file.write(
"############################################################################\n"
)
data_control_file.write(
"# ---------------------------- INPUT ------------------------------------- \n"
)
data_control_file.write(
"############################################################################\n"
)
data_control_file.write(" \n")
data_control_file.write("####################################\n")
data_control_file.write("# enable, step\n")
data_control_file.write("####################################\n")
data_control_file.write("{:25s} {}\n".format("Restart", self.Restart))
data_control_file.write("\n")
data_control_file.write(
"{:25s} {}\n".format("RestartCheckpoint", self.RestartCheckpoint)
)
data_control_file.write("\n")
data_control_file.write(
"{:25s} {}\n".format("ExpertMode", self.ExpertMode)
)
data_control_file.write("\n")
data_control_file.write("####################################\n")
data_control_file.write("# kind {RESTART, RANDOM, INTSEED}\n")
data_control_file.write("####################################\n")
if self.PRNG == "RANDOM":
data_control_file.write("{:25s} {}\n".format("PRNG", self.PRNG))
elif isinstance(self.PRNG, int):
data_control_file.write("PRNG \t\t " + "INTSEED \n")
data_control_file.write(
"{:25s} {}\n".format("Random_Seed", self.PRNG)
)
data_control_file.write(" \n")
data_control_file.write("####################################\n")
data_control_file.write("# FORCE FIELD\n")
data_control_file.write("####################################\n")
data_control_file.write(
"{:25s} {}\n".format(str(self.VDW_type), str(True))
)
data_control_file.write(" \n")
data_control_file.write(
"{:25s} {}\n".format("Parameters", self.ff_filename)
)
data_control_file.write("####################################\n")
data_control_file.write("# INPUT PDB FILES\n")
data_control_file.write("####################################\n")
if self.ensemble_type in ["NVT", "NPT", "GEMC_NPT", "GEMC_NVT", "GCMC"]:
data_control_file.write(
"{:25s} {}\n".format("Coordinates 0", self.Coordinates_box_0)
)
if self.ensemble_type in ["GEMC_NPT", "GEMC_NVT", "GCMC"]:
data_control_file.write(
"{:25s} {}\n".format("Coordinates 1", self.Coordinates_box_1)
)
data_control_file.write(" \n")
data_control_file.write("####################################\n")
data_control_file.write("# INPUT PSF FILES\n")
data_control_file.write("####################################\n")
if self.ensemble_type in ["NVT", "NPT", "GEMC_NPT", "GEMC_NVT", "GCMC"]:
data_control_file.write(
"{:25s} {}\n".format("Structure 0", self.Structure_box_0)
)
if self.ensemble_type in ["GEMC_NPT", "GEMC_NVT", "GCMC"]:
data_control_file.write(
"{:25s} {}\n".format("Structure 1", self.Structure_box_1)
)
if (
self.Restart is True
and self.binCoordinates_box_0 is not None
and self.extendedSystem_box_0 is not None
and self.ensemble_type
in ["NVT", "NPT", "GEMC_NPT", "GEMC_NVT", "GCMC"]
):
data_control_file.write(" \n")
data_control_file.write("####################################\n")
data_control_file.write(
"# INPUT FILES FOR RESTARTING (COORDINATE, XSC, VELOCITY FILES)\n"
)
data_control_file.write("####################################\n")
data_control_file.write(
"{:25s} {}\n".format(
"binCoordinates 0", self.binCoordinates_box_0
)
)
data_control_file.write(
"{:25s} {}\n".format(
"extendedSystem 0", self.extendedSystem_box_0
)
)
if self.binVelocities_box_0 is not None:
data_control_file.write(
"{:25s} {}\n".format(
"binVelocities 0", self.binVelocities_box_0
)
)
data_control_file.write(" \n")
if (
self.binCoordinates_box_1 is not None
and self.extendedSystem_box_1 is not None
and self.ensemble_type in ["GEMC_NPT", "GEMC_NVT", "GCMC"]
):
data_control_file.write(
"{:25s} {}\n".format(
"binCoordinates 1", self.binCoordinates_box_1
)
)
data_control_file.write(
"{:25s} {}\n".format(
"extendedSystem 1", self.extendedSystem_box_1
)
)
if self.binVelocities_box_1 is not None:
data_control_file.write(
"{:25s} {}\n".format(
"binVelocities 1", self.binVelocities_box_1
)
)
data_control_file.write(" \n")
data_control_file.write(
"############################################################################\n"
)
data_control_file.write(
"# ---------------------------- SYSTEM -------------------------------------\n"
)
data_control_file.write(
"############################################################################ \n"
)
data_control_file.write(" \n")
if self.ensemble_type in ["GEMC_NPT", "GEMC_NVT"]:
data_control_file.write("####################################\n")
data_control_file.write("# GEMC TYPE \n")
data_control_file.write("####################################\n")
if self.ensemble_type in "GEMC_NPT":
data_control_file.write("GEMC \t\t NPT \n")
elif self.ensemble_type in "GEMC_NVT":
data_control_file.write("GEMC \t\t NVT \n")
data_control_file.write(" \n")
data_control_file.write("####################################\n")
data_control_file.write("# SIMULATION CONDITION\n")
data_control_file.write("####################################\n")
data_control_file.write(
"{:25s} {}\n".format("Temperature", self.Temperature)
)
if self.ensemble_type in ["GEMC_NPT", "NPT"]:
data_control_file.write(
"{:25s} {}\n".format("Pressure", self.Pressure)
)
data_control_file.write(
"{:25s} {}\n".format("useConstantArea", self.useConstantArea)
)
if self.ensemble_type in ["GEMC_NPT"] and self.FixVolBox0 is True:
data_control_file.write(
"{:25s} {}\n".format("FixVolBox0", self.FixVolBox0)
)
if (
self.ensemble_type in ["GCMC"]
and self.ChemPot is not None
and self.Fugacity is None
):
chem_pot_dict_key_list = dict_keys_to_list(self.ChemPot)
for chem_pot_iter in range(0, len(chem_pot_dict_key_list)):
chem_pot_residue_iter = chem_pot_dict_key_list[chem_pot_iter]
data_control_file.write(
"{:25s} {:10s} {}\n".format(
"ChemPot",
chem_pot_residue_iter,
self.ChemPot[chem_pot_residue_iter],
)
)
if (
self.ensemble_type in ["GCMC"]
and self.Fugacity is not None
and self.ChemPot is None
):
fugacity_iter_dict_key_list = dict_keys_to_list(self.Fugacity)
for fugacity_iter in range(0, len(fugacity_iter_dict_key_list)):
fugacity_residue_iter = fugacity_iter_dict_key_list[
fugacity_iter
]
data_control_file.write(
"{:25s} {:10s} {}\n".format(
"Fugacity",
fugacity_residue_iter,
self.Fugacity[fugacity_residue_iter],
)
)
data_control_file.write(" \n")
data_control_file.write(
"{:25s} {}\n".format("Potential", self.Potential)
)
data_control_file.write("{:25s} {}\n".format("LRC", self.LRC))
data_control_file.write("{:25s} {}\n".format("IPC", self.IPC))
data_control_file.write("{:25s} {}\n".format("Rcut", self.Rcut))
data_control_file.write("{:25s} {}\n".format("RcutLow", self.RcutLow))
if self.Potential == "SWITCH":
data_control_file.write(
"{:25s} {}\n".format("Rswitch", self.Rswitch)
)
data_control_file.write("{:25s} {}\n".format("Exclude", self.Exclude))
data_control_file.write(
"{:25s} {}\n".format("VDWGeometricSigma", self.VDWGeometricSigma)
)
data_control_file.write(" \n")
data_control_file.write("####################################\n")
data_control_file.write("# ELECTROSTATIC \n")
data_control_file.write("####################################\n")
data_control_file.write("{:25s} {}\n".format("Ewald", self.Ewald))
data_control_file.write(
"{:25s} {}\n".format("ElectroStatic", self.ElectroStatic)
)
data_control_file.write(
"{:25s} {}\n".format("CachedFourier", self.CachedFourier)
)
data_control_file.write(
"{:25s} {}\n".format("Tolerance", str(self.Tolerance))
)
if self.VDW_type in ["ParaTypeMARTINI"]:
data_control_file.write(
"{:25s} {}\n".format("Dielectric", format(self.Dielectric))
)
data_control_file.write(
"{:25s} {}\n".format("1-4scaling", self.coul_1_4)
)
data_control_file.write(" \n")
if self.RcutCoulomb_box_0 is not None:
data_control_file.write(
"{:25s} {}\n".format("RcutCoulomb 0", self.RcutCoulomb_box_0)
)
if self.RcutCoulomb_box_1 is not None and self.ensemble_type in [
"GEMC_NPT",
"GEMC_NVT",
"GCMC",
]:
data_control_file.write(
"{:25s} {}\n".format("RcutCoulomb 1", self.RcutCoulomb_box_1)
)
data_control_file.write(" \n")
data_control_file.write("####################################\n")
data_control_file.write("# PRESSURE CALCULATION\n")
data_control_file.write("####################################\n")
data_control_file.write(
"{:25s} {:10s} {}\n".format(
"PressureCalc",
str(self.PressureCalc[0]),
self.PressureCalc[1],
)
)
data_control_file.write(" \n")
data_control_file.write("####################################\n")
data_control_file.write("# STEPS \n")
data_control_file.write("####################################\n")
data_control_file.write("{:25s} {}\n".format("RunSteps", self.RunSteps))
data_control_file.write("{:25s} {}\n".format("EqSteps", self.EqSteps))
data_control_file.write("{:25s} {}\n".format("AdjSteps", self.AdjSteps))
data_control_file.write(" \n")
data_control_file.write("####################################\n")
data_control_file.write("# MOVE FREQUENCY \n")
data_control_file.write("####################################\n")
mc_move_zero_error_tolerance = 10 ** (-14)
if self.DisFreq > mc_move_zero_error_tolerance:
data_control_file.write(
"{:25s} {}\n".format("DisFreq", self.DisFreq)
)
if self.RotFreq > mc_move_zero_error_tolerance:
data_control_file.write(
"{:25s} {}\n".format("RotFreq", self.RotFreq)
)
if self.IntraSwapFreq > mc_move_zero_error_tolerance:
data_control_file.write(
"{:25s} {}\n".format("IntraSwapFreq", self.IntraSwapFreq)
)
if self.SwapFreq > mc_move_zero_error_tolerance:
data_control_file.write(
"{:25s} {}\n".format("SwapFreq", self.SwapFreq)
)
if self.RegrowthFreq > mc_move_zero_error_tolerance:
data_control_file.write(
"{:25s} {}\n".format("RegrowthFreq", self.RegrowthFreq)
)
if self.CrankShaftFreq > mc_move_zero_error_tolerance:
data_control_file.write(
"{:25s} {}\n".format("CrankShaftFreq", self.CrankShaftFreq)
)
if self.VolFreq > mc_move_zero_error_tolerance:
data_control_file.write(
"{:25s} {}\n".format("VolFreq", self.VolFreq)
)
if self.MultiParticleFreq > mc_move_zero_error_tolerance:
data_control_file.write(
"{:25s} {}\n".format(
"MultiParticleFreq", self.MultiParticleFreq
)
)
if self.IntraMEMC_1Freq > mc_move_zero_error_tolerance:
data_control_file.write(
"{:25s} {}\n".format("IntraMEMC-1Freq", self.IntraMEMC_1Freq)
)
if self.MEMC_1Freq > mc_move_zero_error_tolerance:
data_control_file.write(
"{:25s} {}\n".format("MEMC-1Freq", self.MEMC_1Freq)
)
if self.IntraMEMC_2Freq > mc_move_zero_error_tolerance:
data_control_file.write(
"{:25s} {}\n".format("IntraMEMC-2Freq", self.IntraMEMC_2Freq)
)
if self.MEMC_2Freq > mc_move_zero_error_tolerance:
data_control_file.write(
"{:25s} {}\n".format("MEMC-2Freq", self.MEMC_2Freq)
)
if self.IntraMEMC_3Freq > mc_move_zero_error_tolerance:
data_control_file.write(
"{:25s} {}\n".format("IntraMEMC-3Freq", self.IntraMEMC_3Freq)
)
if self.MEMC_3Freq > mc_move_zero_error_tolerance:
data_control_file.write(
"{:25s} {}\n".format("MEMC-3Freq", self.MEMC_3Freq)
)
if self.TargetedSwapFreq > mc_move_zero_error_tolerance:
data_control_file.write(
"{:25s} {}\n".format("TargetedSwapFreq", self.TargetedSwapFreq)
)
if self.IntraTargetedSwapFreq > mc_move_zero_error_tolerance:
data_control_file.write(
"{:25s} {}\n".format(
"IntraTargetedSwapFreq", self.IntraTargetedSwapFreq
)
)
data_control_file.write(" \n")
# sort and print the MEMC data if MEMC is used for the simulation
if self.MEMC_DataInput is not None and (
self.MEMC_1Freq > 0
or self.MEMC_2Freq > 0
or self.MEMC_3Freq > 0
or self.IntraMEMC_1Freq > 0
or self.IntraMEMC_2Freq > 0
or self.IntraMEMC_3Freq > 0
):
ExchangeRatio_list = []
ExchangeLargeKind_list = []
LargeKindBackBone_list = []
ExchangeSmallKind_list = []
SmallKindBackBone_list = []
for memc_i in range(0, len(self.MEMC_DataInput)):
ExchangeRatio_list.append(
str("{:10s} \t".format(str(self.MEMC_DataInput[memc_i][0])))
)
ExchangeLargeKind_list.append(
"{:10s} \t".format(str(self.MEMC_DataInput[memc_i][1]))
)
LargeKindBackBone_list.append(
"{:4s} {:4s} \t".format(
str(self.MEMC_DataInput[memc_i][2][0]),
str(self.MEMC_DataInput[memc_i][2][1]),
)
)
ExchangeSmallKind_list.append(
"{:10s} \t".format(str(self.MEMC_DataInput[memc_i][3]))
)
SmallKindBackBone_list.append(
"{:4s} {:4s} \t".format(
str(self.MEMC_DataInput[memc_i][4][0]),
str(self.MEMC_DataInput[memc_i][4][1]),
)
)
ExchangeRatio_str = "".join(ExchangeRatio_list)
ExchangeLargeKind_str = "".join(ExchangeLargeKind_list)
LargeKindBackBone_str = "".join(LargeKindBackBone_list)
ExchangeSmallKind_str = "".join(ExchangeSmallKind_list)
SmallKindBackBone_str = "".join(SmallKindBackBone_list)
data_control_file.write("####################################\n")
data_control_file.write("# MEMC PARAMETER \n")
data_control_file.write("####################################\n")
data_control_file.write(
"{:25s} {}\t{}\t{}\n".format(
"ExchangeVolumeDim",
self.ExchangeVolumeDim[0],
self.ExchangeVolumeDim[1],
self.ExchangeVolumeDim[2],
)
)
data_control_file.write(
"{:25s} {}\n".format("ExchangeRatio", ExchangeRatio_str)
)
data_control_file.write(
"{:25s} {}\n".format("ExchangeLargeKind", ExchangeLargeKind_str)
)
data_control_file.write(
"{:25s} {}\n".format("ExchangeSmallKind", ExchangeSmallKind_str)
)
if self.MEMC_DataInput is not None and (
self.MEMC_2Freq > 0
or self.IntraMEMC_2Freq > 0
or self.MEMC_3Freq > 0
or self.IntraMEMC_3Freq > 0
):
data_control_file.write(
"{:25s} {}\n".format(
"LargeKindBackBone", LargeKindBackBone_str
)
)
if self.MEMC_DataInput is not None and (
self.MEMC_2Freq > 0 or self.IntraMEMC_2Freq > 0
):
data_control_file.write(
"{:25s} {}\n".format(
"SmallKindBackBone", SmallKindBackBone_str
)
)
data_control_file.write(" \n")
if self.TargetedSwap_DataInput is not None:
data_control_file.write("####################################\n")
data_control_file.write(
"# TARGETED SWAP PARAMETERS (only available in the GCMC and NPT ensembles) \n"
)
data_control_file.write("####################################\n")
for sub_vol_tag_id_i in list(self.TargetedSwap_DataInput.keys()):
data_control_file.write(
"{:30s} {:10s} {:10s}\n".format(
"SubVolumeBox",
str(sub_vol_tag_id_i),
str(
self.TargetedSwap_DataInput[sub_vol_tag_id_i][
"subvolumebox"
]
),
)
)
if (
self.TargetedSwap_DataInput[sub_vol_tag_id_i][
"subvolumetype"
]
== "static"
):
data_control_file.write(
"{:30s} {:10s} {:10s} {:10s} {:10s}\n".format(
"SubVolumeCenter",
str(sub_vol_tag_id_i),
str(
self.TargetedSwap_DataInput[sub_vol_tag_id_i][
"subvolumecenter"
][0]
),
str(
self.TargetedSwap_DataInput[sub_vol_tag_id_i][
"subvolumecenter"
][1]
),
str(
self.TargetedSwap_DataInput[sub_vol_tag_id_i][
"subvolumecenter"
][2]
),
)
)
elif (
self.TargetedSwap_DataInput[sub_vol_tag_id_i][
"subvolumetype"
]
== "dynamic"
):
data_control_file.write(
"{:30s} {:10s} {:10s} {:10s} {:10s}\n".format(
"SubVolumeCenterList",
str(sub_vol_tag_id_i),
str(
self.TargetedSwap_DataInput[sub_vol_tag_id_i][
"subvolumecenterlist"
][0]
),
str(
self.TargetedSwap_DataInput[sub_vol_tag_id_i][
"subvolumecenterlist"
][1]
),
str(
self.TargetedSwap_DataInput[sub_vol_tag_id_i][
"subvolumecenterlist"
][2]
),
)
)
# get the SubVolumeDim
data_control_file.write(
"{:30s} {:10s} {:10s} {:10s} {:10s}\n".format(
"SubVolumeDim",
str(sub_vol_tag_id_i),
str(
self.TargetedSwap_DataInput[sub_vol_tag_id_i][
"subvolumedim"
][0]
),
str(
self.TargetedSwap_DataInput[sub_vol_tag_id_i][
"subvolumedim"
][1]
),
str(
self.TargetedSwap_DataInput[sub_vol_tag_id_i][
"subvolumedim"
][2]
),
)
)
# get the length of the SubVolumeResidueKind, modify the print statment and print it
data_control_file.write(
"{:30s} {:10s}".format(
"SubVolumeResidueKind",
str(sub_vol_tag_id_i),
)
)
for res_i in range(
0,
len(
self.TargetedSwap_DataInput[sub_vol_tag_id_i][
"subvolumeresiduekind"
]
),
):
data_control_file.write(
" {:10s}".format(
str(
self.TargetedSwap_DataInput[sub_vol_tag_id_i][
"subvolumeresiduekind"
][res_i]
),
)
)
data_control_file.write(
"{}\n".format(""),
)
data_control_file.write(
"{:30s} {:10s} {:10s}\n".format(
"SubVolumeRigidSwap",
str(sub_vol_tag_id_i),
str(
self.TargetedSwap_DataInput[sub_vol_tag_id_i][
"subvolumerigidswap"
]
),
)
)
data_control_file.write(
"{:30s} {:10s} {:10s}\n".format(
"SubVolumePBC",
str(sub_vol_tag_id_i),
str(
self.TargetedSwap_DataInput[sub_vol_tag_id_i][
"subvolumepbc"
]
),
)
)
# get the length of the SubVolumeChemPot, modify the print statment and print it
if "subvolumechempot" in list(
self.TargetedSwap_DataInput[sub_vol_tag_id_i].keys()
):
for subvol_chempot_key_i in list(
self.TargetedSwap_DataInput[sub_vol_tag_id_i][
"subvolumechempot"
].keys()
):
data_control_file.write(
"{:30s} {:10s} {:10s} {:30s}\n".format(
"SubVolumeChemPot",
str(sub_vol_tag_id_i),
str(subvol_chempot_key_i),
str(
self.TargetedSwap_DataInput[
sub_vol_tag_id_i
]["subvolumechempot"][subvol_chempot_key_i]
),
)
)
# get the length of the SubVolumeFugacity, modify the print statment and print it
if "subvolumefugacity" in list(
self.TargetedSwap_DataInput[sub_vol_tag_id_i].keys()
):
for subvol_fugacity_key_i in list(
self.TargetedSwap_DataInput[sub_vol_tag_id_i][
"subvolumefugacity"
].keys()
):
data_control_file.write(
"{:30s} {:10s} {:10s} {:30s}\n".format(
"SubVolumeFugacity",
str(sub_vol_tag_id_i),
str(subvol_fugacity_key_i),
str(
self.TargetedSwap_DataInput[
sub_vol_tag_id_i
]["subvolumefugacity"][
subvol_fugacity_key_i
]
),
)
)
data_control_file.write(" \n")
data_control_file.write("####################################\n")
data_control_file.write(
"# BOX DIMENSION #, X, Y, Z (only orthoganol boxes are currently "
"available in this control file writer)\n"
)
data_control_file.write("####################################\n")
data_control_file.write(
"{:25s} {:20s} {:20s} {:20s}\n".format(
"CellBasisVector1 0",
str(self.box_0_vectors[0][0]),
str(self.box_0_vectors[0][1]),
str(self.box_0_vectors[0][2]),
)
)
data_control_file.write(
"{:25s} {:20s} {:20s} {:20s}\n".format(
"CellBasisVector2 0",
str(self.box_0_vectors[1][0]),
str(self.box_0_vectors[1][1]),
str(self.box_0_vectors[1][2]),
)
)
data_control_file.write(
"{:25s} {:20s} {:20s} {:20s}\n".format(
"CellBasisVector3 0",
str(self.box_0_vectors[2][0]),
str(self.box_0_vectors[2][1]),
str(self.box_0_vectors[2][2]),
)
)
data_control_file.write(" \n")
if self.ensemble_type in ["GEMC_NPT", "GEMC_NVT", "GCMC"]:
data_control_file.write(
"{:25s} {:20s} {:20s} {:20s}\n".format(
"CellBasisVector1 1",
str(self.box_1_vectors[0][0]),
str(self.box_1_vectors[0][1]),
str(self.box_1_vectors[0][2]),
)
)
data_control_file.write(
"{:25s} {:20s} {:20s} {:20s}\n".format(
"CellBasisVector2 1",
str(self.box_1_vectors[1][0]),
str(self.box_1_vectors[1][1]),
str(self.box_1_vectors[1][2]),
)
)
data_control_file.write(
"{:25s} {:20s} {:20s} {:20s}\n".format(
"CellBasisVector3 1",
str(self.box_1_vectors[2][0]),
str(self.box_1_vectors[2][1]),
str(self.box_1_vectors[2][2]),
)
)
data_control_file.write(" \n")
if (
(self.ensemble_type in ["NPT", "NVT"])
and self.FreeEnergyCalc is not None
and self.MoleculeType is not None
and self.InitialState is not None
and self.LambdaVDW is not None
):
# make list for number of states, LambdaVDW, and Lambda_Coul, and convert the list to string for printing
Lambda_states_list = []
Lambda_VDW_list = []
Lambda_Coul_list = []
for lamda_i in range(0, len(self.LambdaVDW)):
Lambda_states_list.append(str(lamda_i))
Lambda_VDW_list.append(str(self.LambdaVDW[lamda_i]))
if self.LambdaCoulomb is not None:
Lambda_Coul_list.append(str(self.LambdaCoulomb[lamda_i]))
Lambda_states_str = "\t".join(Lambda_states_list)
Lambda_VDW_str = "\t".join(Lambda_VDW_list)
if self.LambdaCoulomb is not None:
Lambda_Coul_str = "\t".join(Lambda_Coul_list)
data_control_file.write("####################################\n")
data_control_file.write(
"# FREE ENERGY PARAMETERS (only available in NPT and NVT ensembles) \n"
)
data_control_file.write("####################################\n")
data_control_file.write(
"{:25s} {:10s} {}\n".format(
"FreeEnergyCalc",
str(self.FreeEnergyCalc[0]),
self.FreeEnergyCalc[1],
)
)
data_control_file.write(
"{:25s} {:10s} {}\n".format(
"MoleculeType",
str(self.MoleculeType[0]),
self.MoleculeType[1],
)
)
data_control_file.write(
"{:25s} {}\n".format("InitialState", self.InitialState)
)
data_control_file.write(
"{:25s} {}\n".format("ScalePower", self.ScalePower)
)
data_control_file.write(
"{:25s} {}\n".format("ScaleAlpha", self.ScaleAlpha)
)
data_control_file.write(
"{:25s} {}\n".format("MinSigma", self.MinSigma)
)
data_control_file.write(
"{:25s} {}\n".format("ScaleCoulomb", self.ScaleCoulomb)
)
data_control_file.write(
"{:25s} {}\n".format("# States", Lambda_states_str)
)
data_control_file.write(
"{:25s} {}\n".format("LambdaVDW", Lambda_VDW_str)
)
if self.LambdaCoulomb is not None:
data_control_file.write(
"{:25s} {}\n".format("LambdaCoulomb", Lambda_Coul_str)
)
data_control_file.write(" \n")
data_control_file.write("####################################\n")
data_control_file.write("# CBMC TRIALS \n")
data_control_file.write("####################################\n")
data_control_file.write(
"{:25s} {}\n".format("CBMC_First", self.CBMC_First)
)
data_control_file.write("{:25s} {}\n".format("CBMC_Nth", self.CBMC_Nth))
data_control_file.write("{:25s} {}\n".format("CBMC_Ang", self.CBMC_Ang))
data_control_file.write("{:25s} {}\n".format("CBMC_Dih", self.CBMC_Dih))
data_control_file.write(" \n")
data_control_file.write(
"############################################################################\n"
)
data_control_file.write(
"# --------------------------- OUTPUT ------------------------------------- \n"
)
data_control_file.write(
"############################################################################\n"
)
data_control_file.write(" \n")
data_control_file.write("####################################\n")
data_control_file.write("# statistics filename add\n")
data_control_file.write("####################################\n")
data_control_file.write(
"{:25s} {}\n".format("OutputName", self.OutputName)
)
data_control_file.write(" \n")
data_control_file.write("####################################\n")
data_control_file.write("# enable, frequency \n")
data_control_file.write("####################################\n")
data_control_file.write(
"{:25s} {:10s} {}\n".format(
"RestartFreq", str(self.RestartFreq[0]), self.RestartFreq[1]
)
)
data_control_file.write(
"{:25s} {:10s} {}\n".format(
"CheckpointFreq",
str(self.CheckpointFreq[0]),
self.CheckpointFreq[1],
)
)
data_control_file.write(
"{:25s} {:10s} {}\n".format(
"CoordinatesFreq",
str(self.CoordinatesFreq[0]),
self.CoordinatesFreq[1],
)
)
# set this only true if use dcd is true, until the DCDFreq is in a official release of GOMC
if self.DCDFreq[0] is True:
data_control_file.write(
"{:25s} {:10s} {}\n".format(
"DCDFreq",
str(self.DCDFreq[0]),
self.DCDFreq[1],
)
)
data_control_file.write(
"{:25s} {:10s} {}\n".format(
"ConsoleFreq", str(self.ConsoleFreq[0]), self.ConsoleFreq[1]
)
)
data_control_file.write(
"{:25s} {:10s} {}\n".format(
"BlockAverageFreq",
str(self.BlockAverageFreq[0]),
self.BlockAverageFreq[1],
)
)
data_control_file.write(
"{:25s} {:10s} {}\n".format(
"HistogramFreq",
str(self.HistogramFreq[0]),
self.HistogramFreq[1],
)
)
data_control_file.write(" \n")
data_control_file.write("####################################\n")
data_control_file.write("# OutHistSettings \n")
data_control_file.write("####################################\n")
data_control_file.write("{:25s} {}\n".format("DistName", self.DistName))
data_control_file.write("{:25s} {}\n".format("HistName", self.HistName))
data_control_file.write(
"{:25s} {}\n".format("RunNumber", self.RunNumber)
)
data_control_file.write(
"{:25s} {}\n".format("RunLetter", self.RunLetter)
)
data_control_file.write(
"{:25s} {}\n".format("SampleFreq", self.SampleFreq)
)
data_control_file.write(" \n")
data_control_file.write("####################################\n")
data_control_file.write("# enable: blk avg., fluct. \n")
data_control_file.write("####################################\n")
data_control_file.write(
"{:25s} {:10s} {:10s}\n".format(
"OutEnergy",
str(self.OutEnergy[0]),
str(self.OutEnergy[1]),
)
)
data_control_file.write(
"{:25s} {:10s} {:10s}\n".format(
"OutPressure",
str(self.OutPressure[0]),
str(self.OutPressure[1]),
)
)
data_control_file.write(
"{:25s} {:10s} {:10s}\n".format(
"OutMolNum",
str(self.OutMolNum[0]),
str(self.OutMolNum[1]),
)
)
data_control_file.write(
"{:25s} {:10s} {:10s}\n".format(
"OutDensity",
str(self.OutDensity[0]),
str(self.OutDensity[1]),
)
)
data_control_file.write(
"{:25s} {:10s} {:10s}\n".format(
"OutVolume",
str(self.OutVolume[0]),
str(self.OutVolume[1]),
)
)
data_control_file.write(
"{:25s} {:10s} {:10s}\n".format(
"OutSurfaceTension",
str(self.OutSurfaceTension[0]),
str(self.OutSurfaceTension[1]),
)
)
data_control_file.write("\n")
data_control_file.write("\n")
return "GOMC_CONTROL_FILE_WRITTEN"
def ck_input_variable_true_or_false(
self, input_variables_dict, key, bad_user_variable_list
):
"""
Checks if the input variable is either True for False.
If not either True or False, the provided list is appended with the bad with the dict_key
Parameters
----------
input_variables_dict: dict
The user input variable dictionary
key: str
Dictionary key for the user provided input variable list
bad_user_variable_list: list
A list to append with the bad dict_key user inputs
Note: This list is intented to be printed with all the bad input variables
so the user can fix them after upon a failed GOMC conf file writing attempt.
Returns
---------
bad_user_variable_list : list,
A list to append with the bad dict_key user inputs,
which is appended upon detecting a bad user input variable.
Note: This list is intented to be printed with all the bad input variables
so the user can fix them after upon a failed GOMC conf file writing attempt.
"""
if (
input_variables_dict[key] is not True
and input_variables_dict[key] is not False
or (
str(input_variables_dict[key]) == str(True)
and str(input_variables_dict[key]) == str(False)
)
):
bad_user_variable_list.append(key)
def ck_input_variable_int_or_float_zero_or_greater(
self, input_variables_dict, key, bad_input_variables_values_list
):
"""
Checks if the input variable is an integer or float is zero or greater ( value >= 0 ).
If not, the provided list is appended with the bad with the dict_key.
Parameters
----------
input_variables_dict: dict
The user input variable dictionary
key: str
Dictionary key for the user provided input variable list
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
Returns
---------
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
"""
if (
input_variables_dict[key] is not None
and isinstance(input_variables_dict[key], int) is not True
and isinstance(input_variables_dict[key], float) is not True
or input_variables_dict[key] < 0
or str(input_variables_dict[key]) == str(True)
or str(input_variables_dict[key]) == str(False)
):
bad_input_variables_values_list.append(key)
def ck_input_variable_int_zero_or_greater(
self, input_variables_dict, key, bad_input_variables_values_list
):
"""
Checks if the input variable is an integer is zero or greater ( value >= 0 ).
If not, the provided list is appended with the bad with the dict_key
Returns
---------
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
Parameters
----------
input_variables_dict: dict
The user input variable dictionary
key: str
Dictionary key for the user provided input variable list
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
"""
if (
input_variables_dict[key] is not None
and isinstance(input_variables_dict[key], int) is not True
or input_variables_dict[key] < 0
or str(input_variables_dict[key]) == str(True)
or str(input_variables_dict[key]) == str(False)
):
bad_input_variables_values_list.append(key)
def ck_input_variable_float_zero_or_greater(
self, input_variables_dict, key, bad_input_variables_values_list
):
"""
Checks if the input variable is a float is zero or greater ( value >= 0 ).
If not, the provided list is appended with the bad with the dict_key
Parameters
----------
input_variables_dict: dict
The user input variable dictionary
key: str
Dictionary key for the user provided input variable list
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
Returns
---------
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
"""
if (
input_variables_dict[key] is not None
and isinstance(input_variables_dict[key], float) is not True
or input_variables_dict[key] < 0
or str(input_variables_dict[key]) == str(True)
or str(input_variables_dict[key]) == str(False)
):
bad_input_variables_values_list.append(key)
def ck_input_variable_int_or_float_greater_zero(
self, input_variables_dict, key, bad_input_variables_values_list
):
"""
Checks if the input variable is an integer or float is greater than zero ( value > 0).
If not, the provided list is appended with the bad with the dict_key
Parameters
----------
input_variables_dict: dict
The user input variable dictionary
key: str
Dictionary key for the user provided input variable list
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
Returns
---------
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
"""
if (
input_variables_dict[key] is not None
and isinstance(input_variables_dict[key], int) is not True
and isinstance(input_variables_dict[key], float) is not True
or input_variables_dict[key] <= 0
or str(input_variables_dict[key]) == str(True)
or str(input_variables_dict[key]) == str(False)
):
bad_input_variables_values_list.append(key)
def ck_input_variable_int_greater_zero(
self, input_variables_dict, key, bad_input_variables_values_list
):
"""
Checks if the input variable is an integer greater than zero ( value > 0)..
If not, the provided list is appended with the bad with the dict_key
Parameters
----------
input_variables_dict: dict
The user input variable dictionary
key: str
Dictionary key for the user provided input variable list
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
Returns
---------
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
"""
if (
input_variables_dict[key] is not None
and isinstance(input_variables_dict[key], int) is not True
or input_variables_dict[key] <= 0
or str(input_variables_dict[key]) == str(True)
or str(input_variables_dict[key]) == str(False)
):
bad_input_variables_values_list.append(key)
def ck_input_variable_float_greater_zero(
self, input_variables_dict, key, bad_input_variables_values_list
):
"""
Checks if the input variable is a float greater than zero ( value > 0).
If not, the provided list is appended with the bad with the dict_key
Parameters
----------
input_variables_dict: dict
The user input variable dictionary
key: str
Dictionary key for the user provided input variable list
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
Returns
---------
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
"""
if (
input_variables_dict[key] is not None
and isinstance(input_variables_dict[key], float) is not True
or input_variables_dict[key] <= 0
or str(input_variables_dict[key]) == str(True)
or str(input_variables_dict[key]) == str(False)
):
bad_input_variables_values_list.append(key)
def ck_input_variable_float_greater_zero_less_1(
self, input_variables_dict, key, bad_input_variables_values_list
):
"""
Checks if the input variable is a float greater than zero and less than 1
( 0 < value < 1).
If not, the provided list is appended with the bad with the dict_key
Parameters
----------
input_variables_dict: dict
The user input variable dictionary
key: str
Dictionary key for the user provided input variable list
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
Returns
---------
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
"""
if (
input_variables_dict[key] is not None
and isinstance(input_variables_dict[key], float) is not True
or input_variables_dict[key] <= 0
or input_variables_dict[key] >= 1
or str(input_variables_dict[key]) == str(True)
or str(input_variables_dict[key]) == str(False)
):
bad_input_variables_values_list.append(key)
def ck_input_variable_int_or_float_zero_to_1(
self, input_variables_dict, key, bad_input_variables_values_list
):
"""
Checks if the input variable is an integer or float from 0 to 1 ( 0 =< value <= 1).
If not, the provided list is appended with the bad with the dict_key
If not, the provided list is appended with the bad with the dict_key
Parameters
----------
input_variables_dict: dict
The user input variable dictionary
key: str
Dictionary key for the user provided input variable list
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
Returns
---------
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
"""
if (
input_variables_dict[key] is not None
and isinstance(input_variables_dict[key], int) is not True
and isinstance(input_variables_dict[key], float) is not True
or input_variables_dict[key] < 0
or input_variables_dict[key] > 1
or str(input_variables_dict[key]) == str(True)
or str(input_variables_dict[key]) == str(False)
):
bad_input_variables_values_list.append(key)
def ck_input_variable_float_zero_to_1(
self, input_variables_dict, key, bad_input_variables_values_list
):
"""
Checks if the input variable is a float from 0 to 1 ( 0 =< value <= 1).
If not, the provided list is appended with the bad with the dict_key
Parameters
----------
input_variables_dict: dict
The user input variable dictionary
key: str
Dictionary key for the user provided input variable list
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
Returns
---------
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
"""
if (
input_variables_dict[key] is not None
and isinstance(input_variables_dict[key], float) is not True
or input_variables_dict[key] < 0
or input_variables_dict[key] > 1
or str(input_variables_dict[key]) == str(True)
or str(input_variables_dict[key]) == str(False)
):
bad_input_variables_values_list.append(key)
def ck_input_variable_int_zero_to_1(
self, input_variables_dict, key, bad_input_variables_values_list
):
"""
Checks if the input variable is an integer from 0 to 1 ( 0 =< value <= 1).
If not, the provided list is appended with the bad with the dict_key
Parameters
----------
input_variables_dict: dict
The user input variable dictionary
key: str
Dictionary key for the user provided input variable list
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
Returns
---------
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
"""
if (
input_variables_dict[key] is not None
and isinstance(input_variables_dict[key], int) is not True
or input_variables_dict[key] < 0
or input_variables_dict[key] > 1
or str(input_variables_dict[key]) == str(True)
or str(input_variables_dict[key]) == str(False)
):
bad_input_variables_values_list.append(key)
def ck_input_variable_list_bool_int_zero_or_greater(
self, input_variables_dict, key, bad_input_variables_values_list
):
"""
Checks if the input variable is a list with a bool and integer 0 or greater
([bool, int >= 0 ]).
If not, the provided list is appended with the bad with the dict_key
Parameters
----------
input_variables_dict: dict
The user input variable dictionary
key: str
Dictionary key for the user provided input variable list
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
Returns
---------
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
"""
if isinstance(input_variables_dict[key], list) is False:
bad_input_variables_values_list.append(key)
elif isinstance(input_variables_dict[key], list) is True:
if (
len(input_variables_dict[key]) != 2
or (
input_variables_dict[key][0] is not True
and input_variables_dict[key][0] is not False
)
or isinstance(input_variables_dict[key][1], int) is not True
or input_variables_dict[key][1] < 0
or (
str(input_variables_dict[key][0]) != str(True)
and str(input_variables_dict[key][0]) != str(False)
)
or str(input_variables_dict[key][1]) == str(True)
or str(input_variables_dict[key][1]) == str(False)
):
bad_input_variables_values_list.append(key)
def ck_input_variable_list_bool_int_greater_zero(
self, input_variables_dict, key, bad_input_variables_values_list
):
"""
Checks if the input variable is a list with a bool and integer greater than zero
([bool, int > 0 ]).
If not, the provided list is appended with the bad with the dict_key
Parameters
----------
input_variables_dict: dict
The user input variable dictionary
key: str
Dictionary key for the user provided input variable list
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
Returns
---------
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
"""
if isinstance(input_variables_dict[key], list) is False:
bad_input_variables_values_list.append(key)
elif isinstance(input_variables_dict[key], list) is True:
if (
len(input_variables_dict[key]) != 2
or (
input_variables_dict[key][0] is not True
and input_variables_dict[key][0] is not False
)
or isinstance(input_variables_dict[key][1], int) is not True
or input_variables_dict[key][1] <= 0
or (
str(input_variables_dict[key][0]) != str(True)
and str(input_variables_dict[key][0]) != str(False)
)
or str(input_variables_dict[key][1]) == str(True)
or str(input_variables_dict[key][1]) == str(False)
):
bad_input_variables_values_list.append(key)
def ck_input_variable_list_residue_str_int_greater_zero(
self, input_variables_dict, key, bad_input_variables_values_list
):
"""
Checks if the input variable is a list with a str and integer greater than zero
([str, int > 0 ]).
If not, the provided list is appended with the bad with the dict_key
Parameters
----------
input_variables_dict: dict
The user input variable dictionary
key: str
Dictionary key for the user provided input variable list
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
Returns
---------
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
"""
if isinstance(input_variables_dict[key], list) is False:
bad_input_variables_values_list.append(key)
elif isinstance(input_variables_dict[key], list) is True:
if len(input_variables_dict[key]) == 2:
if isinstance(input_variables_dict[key], list) is True:
if (
isinstance(input_variables_dict[key][0], str) is False
or isinstance(input_variables_dict[key][1], int)
is False
):
bad_input_variables_values_list.append(key)
elif isinstance(input_variables_dict[key][0], str) is True:
if (
len(input_variables_dict[key][0]) > 4
or input_variables_dict[key][0] not in self.residues
):
bad_input_variables_values_list.append(key)
if (
isinstance(input_variables_dict[key][1], int) is True
and input_variables_dict[key][1] <= 0
):
bad_input_variables_values_list.append(key)
def ck_input_variable_list_bool_bool(
self, input_variables_dict, key, bad_input_variables_values_list
):
"""
Checks if the input variable is a list with a 2 booleans ([bool, bool]).
If not, the provided list is appended with the bad with the dict_key
Parameters
----------
input_variables_dict: dict
The user input variable dictionary
key: str
Dictionary key for the user provided input variable list
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
Returns
---------
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
"""
if isinstance(input_variables_dict[key], list) is False:
bad_input_variables_values_list.append(key)
elif isinstance(input_variables_dict[key], list) is True:
if (
len(input_variables_dict[key]) != 2
or (
input_variables_dict[key][0] is not True
and input_variables_dict[key][0] is not False
)
or (
input_variables_dict[key][1] is not True
and input_variables_dict[key][1] is not False
)
or (
str(input_variables_dict[key][0]) != str(True)
and str(input_variables_dict[key][0]) != str(False)
)
or (
str(input_variables_dict[key][1]) != str(True)
and str(input_variables_dict[key][1]) != str(False)
)
):
bad_input_variables_values_list.append(key)
def ck_input_variable_list_of_floats_zero_to_1(
self, input_variables_dict, key, bad_input_variables_values_list
):
"""
Checks if the input variable is a list of floats between 0 and 1 ([0,0, 0.1, ..., 1.0]).
Note: the list can be of any length with 0.0 <= float <= 1.0
If not, the provided list is appended with the bad with the dict_key
Parameters
----------
input_variables_dict: dict
The user input variable dictionary
key: str
Dictionary key for the user provided input variable list
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
Returns
---------
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
"""
if input_variables_dict[key] is not None:
if isinstance(input_variables_dict[key], list) is False:
bad_input_variables_values_list.append(key)
elif isinstance(input_variables_dict[key], list) is True:
if len(input_variables_dict[key]) >= 1:
for Lambda_i in range(0, len(input_variables_dict[key])):
if (
isinstance(
input_variables_dict[key][Lambda_i], float
)
is False
):
bad_input_variables_values_list.append(key)
elif (
isinstance(
input_variables_dict[key][Lambda_i], float
)
is True
):
if (
input_variables_dict[key][Lambda_i] < 0.0
or input_variables_dict[key][Lambda_i] > 1.0
):
bad_input_variables_values_list.append(key)
else:
bad_input_variables_values_list.append(key)
def ck_input_variable_GCMC_dict_str_int_or_float(
self, input_variables_dict, key, bad_input_variables_values_list
):
"""
Checks if the input variable is a dictionary with a key = string and
value = integer or float ({'str_1' : integer_1 or float_1, ....,
'str_x' : integer_x or float_x }).
Note: the dictionary can be of any length
If not, the provided list is appended with the bad with the dict_key
Parameters
----------
input_variables_dict: dict
The user input variable dictionary
key: str
Dictionary key for the user provided input variable list
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
Returns
---------
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
"""
if (
input_variables_dict[key] is not None
and isinstance(input_variables_dict[key], dict) is not True
):
bad_input_variables_values_list.append(key)
elif isinstance(input_variables_dict[key], dict) is True:
keys_list = dict_keys_to_list(input_variables_dict[key])
for keys_iter_No in range(0, len(keys_list)):
key_iter = keys_list[keys_iter_No]
value_iter = input_variables_dict[key][key_iter]
if key_iter not in self.residues:
bad_input_variables_values_list.append(key)
if isinstance(key_iter, str) is False:
bad_input_variables_values_list.append(key)
elif isinstance(key_iter, str) is True:
if len(key_iter) > 4:
bad_input_variables_values_list.append(key)
if (
(
isinstance(value_iter, int) is False
and isinstance(value_iter, float) is False
)
or str(value_iter) == str(True)
or str(value_iter) == str(False)
):
bad_input_variables_values_list.append(key)
def ck_input_variable_GCMC_dict_str_int_or_float_zero_or_greater(
self, input_variables_dict, key, bad_input_variables_values_list
):
"""
Checks if the input variable is a dictionary with a key = string and
value = integer or float zero or greater ({'str_1' : integer_1 or float_1 (>= 0), ....,
'str_x' : integer_x or float_x (>= 0)}).
Note: the dictionary can be of any length
If not, the provided list is appended with the bad with the dict_key
Parameters
----------
input_variables_dict: dict
The user input variable dictionary
key: str
Dictionary key for the user provided input variable list
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
Returns
---------
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
"""
if (
input_variables_dict[key] is not None
and isinstance(input_variables_dict[key], dict) is not True
):
bad_input_variables_values_list.append(key)
elif isinstance(input_variables_dict[key], dict) is True:
keys_list = dict_keys_to_list(input_variables_dict[key])
for keys_iter_No in range(0, len(keys_list)):
key_iter = keys_list[keys_iter_No]
value_iter = input_variables_dict[key][key_iter]
if key_iter not in self.residues:
bad_input_variables_values_list.append(key)
if isinstance(key_iter, str) is False:
bad_input_variables_values_list.append(key)
elif isinstance(key_iter, str) is True:
if len(key_iter) > 4:
bad_input_variables_values_list.append(key)
if (
(
isinstance(value_iter, int) is False
and isinstance(value_iter, float) is False
)
or str(value_iter) == str(True)
or str(value_iter) == str(False)
or value_iter < 0
):
bad_input_variables_values_list.append(key)
def ck_input_variable_str_with_no_spaces(
self, input_variables_dict, key, bad_input_variables_values_list
):
"""
Checks if the input variable is a string with no spaces.
If not, the provided list is appended with the bad with the dict_key.
Parameters
----------
input_variables_dict: dict
The user input variable dictionary
key: str
Dictionary key for the user provided input variable list
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
Returns
---------
bad_input_variables_values_list: list
A list to append with the bad variable user inputs
so the user can see which variable input values are bad.
"""
if isinstance(input_variables_dict[key], str) is True:
no_spaces_in_OutputName_string = " " in input_variables_dict[key]
if (
isinstance(input_variables_dict[key], str) is not True
or no_spaces_in_OutputName_string is True
):
bad_input_variables_values_list.append(key)
def _scale_gen_freq_for_run_steps_list_bool_int(
variable_name, charmm_variable, run_steps
):
"""
Scales the frequency of the output to a a more realistic value,
if the output frequency does not make sense based on the
total number of simulation run steps.
Parameters
----------
variable_name, str
The variable name as a sting, which is used for printing error outputs.
charmm_variable : GOMCControl object variable list, [bool, int]
This only for the frequency output variables of the GOMCControl object
run_steps : int (>0), must be an integer greater than zero.
This is the GOMCControl object varaible which sets the total number of simulation steps.
This should be the RunSteps variable in the GOMCControl object.
Returns
---------
charmm_variable : GOMCControl object variable list [bool, int]
A rescaled and appropriate value for the frequency output variables of the
GOMCControl object, based on the RunSteps in the simulation.
"""
if not isinstance(charmm_variable, list):
print_error_message = "ERROR: The {} variable is not a list.".format(
variable_name
)
raise ValueError(print_error_message)
if len(charmm_variable) != 2:
print_error_message = (
"ERROR: The {} variable list length is not 2.".format(
variable_name
)
)
raise ValueError(print_error_message)
else:
if not isinstance(charmm_variable[0], bool):
print_error_message = (
"ERROR: The {} variable is not a boolean.".format(
variable_name
)
)
raise ValueError(print_error_message)
if not isinstance(charmm_variable[1], int):
print_error_message = (
"ERROR: The {} variable is not a int.".format(variable_name)
)
raise ValueError(print_error_message)
set_max_steps_charmm_variable = charmm_variable[1]
if run_steps / 10 >= set_max_steps_charmm_variable and run_steps / 10 >= 1:
charmm_variable[1] = int(set_max_steps_charmm_variable)
elif run_steps / 10 >= 1:
charmm_variable[1] = int(run_steps / 10)
else:
charmm_variable[1] = int(1)
return charmm_variable
def _scale_gen_freq_for_run_steps_int(
variable_name, charmm_variable, run_steps
):
"""
Scales the frequency of the output to a a more realistic value,
if the output frequency does not make sense based on the
total number of simulation run steps.
Parameters
----------
variable_name, str
The variable name as a sting, which is used for printing error outputs.
charmm_variable : GOMCControl object variable, int
This only for the frequency output variables of the GOMCControl object
run_steps : int (>0), must be an integer greater than zero.
This is the GOMCControl object varaible which sets the total number of simulation steps.
This should be the RunSteps variable in the GOMCControl object.
Returns
---------
charmm_variable : GOMCControl object variable list, int
A rescaled and appropriate value for the frequency output variables of the
GOMCControl object, based on the RunSteps in the simulation.
"""
if not isinstance(charmm_variable, int):
print_error_message = (
"ERROR: The {} variable is not an interger.".format(variable_name)
)
raise ValueError(print_error_message)
set_max_steps_charmm_variable = charmm_variable
if run_steps / 10 >= set_max_steps_charmm_variable and run_steps / 10 >= 1:
charmm_variable = int(set_max_steps_charmm_variable)
elif run_steps / 10 >= 1:
charmm_variable = int(run_steps / 10)
else:
charmm_variable = int(1)
return charmm_variable
def ck_box_dim_is_float_or_int_greater_0(
charmm_box_dimension, dimension, box_no, ensemble_type
):
"""
Scales the frequency of the output to a a more realistic value,
if the output frequency does not make sense based on the
total number of simulation run steps.
Parameters
----------
charmm_box_dimension : GOMCControl object box dimension variable
This is the variable that contains the box input x, y, or z dimensions for box 0 or 1.
dimension : str (Only enter 'x', 'y', or 'z')
This is the dimension of the charmm_box_dimension variable.
Only enter 'x', 'y', or 'z', but it will not error out if you do not.
box_no : int (only 0 or 1)
This is the box number which is defined in the mbuild.Charmm object
Only enter only 0 or 1, but it will not error out if you do not.
ensemble_type : str, valid options are 'NVT', 'NPT', 'GEMC_NVT', 'GEMC_NPT', 'GCMC'
The ensemble type of the simulation.
Returns
---------
If charmm_box_dimension is an int or float (>0) : None
If charmm_box_dimension is not an int or float (>0) : raise ValueError
"""
if (
isinstance(charmm_box_dimension, int) is False
and isinstance(charmm_box_dimension, float) is False
) or charmm_box_dimension <= 0:
print_error_message = "ERROR: The {}-dimension for box {} is, {} , not an integer, float, "
"or is <= 0.".format(dimension, box_no, charmm_box_dimension)
raise ValueError(print_error_message)
if (
(ensemble_type in ["GEMC_NVT", "GEMC_NPT", "GCMC"])
and charmm_box_dimension is None
and box_no == 1
):
print_error_message = (
"ERROR: The {}-dimension for box {} was not provided. "
"The {}-dimension for box {}, "
" is required to be an an integer, float, and be > 0.".format(
dimension, box_no, dimension, box_no
)
)
raise ValueError(print_error_message)
return None
def _check_box_vectors_char_limit(vectors, char_limit):
"""
Checks to see if the vectors exceed the specified character limit
Parameters
----------
vectors : numpy.ndarray, [[float, float, float], [float, float, float], [float, float, float]]
Three (3) sets vectors for box 0 each with 3 float values, which represent
the vectors for the Charmm-style systems (i.e, the CellBasisVectors).
char_limit : int
The specified number of allowable characters for each individual value in the vectors.
Returns
-------
bool:
True, if within the allowable character limit
False, if not within the allowable character limit
"""
for x_i in range(0, 3):
for y_i in range(0, 3):
if len(str(vectors[x_i][y_i])) > char_limit:
return False
return True
def _check_if_input_files_exist(
file_directory_and_name,
type_of_file,
check_input_files_exist=True,
):
"""
Checks to see GOMC FF, pdb, and psf files exist
Parameters
----------
file_directory_and_name : str
The file directory and name of the file.
type_of_file : str
A brief description of the file which is evaluated.
check_input_files_exist: bool (default=True)
Check if the force field, psf, and pdb files exist.
If the files are checked and do not exist, the writer will throw a ValueError.
True, check if the force field, psf, and pdb files exist.
False, do not check if the force field, psf, and pdb files exist.
Returns
-------
If the file exists : None
If the file does not exist : raise ValueError
"""
if (
os.path.isfile(file_directory_and_name) is False
and check_input_files_exist is True
):
print_error_message = (
"The {} with the file directory and name {}, "
"does not exist.".format(type_of_file, file_directory_and_name)
)
raise ValueError(print_error_message)
def _check_if_string_and_extension(
file_directory_and_name,
file_directory_and_name_variable,
type_of_file,
expected_file_extension=None,
):
"""
Checks to see GOMC FF, pdb, and psf files exist
Parameters
----------
file_directory_and_name : str
The file directory and name of the file.
file_directory_and_name_variable : variable
The variable for the file directory and name of the file.
type_of_file : str
A brief description of the file which is evaluated (force file, psf, pdb).
expected_file_extension : list of strings (optional), [str, ..., str], default=None
The expected file extensions that are checked against the actual file extension.
Returns
-------
If the variable is a string : None
If the variable is not a string : raise TypeError
If the variable is a string and has the correct extension : None
If the variable is a string and has the wrong extension : raise TypeError
"""
if (
not isinstance(file_directory_and_name_variable, str)
and file_directory_and_name_variable is not None
):
print(
"file_directory_and_name_variable ="
+ str(file_directory_and_name_variable)
)
print_error_message = (
r"ERROR: The {} variable for directly entering the "
r"{} file directory and name is a {} and not a string.".format(
file_directory_and_name,
type_of_file,
type(file_directory_and_name_variable),
)
)
raise TypeError(print_error_message)
if expected_file_extension is not None:
acutal_file_extension = os.path.splitext(
file_directory_and_name_variable
)[-1]
if acutal_file_extension not in expected_file_extension:
print_error_message = (
r"ERROR: The {} variable expects a file extension of {}, "
r'but the actual file extension is "{}". '
r"".format(
file_directory_and_name,
expected_file_extension,
acutal_file_extension,
)
)
raise TypeError(print_error_message)
def _check_if_bool(
variable_as_a_string,
variable,
):
"""
Checks to see if the variable is a boolean.
Parameters
----------
variable_as_a_string : str
The variable name as a string.
variable : variable
The variable to test if it is a boolean.
Returns
-------
If the variable is a bool : None
If the variable is not a bool : raise TypeError
"""
if not isinstance(variable, bool):
print_error_message = (
"ERROR: The {} input is {} and needs to be a boolean (i.e., True or False)."
"".format(variable_as_a_string, type(variable))
)
raise TypeError(print_error_message)
# user callable function to write the GOMC control file
[docs]def write_gomc_control_file(
charmm_object,
conf_filename,
ensemble_type,
RunSteps,
Temperature,
ff_psf_pdb_file_directory=None,
check_input_files_exist=True,
Restart=False,
RestartCheckpoint=False,
ExpertMode=False,
Parameters=None,
Coordinates_box_0=None,
Structure_box_0=None,
Coordinates_box_1=None,
Structure_box_1=None,
binCoordinates_box_0=None,
extendedSystem_box_0=None,
binVelocities_box_0=None,
binCoordinates_box_1=None,
extendedSystem_box_1=None,
binVelocities_box_1=None,
input_variables_dict=None,
):
"""
The usable command that creates the ``GOMCControl`` object and writes
the GOMC control file via the ``GOMCControl.write_conf_file`` function.
Constructs the GOMC GOMCControl object with the defaults,
or adding additional data in the input_variable section.
Default setting for the GOMC configuraion files are based upon
an educated guess, which should result in reasonable sampling for a
given ensemble/simulation type. However, there is no guarantee that
the default setting will provide the best or adequate sampling for
the selected system. The user has the option to modify the
configuration/control files based on the simulation specifics or to
optimize the system beyond the standard settings. These override
options are available via the keyword arguments in input_variable_dict.
Parameters
----------
charmm_object : Charmm object
Charmm object is has been parameterized from the selected force field.
ensemble_typ : str, ['NVT', 'NPT', 'GEMC_NPT', 'GCMC-NVT', 'GCMC']
The ensemble type of the simulation.
RunSteps : int (>0), must be an integer greater than zero.
Sets the total number of simulation steps.
Temperature : float or int (>0), must be an integer greater than zero.
Temperature of system in Kelvin (K)
ff_psf_pdb_file_directory : str (optional), default=None (i.e., the current directory).
The full or relative directory added to the force field, psf, and pdb
file names, created via the Charmm object.
check_input_files_exist : bool, (default=True)
Check if the force field, psf, and pdb files exist.
If the files are checked and do not exist, the writer will throw a ValueError.
True, check if the force field, psf, and pdb files exist.
False, do not check if the force field, psf, and pdb files exist.
Restart : boolean, default = False
Determines whether to restart the simulation from restart file
(``*_restart.pdb`` and ``*_restart.psf``) or not.
RestartCheckpoint : boolean, default = False
Determines whether to restart the simulation with the checkpoint
file (checkpoint.dat) or not. Restarting the simulation with checkpoint.dat
would result in an identical outcome, as if previous simulation was continued.
ExpertMode : boolean, default = False
This allows the move ratios to be any value, regardless of the ensemble,
provided all the move ratios sum to 1. For example, this mode is utilized
to easily equilibrate a GCMC or GEMC ensemble in a pseudo NVT mode by removing
the requirement that the volume and swap moves must be non-zero.
In other words, when the volume and swap moves are zero, the GCMC and GEMC
ensembles will run pseudo NVT simulations in 1 and 2 simulation boxes, respectively.
The simulation's output and restart files will keep their original output structure
for the selected ensemble, which is advantageous when automating a workflow.
Parameters : str, (default=None)
Override all other force field directory and filename input with the correct extension (.inp or .par).
Note: the default directory is the current directory with the Charmm object file name.
Coordinates_box_0 : str, (default=None)
Override all other box 0 pdb directory and filename inputs with the correct extension.
Note: the default directory is the current directory with the Charmm object file name.
Structure_box_0 : str, (default=None)
Override all other box 0 psf directory and filename inputs with the correct extension.
Note: the default directory is the current directory with the Charmm object file name.
Coordinates_box_1 : str, (default=None)
Override all other box 1 pdb directory and filename inputs with the correct extension.
Note: the default directory is the current directory with the Charmm object file name.
Structure_box_1 : str, (default=None)
Override all other box 1 psf directory and filename inputs with the correct extension.
Note: the default directory is the current directory with the Charmm object file name.
binCoordinates_box_0 : str, (default=None)
The box 0 binary coordinate file is used only for restarting a GOMC simulation,
which provides increased numerical accuracy.
extendedSystem_box_0 : str, (default=None)
The box 0 vectors and origin file is used only for restarting a GOMC simulation.
binVelocities_box_0 : str, (default=None)
The box 0 binary velocity file is used only for restarting a GOMC simulation,
which provides increased numerical accuracy. These velocities are only passed thru
GOMC since Monte Carlo simulations do not utilize any velocity information.
binCoordinates_box_1 : str, (default=None)
The box 1 binary coordinate file is used only for restarting a GOMC simulation,
which provides increased numerical accuracy.
extendedSystem_box_1 : str, (default=None)
The box 1 vectors and origin file is used only for restarting a GOMC simulation.
binVelocities_box_1 : str, (default=None)
The box 1 binary velocity file is used only for restarting a GOMC simulation,
which provides increased numerical accuracy. These velocities are only passed thru
GOMC since Monte Carlo simulations do not utilize any velocity information.
input_variables_dict: dict, default=None
These input variables are optional and override the default settings.
Changing these variables likely required for more advanced systems.
The details of the acceptable input variables for the selected
ensembles can be found by running the code below in python,
>>>print_valid_ensemble_input_variables('GCMC', description = True)
which prints the input_variables with their subsection description
for the selected 'GCMC' ensemble (other ensembles can be set as well).
Example : input_variables_dict = {'PRNG' : 123,
'ParaTypeCHARMM' : True }
# *******************************************************************
# input_variables_dict options (keys and values) - (start)
# Note: the input_variables_dict keys are also attributes
# *******************************************************************
PRNG : string or int (>= 0) ("RANDOM" or int), default = "RANDOM"
PRNG = Pseudo-Random Number Generator (PRNG). There are two (2) options, entering
the string, "RANDOM", or a integer.
--- "RANDOM": selects a random seed number. This will enter the line
"PRNG RANDOM" in the gomc configuration file.
--- integer: which defines the integer seed number for the simulation. This is
equivalent to entering the following two lines in the configuration file
line 1 = PRNG INTSEED
line 2 = Random_Seed user_selected_integer.
Example 1: for a random seed enter the string "RANDOM".
Example 2: for a specific seed number enter a integer of your choosing.
ParaTypeCHARMM : boolean, default = True
True if a CHARMM forcefield, False otherwise.
ParaTypeMie : boolean, default = False
True if a Mie forcefield type, False otherwise.
ParaTypeMARTINI : boolean, default = False
True if a MARTINI forcefield, False otherwise.
RcutCoulomb_box_0 : int or float (>= 0), default = None
Sets a specific radius in box 0 where the short-range electrostatic
energy will be calculated (i.e., The distance to truncate the
short-range electrostatic energy in box 0.)
Note: if None, GOMC will default to the Rcut value
RcutCoulomb_box_1 : int or float (>= 0), default = None
Sets a specific radius in box 1 where the short-range electrostatic
energy will be calculated (i.e., The distance to truncate the
short-range electrostatic energy in box 0.)
Note: if None, GOMC will default to the Rcut value
Pressure : int or float (>= 0), default = 1.01325
The pressure in bar utilized for the NPT and GEMC_NPT simulations.
Rcut : int or float (>= 0 and RcutLow < Rswitch < Rcut), default = 10
Sets a specific radius in Angstroms that non-bonded interaction
energy and force will be considered and calculated using defined potential function.
The distance in Angstoms to truncate the LJ, Mie, or other VDW type potential at.
Note: Rswitch is only used when the "Potential" = SWITCH.
RcutLow : int or float (>= 0 and RcutLow < Rswitch < Rcut), default = 0
Sets a specific minimum possible distance in Angstroms that reject
any move that places any atom closer than specified distance.
The minimum possible distance between any atoms.
Sets a specific radius in Angstroms that non-bonded interaction
Note: Rswitch is only used when the "Potential" = SWITCH.
WARNING: When using a molecule that has charge atoms with non-bonded epsilon values of zero (i.e., water),
the RcutLow need to be greater than zero, typically 1 angstrom.
WARNING: When using the free energy calculations, RcutLow needs to be set to zero (RcutLow=0);
otherwise, the free energy calculations can produce results that are slightly off or wrong.
LRC : boolean, default = True
If True, the simulation considers the long range tail corrections for the
non-bonded VDW or dispersion interactions.
Note: In case of using SHIFT or SWITCH potential functions, LRC will be ignored.
IPC : boolean, default = False
If True, the simulation adds the impulse correction term to the pressure,
which considers to correct for the discontinuous Rcut potential
(i.e., a hard cutoff potential, meaning a potential without tail corrections)
the long range tail corrections for the non-bonded VDW or dispersion interactions.
If False, the impulse correction term to the pressure is not applied.
Note: This can not be used if LRC is True or the Potential is set to SWITCH, or SHIFT.
Exclude : str ["1-2", "1-3", or "1-4"], default = "1-3"
Note: In CHARMM force field, the 1-4 interaction needs to be considered.
Choosing "Excude 1-3", will modify 1-4 interaction based on 1-4 parameters
in parameter file. If a kind force field is used, where 1-4 interaction
needs to be ignored, such as TraPPE, either Exclude "1-4" needs to be
chosen or 1-4 parameter needs to be assigned to zero in the parameter file.
--- "1-2": All interaction pairs of bonded atoms, except the ones that
separated with one bond, will be considered and modified using 1-4
parameters defined in parameter file.
--- "1-3": All interaction pairs of bonded atoms, except the ones that
separated with one or two bonds, will be considered and modified using
1-4 parameters defined in parameter file.
--- "1-4": All interaction pairs of bonded atoms, except the ones that
separated with one, two or three bonds, will be considered using
non-bonded parameters defined in parameter file.
Potential : str, ["VDW", "EXP6", "SHIFT" or "SWITCH"], default = "VDW"
Defines the potential function type to calculate non-bonded dispersion
interaction energy and force between atoms.
--- "VDW": Non-bonded dispersion interaction energy and force
calculated based on n-6 (Lennard - Jones) equation. This
function will be discussed further in the Intermolecular energy
and Virial calculation section.
--- "EXP6": Non-bonded dispersion interaction energy and force calculated
based on exp-6 (Buckingham potential) equation.
--- "SHIFT": This option forces the potential energy to be zero at Rcut distance.
--- "SWITCH": This option smoothly forces the potential energy to be zero at
Rcut distance and starts modifying the potential at Rswitch
distance. Depending on force field type, specific potential
function will be applied.
Rswitch : int or float (>= 0 and RcutLow < Rswitch < Rcut), default = 9
Note: Rswitch is only used when the SWITCH function is used
(i.e., "Potential" = SWITCH). The Rswitch distance is in Angstrom. If the
“SWITCH” function is chosen, Rswitch needs to be defined, otherwise, the
program will be terminated. When using choosing "SWITCH" as potential function,
the Rswitch distance defines where the non-bonded interaction energy
modification is started, which is eventually truncated smoothly at Rcut
distance.
ElectroStatic : boolean, default = True
Considers the coulomb interactions or not. If True, coulomb interactions are
considered and false if not. Note: To simulate the polar molecule in MARTINI
force field, ElectroStatic needs to be turn on (i.e., True). The MARTINI force
field uses short-range coulomb interaction with constant Dielectric of 15.0.
Ewald : boolean, default = True
Considers the standard Ewald summation method for electrostatic calculations.
If True, Ewald summation calculation needs to be considered and false if not.
Note: By default, GOMC will set ElectroStatic to True if Ewald summation
method was used to calculate coulomb interaction.
CachedFourier : boolean, default = False
Considers storing the reciprocal terms for Ewald summation calculation in
order to improve the code performance. This option would increase the code
performance with the cost of memory usage. If True, to store reciprocal
terms of Ewald summation calculation and False if not.
Warning: Monte Carlo moves, such as MEMC-1, MEMC-2, MEMC-3,
IntraMEMC-1, IntraMEMC-2, and IntraMEMC-3 are not support with CachedFourier.
Tolerance : float (0.0 < float < 1.0), default = 1e-05
Sets the accuracy in Ewald summation calculation. Ewald separation parameter
and number of reciprocal vectors for the Ewald summation are determined
based on the accuracy parameter.
Dielectric : int or float (>= 0.0), default = 15
Sets dielectric value used in coulomb interaction when the Martini
force field is used. Note: In MARTINI force field, Dielectric needs to
be set to 15.0.
PressureCalc : list [bool , int (> 0)] or [bool , step_frequency],
default = [True, 10k] or [True , set via formula based on the number of RunSteps or 10k max]
Calculate the system pressure or not. bool = True, enables the pressure calculation
during the simulation, false disables the calculation. The int/step frequency sets the
frequency of calculating the pressure.
EqSteps : int (> 0), default = set via formula based on the number of RunSteps or 1M max
Sets the number of steps necessary to equilibrate the system.
Averaging will begin at this step.
Note: In GCMC simulations, the Histogram files will be outputed at EqSteps.
AdjSteps : int (> 0), default = set via formula based on the number of RunSteps or 1k max
Sets the number of steps per adjustment of the parameter associated with each move
(e.g. maximum translate distance, maximum rotation, maximum volume exchange, etc.).
VDWGeometricSigma: boolean, default = False
Use geometric mean, as required by OPLS force field, to combining
Lennard-Jones sigma parameters for different atom types.
If set to True, GOMC uses geometric mean to combine Lennard-Jones or VDW sigmas.
Note: The default setting of VDWGeometricSigma is false, which uses the arithmetic
mean when combining Lennard-Jones or VDW sigma parameters for different atom types.
useConstantArea : boolean, default = False
Changes the volume of the simulation box by fixing the cross-sectional
area (x-y plane). If True, the volume will change only in z axis,
If False, the volume of the box will change in a way to maintain the constant
axis ratio.
FixVolBox0 : boolean, default = False
Changing the volume of fluid phase (Box 1) to maintain the constant imposed
pressure and Temperature, while keeping the volume of adsorbed phase (Box 0) fixed.
Note: By default, GOMC will set useConstantArea to False if no value was set.
It means, the volume of the box will change in a way to maintain the constant
axis ratio.
ChemPot : dict {str (4 dig limit) , int or float}, default = None
The chemical potentials in GOMC units of energy, K.
There is a 4 character limit for the string/residue name since the PDB/PSF
files have a 4 character limitation and require and exact match in the conf file.
Note: These strings must match the residue in the psf and psb files or it will fail.
The name of the residues and their corresponding chemical potential must specified
for every residue in the system (i.e., {"residue_name" : chemical_potential}).
Note: IF 2 KEYS WITH THE SAME STRING/RESIDUE ARE PROVIDED, ONE WILL BE AUTOMATICALLY
OVERWRITTEN AND NO ERROR WILL BE THROWN IN THIS CONTROL FILE WRITER.
Example 1 (system with only water): {"H2O" : -4000}
Example 2 (system with water and ethanol): {"H2O" : -4000, "ETH" : -8000}
Fugacity : dict {str , int or float (>= 0)}, default = None
The fugacity in GOMC units of pressure, bar.
There is a 4 character limit for the string/residue name since the PDB/PSF
files have a 4 character limitation and require and exact match in the conf file.
Note: These strings must match the residue in the psf and psb files or it will fail.
The name of the residues and their corresponding fugacity must specified
for every residue in the system (i.e., {"residue_name" : fugacity}).
Note: IF 2 KEYS WITH THE SAME STRING/RESIDUE ARE PROVIDED, ONE WILL BE AUTOMATICALLY
OVERWRITTEN AND NO ERROR WILL BE THROWN IN THIS CONTROL FILE WRITER.
Example 1 (system with only water): {"H2O" : 1}
Example 2 (system with water and ethanol): {"H2O" : 0.5, "ETH" : 10}
CBMC_First : int (>= 0), default = 12
The number of CD-CBMC trials to choose the first atom position
(Lennard-Jones trials for first seed growth).
CBMC_Nth : int (>= 0), default = 10
The Number of CD-CBMC trials to choose the later atom positions
(Lennard-Jones trials for first seed growth).
CBMC_Ang : int (>= 0), default = 50
The Number of CD-CBMC bending angle trials to perform for geometry
(per the coupled-decoupled CBMC scheme).
CBMC_Dih : int (>= 0), default = 50
The Number of CD-CBMC dihedral angle trials to perform for geometry
(per the coupled-decoupled CBMC scheme).
OutputName : str (NO SPACES), , default = "Output_data", default = [True, 1M] or
[True , set via formula based on the number of RunSteps or 1M max]
The UNIQUE STRING NAME, WITH NO SPACES, which is used for the
output block average, PDB, and PSF file names.
CoordinatesFreq : list [bool , int (> 0)] or [Generate_data_bool , steps_per_data_output_int],
default = [True, 1M] or [True , set via formula based on the number of RunSteps or M max]
Controls output of PDB file (coordinates). If bool is True, this
enables outputting the coordinate files at the integer frequency
(set steps_per_data_output_int), while "False" disables outputting
the coordinates.
DCDFreq : list [bool , int (> 0)] or [Generate_data_bool , steps_per_data_output_int],
default = [True, 1M] or [True , set via formula based on the number of RunSteps or M max]
Controls output of DCD file (coordinates). If bool is True, this
enables outputting the coordinate files at the integer frequency
(set steps_per_data_output_int), while "False" disables outputting
the coordinates.
RestartFreq : list [bool , int (> 0)] or [Generate_data_bool , steps_per_data_output_int],
default = [True, 1M] or [True , set via formula based on the number of RunSteps or 1M max]
This creates the PDB and PSF (coordinate and topology) files for
restarting the system at the set steps_per_data_output_int (frequency)
If bool is True, this enables outputting the PDB/PSF restart files at the
integer frequency (set steps_per_data_output_int), while “false”
disables outputting the PDB/PSF restart files.
CheckpointFreq : list [bool , int (> 0)] or [Generate_data_bool , steps_per_data_output_int],
default = [True, 1M] or [True , set via formula based on the number of RunSteps or 1M max]
Controls the output of the last state of simulation at a specified step,
in a binary file format (checkpoint.dat). Checkpoint file contains the
following information in full precision:
(1) Last simulation step that saved into checkpoint file
(2) Simulation cell dimensions and angles
(3) Maximum amount of displacement (Å), rotation (δ), and volume (Å^3)
that is used in the Displacement, Rotation, MultiParticle, and Volume moves
(4) Number of Monte Carlo move trial and acceptance
(5) All molecule’s coordinates
(6) Random number sequence
If bool is True, this enables outputing the checkpoint file at the
integer frequency (set steps_per_data_ouput_int),
while "False" disables outputting the checkpoint file.
ConsoleFreq : list [bool , int (> 0)] or [Generate_data_bool , steps_per_data_output_int],
default = [True, 10k] or [True , set via formula based on the number of RunSteps or 10k max]
Controls the output to the "console" or log file, which prints the
acceptance statistics, and run timing info. In addition, instantaneously-selected
thermodynamic properties will be output to this file. If bool is True,
this enables outputting the console data at the integer frequency
(set steps_per_data_output_int), while "False" disables outputting the console
data file.
BlockAverageFreq : list [bool , int (> 0)] or [Generate_data_bool , steps_per_data_output_int],
default = [True, 10k] or [True , set via formula based on the number of RunSteps or 10k max]
Controls the block averages output of selected thermodynamic properties.
Block averages are averages of thermodynamic values of interest for chunks of the
simulation (for post-processing of averages or std. dev. in those values).
If bool is True, this enables outputting the block averaging data/file at the
integer frequency (set steps_per_data_output_int), while "False"
disables outputting the block averaging data/file.
HistogramFreq : list [bool , int (> 0)] or [Generate_data_bool , steps_per_data_output_int],
default = [True, 10k] or [True , set via formula based on the number of RunSteps or 10k max]
Controls the histograms. Histograms are a binned listing of observation frequency
for a specific thermodynamic variable. In the GOMC code, they also control the output
of a file containing energy/molecule samples, which is only used for the "GCMC"
ensemble simulations for histogram reweighting purposes. If bool is True, this
enables outputting the data to the histogram data at the integer frequency
(set steps_per_data_output_int), while "False" disables outputting the histogram
data.
DistName : str (NO SPACES), default = "dis"
Short phrase which will be combined with RunNumber and RunLetter
to use in the name of the binned histogram for molecule distribution.
HistName : str (NO SPACES), default = "his"
Short phrase, which will be combined with RunNumber and RunLetter,
to use in the name of the energy/molecule count sample file.
RunNumber : int ( > 0 ), default = 1
Sets a number, which is a part of DistName and HistName file name.
RunLetter : str (1 alphabetic character only), default = "a"
Sets a letter, which is a part of DistName and HistName file name.
SampleFreq : int ( > 0 ), default = 500
The number of steps per histogram sample or frequency.
OutEnergy : [bool, bool], default = [True, True]
The list provides the booleans to [block_averages_bool, console_output_bool].
This outputs the energy data into the block averages and console output/log
OutPressure : [bool, bool], default = [True, True]
The list provides the booleans to [block_averages_bool, console_output_bool].
This outputs the pressure data into the block averages and console output/log files.
OutMolNum : [bool, bool], default = [True, True]
The list provides the booleans to [block_averages_bool, console_output_bool].
This outputs the number of molecules data into the block averages and console
output/log files.
OutDensity : [bool, bool], default = [True, True]
The list provides the booleans to [block_averages_bool, console_output_bool].
This outputs the density data into the block averages and console output/log files.
OutVolume : [bool, bool], default = [True, True]
The list provides the booleans to [block_averages_bool, console_output_bool].
This outputs the volume data into the block averages and console output/log files.
OutSurfaceTension : [bool, bool], default = [False, False]
The list provides the booleans to [block_averages_bool, console_output_bool].
This outputs the surface tension data into the block averages and console
output/log files.
FreeEnergyCalc : list [bool , int (> 0)] or [Generate_data_bool , steps_per_data_output_int],
default = None
bool = True enabling free energy calculation during the simulation, false disables
the calculation. The int/step frequency sets the frequency of calculating the free energy.
WARNING: When using the free energy calculations, RcutLow needs to be set to zero (RcutLow=0);
otherwise, the free energy calculations can produce results that are slightly off or wrong.
MoleculeType : list [str , int (> 0)] or ["residue_name" , residue_ID], default = None
The user must set this variable as there is no working default.
Note: ONLY 4 characters can be used for the string (i.e., "residue_name").
Sets the solute molecule kind (residue name) and molecule number (residue ID),
which absolute solvation free will be calculated for.
InitialState : int (>= 0), default = None
The user must set this variable as there is no working default.
The index of LambdaCoulomb and LambdaVDW vectors. Sets the index of the
LambdaCoulomb and LambdaVDW vectors, to determine the simulation lambda value for
VDW and Coulomb interactions.
WARNING : This must an integer within the vector count of the LambdaVDW and LambdaCoulomb,
in which the counting starts at 0.
LambdaVDW : list of floats (0 <= floats <= 1), default = None
The user must set this variable as there is no working default (default = {}).
Lambda values for VDW interaction in ascending order. Sets the intermediate
lambda states to which solute-solvent VDW interactions are scaled.
WARNING : This list must be the same length as the "LambdaCoulomb" list length.
WARNING : All lambda values must be stated in the ascending order,
starting with 0.0 and ending with 1.0; otherwise, the program will terminate.
Example of ascending order 1: [0.0, 0.1, 1.0]
Example of ascending order 2: [0.0, 0.1, 0.2, 0.4, 0.9, 1.0]
LambdaCoulomb : list of floats (0 <= floats <= 1), default = None
Lambda values for Coulombic interaction in ascending order. Sets the intermediate
lambda states to which solute-solvent Coulombic interactions are scaled.
GOMC defauts to the "LambdaVDW" values for the Coulombic interaction
if no "LambdaCoulomb" variable is set.
WARNING : This list must be the same length as the "LambdaVDW" list length.
WARNING : All lambda values must be stated in the ascending order,
starting with 0.0 and ending with 1.0; otherwise, the program will terminate.
Example of ascending order 1: [0.0, 0.1, 1.0]
Example of ascending order 2: [0.0, 0.1, 0.2, 0.4, 0.9, 1.0]
ScaleCoulomb : bool, default = False
Determines to scale the Coulombic interaction non-linearly
(soft-core scheme) or not.
True if the Coulombic interaction needs to be scaled non-linearly.
False if the Coulombic interaction needs to be scaled linearly.
ScalePower : int (>= 0), default = 2
The p value in the soft-core scaling scheme, where the distance
between solute and solvent is scaled non-linearly.
ScaleAlpha : int or float (>= 0), default = 0.5
The alpha value in the soft-core scaling scheme, where the distance
between solute and solvent is scaled non-linearly.
MinSigma : int or float (>= 0), default = 3
The minimum sigma value in the soft-core scaling scheme, where the
distance between solute and solvent is scaled non-linearly.
DisFreq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.15, 'NPT': 0.15, 'GEMC_NVT': 0.2, 'GEMC_NPT': 0.19, 'GCMC': 0.15}
Fractional percentage at which the displacement move will occur
(i.e., fraction of displacement moves).
RotFreq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.15, 'NPT': 0.15, 'GEMC_NVT': 0.2, 'GEMC_NPT': 0.2, 'GCMC': 0.15}
Fractional percentage at which the rotation move will occur.
(i.e., fraction of rotation moves).
IntraSwapFreq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.3, 'NPT': 0.29, 'GEMC_NVT': 0.1, 'GEMC_NPT': 0.1, 'GCMC': 0.1}
Fractional percentage at which the molecule will be removed from a
box and inserted into the same box using coupled-decoupled configurational-bias
algorithm. (i.e., fraction of intra-molecule swap moves).
SwapFreq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.2, 'GEMC_NPT': 0.2, 'GCMC': 0.35}
For Gibbs and Grand Canonical (GC) ensemble runs only: Fractional
percentage at which molecule swap move will occur using coupled-decoupled
configurational-bias. (i.e., fraction of molecule swaps moves).
RegrowthFreq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.3, 'NPT': 0.3, 'GEMC_NVT': 0.2, 'GEMC_NPT': 0.2, 'GCMC': 0.15}
Fractional percentage at which part of the molecule will be deleted and
then regrown using coupled- decoupled configurational-bias algorithm
(i.e., fraction of molecular growth moves).
CrankShaftFreq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.1, 'NPT': 0.1, 'GEMC_NVT': 0.1, 'GEMC_NPT': 0.1, 'GCMC': 0.1}
Fractional percentage at which crankshaft move will occur.
In this move, two atoms that are forming angle or dihedral are selected
randomly and form a shaft. Then any atoms or group that are within these
two selected atoms, will rotate around the shaft to sample intra-molecular
degree of freedom (i.e., fraction of crankshaft moves).
VolFreq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.01, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.01, 'GCMC': 0.0}
For isobaric-isothermal (NPT) ensemble and Gibbs ensemble
(GEMC_NPT and GEMC_NVT) runs only: Fractional percentage at
which a volume move will occur (i.e., fraction of Volume moves).
MultiParticleFreq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.0, 'GCMC': 0.0}
Fractional percentage at which multi-particle move will occur.
In this move, all molecules in the selected simulation box will be rigidly
rotated or displaced simultaneously, along the calculated torque or force
respectively (i.e., fraction of multi-particle moves).
IntraMEMC-1Freq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.0, 'GCMC': 0.0}
Fractional percentage at which specified number of small molecule kind will be
exchanged with a specified large molecule kind in defined sub-volume within
same simulation box. This move need additional information such as
ExchangeVolumeDim, ExchangeRatio, ExchangeSmallKind, and ExchangeLargeKind.
MEMC-1Freq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.0, 'GCMC': 0.0}
Fractional percentage at which specified number of small molecule kind will
be exchanged with a specified large molecule kind in defined sub-volume,
between simulation boxes. This move need additional information such as
ExchangeVolumeDim, ExchangeRatio, ExchangeSmallKind, and ExchangeLargeKind.
IntraMEMC-2Freq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.0, 'GCMC': 0.0}
Fractional percentage at which specified number of small molecule kind
will be exchanged with a specified large molecule kind in defined sub-volume
within same simulation box. Backbone of small and large molecule kind will be
used to insert the large molecule more efficiently. This move need additional
information such as ExchangeVolumeDim, ExchangeRatio, ExchangeSmallKind,
ExchangeLargeKind, SmallKindBackBone, and LargeKindBackBone.
MEMC-2Freq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.0, 'GCMC': 0.0}
Fractional percentage at which specified number of small molecule kind will be
exchanged with a specified large molecule kind in defined sub-volume,
between simulation boxes. Backbone of small and large molecule kind will be
used to insert the large molecule more efficiently. This move need additional
information such as ExchangeVolumeDim, ExchangeRatio, ExchangeSmallKind,
ExchangeLargeKind, SmallKindBackBone, and LargeKindBackBone.
IntraMEMC-3Freq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.0, 'GCMC': 0.0}
Fractional percentage at which specified number of small molecule kind will be
exchanged with a specified large molecule kind in defined sub-volume within same
simulation box. Specified atom of the large molecule kind will be used to insert
the large molecule using coupled-decoupled configurational-bias. This move need
additional information such as ExchangeVolumeDim, ExchangeRatio, ExchangeSmallKind,
ExchangeLargeKind, and LargeKindBackBone.
MEMC-3Freq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.0, 'GCMC': 0.0}
Fractional percentage at which specified number of small molecule kind will be
exchanged with a specified large molecule kind in defined sub-volume,
between simulation boxes. Specified atom of the large molecule kind will be
used to insert the large molecule using coupled-decoupled configurational-bias.
This move need additional information such as ExchangeVolumeDim,
ExchangeRatio, ExchangeSmallKind, ExchangeLargeKind, and LargeKindBackBone.
TargetedSwapFreq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.0, 'GCMC': 0}
Fractional percentage at which targeted swap move will occur.
Note: This is only usable with the 'GCMC', 'GEMC_NVT', and 'GEMC_NPT' ensembles.
Note: This is used in conjunction with the "TargetedSwap_DataInput" variables.
IntraTargetedSwapFreq : int or float (0 <= value <= 1), default are specific for each ensemble
{'NVT': 0.0, 'NPT': 0.0, 'GEMC_NVT': 0.0, 'GEMC_NPT': 0.0, 'GCMC': 0}
Note: This is used in conjunction with the "TargetedSwap_DataInput" variables.
TargetedSwap_DataInput : dict, default=None
A dictionary which can contain one or several targeted swap regions, each designated with
their own tag ID number (aka, subvolume number).
A few examples for TargetedSwap_DataInput input is provided below.
NOTE: MULTIPLE SIMULATION BOXES CAN BE UTILIZED BY SETTING MULTIPLE tag_ID_integer VALUES (INTEGERS VALUES),
NOTE: THIS IS REQUIRED WHEN USING EITHER THE "TargetedSwapFreq" OR "IntraTargetedSwapFreq" MC MOVES.
WARNING: THE tag_ID_integer VALUES MUST BE UNIQUE FOR EACH SUBVOLUME,
OR THE DICTIONARY WILL OVERWRITE THE PREVIOUS SUBVOLUME (tag_ID_integer) SECTION
WITH THE CURRENT tag_ID_integer AND ITS RESPECTIVE VALUES.
Example 1
input_variables_dict={"TargetedSwap_DataInput": {tag_ID_integer: {"SubVolumeType": "dynamic",
"SubVolumeBox": 0, "SubVolumeCenterList": ['0-10', 12, 15, '22-40'], "SubVolumeDim": [1, 2, 3],
"SubVolumeResidueKind": "ALL", "SubVolumeRigidSwap": False, "SubVolumePBC": "XY",
"SubVolumeChemPot": {"MET": -21, "met": -31}}}
Example 2
input_variables_dict={"TargetedSwap_DataInput": {tag_ID_integer: {"SubVolumeType": "static",
"SubVolumeBox": 0, "SubVolumeCenter": [1, 12, 15], "SubVolumeDim": [3, 3, 3],
"SubVolumeResidueKind": ["MET", "met"], "SubVolumeRigidSwap": False, "SubVolumePBC": "XYZ",
"SubVolumeFugacity": {"MET": 0.1, "met": 1}}}
The details of each key and value for the "TargetedSwap_DataInput" are provided below.
--- "SubVolumeType" : str ("static" or "dynamic"), No default is provided.
The type of targeted swap box (subvolume) that will be created.
The "static" type will maintain the box (subvolume) in a fixed location during the whole simulation,
with the center of the box determined by the coordinates set in the
"SubvolumeCenter" parameter.
The "dynamic" type will allow for dynamic movement of the box (subvolume) based atom indices
provided in the SubvolumeCenterList variable. For the "dynamic" type, the user must define a
list of atom indices using "SubVolumeCenterList" keyword; the geometric center of the
provided atom indices will be used as the center of subVolume. User must ensure that the
atoms defined in the atom list remain in the simulation box (by setting the Beta value to 2 in PDB file).
--- "SubVolumeBox" : int (0 or 1), No default is provided.
The simulation box in which the targeted swap subvolume will be applied.
NOTE: Only box zero (0) can be used for the GCMC, NPT, and NVT ensembles.
--- "SubVolumeCenter" : list of three (3) int or float, [x-axis, y-axis, z-axis], No default is provided.
The simulation box is centered on this x, y, and z-axis points (in Angstroms), which is only
utilized when "SubVolumeType" is set to "static".
--- "SubVolumeCenterList" : list of int and/or str (>=0), [atom_index, ..., atom_index], No default is provided.
The simulation box subVolume is centered on the geometric center of the provided atom indices, which is
only used when the "SubVolumeType" is set to "dynamic". For example, [0-10', 12, 15] means that
atom indices 0 to 10, 12 and 15 are used as the geometric center of the simulation box subVolume.
NOTE: THE ATOM INDICES RANGES MUST BE A STRING IN THE FORM '2-20', WITH THE FIRST ATOM INDICES BEING
SMALLER THAN THE SECOND (i.e, 'a-b', where a < b). ALL SINGULAR ATOM INDICES MUST BE INTEGERS.
NOTE: THE SAME ATOM INDICES CAN BE USED 2, 3 OR X TIMES TO WEIGHT that atom 2, 3, OR X TIMES MORE
IN THE GEOMETRIC CENTERING CALCULATION.
NOTE: THE ATOM INDICES START AT ZERO (0), WHILE THE PDB AND PSF FILES START AT ONE (1).
THEREFORE, YOU NEED TO BE CAREFUL WHEN SETTING THE INDICES FROM THE PDB OR PSF VALUES AS THEY ARE
ONE (1) NUMBER OFF.
--- "SubVolumeDim" : list of three (3) int or float (>0), [x-axis, y-axis, z-axis], No default is provided.
This sets the size of the simulation box (subVolume) in the x, y, and z-axis (in Angstroms).
--- "SubVolumeResidueKind" : str or list of str, "ALL" or "residue"
or ["ALL"] or [residue_str, ..., residue_str], No default is provided.
The residues that will be used in the "TargetedSwap_DataInput" subvolume.
Alternatively, the user can just set the value to ["ALL"] or "ALL", which covers all the residues.
--- "SubVolumeRigidSwap" : bool, default = True
Choose whether to use a rigid or flexible molecule insertion using CD-CBMC for the subVolume.
True uses a rigid molecule insertion, while False uses a flexible molecule insertion
--- "SubVolumePBC" : str ('X', 'XY', 'XZ', 'XYZ', 'Y', 'YZ', or 'Z'), default = 'XYZ'.
Apply periodic boundary condition (PBC) in selected axes for the subVolume.
Example 1, 'X' applies PBC only in the X axis. Example 2, 'XY' applies PBC only in the X and Y axes.
Example 3, 'XYZ' applies PBC in the X, Y, and Z axes.
--- "SubVolumeChemPot" : dict {str (4 dig limit) , int or float}, No default is provided.
The chemical potentials in GOMC units of energy, K. If no SubVolumeChemPot is provided
the default system chemical potential values are used.
There is a 4 character limit for the string/residue name since the PDB/PSF
files have a 4 character limitation and require an exact match in the conf file.
Note: These strings must match the residue in the psf and psb files or it will fail.
The name of the residues and their corresponding chemical potential must be specified
for every residue in the system (i.e., {"residue_name" : chemical_potential}).
Note: THIS IS ONLY REQUIRED FOR THE GCMC ENSEMBLE.
Note: IF 2 KEYS WITH THE SAME STRING/RESIDUE ARE PROVIDED, ONE WILL BE AUTOMATICALLY
OVERWRITTEN AND NO ERROR WILL BE THROWN IN THIS CONTROL FILE WRITER.
Note: ONLY THE "SubVolumeChemPot" OR THE "SubVolumeFugacity" CAN BE USED FOR ALL THE
TARGET SWAP BOXES (SUBVOLUMES). IF MIX OF "SubVolumeChemPot" AND "SubVolumeFugacity" ARE
USED THE CONTROL FILE WRITER WILL THROW AN ERROR.
--- "SubVolumeFugacity" : dict {str , int or float (>= 0)}, No default is provided.
The fugacity in GOMC units of pressure, bar. If no "SubVolumeFugacity" is provided
the default system fugacity values are used.
There is a 4 character limit for the string/residue name since the PDB/PSF
files have a 4 character limitation and require an exact match in the conf file.
Note: These strings must match the residue in the psf and psb files or it will fail.
The name of the residues and their corresponding fugacity must be specified
for every residue in the system (i.e., {"residue_name" : fugacity}).
Note: THIS IS ONLY REQUIRED FOR THE GCMC ENSEMBLE.
Note: IF 2 KEYS WITH THE SAME STRING/RESIDUE ARE PROVIDED, ONE WILL BE AUTOMATICALLY
OVERWRITTEN AND NO ERROR WILL BE THROWN IN THIS CONTROL FILE WRITER.
Note: ONLY THE "SubVolumeChemPot" OR THE "SubVolumeFugacity" CAN BE USED FOR ALL THE
TARGET SWAP BOXES (SUBVOLUMES). IF MIX OF "SubVolumeChemPot" AND "SubVolumeFugacity" ARE
USED THE CONTROL FILE WRITER WILL THROW AN ERROR.
ExchangeVolumeDim : list of 3 floats or integers or [X-dimension, Y-dimension, Z-dimension)],
default = [1.0, 1.0, 1.0]
To use all variations of MEMC and Intra-MEMC Monte Carlo moves, the exchange
subvolume must be defined. The exchange sub-volume is defined as an orthogonal box
with x, y, and z-dimensions, where small molecule/molecules kind will be selected
from to be exchanged with a large molecule kind.
Note: Currently, the X and Y dimension cannot be set independently (X = Y = max(X, Y)).
Note: A heuristic for setting good values of the x, y, and z-dimensions is to use
the geometric size of the large molecule plus 1-2 Å in each dimension.
Note: In case of exchanging 1 small molecule kind with 1 large molecule kind in
IntraMEMC-2, IntraMEMC-3, MEMC-2, MEMC-3 Monte Carlo moves, the sub-volume
dimension has no effect on acceptance rate.
MEMC_DataInput : nested lists, default = None
Enter data as a list with some sub-lists as follows:
[[ExchangeRatio_int (> 0), ExchangeLargeKind_str,
[LargeKindBackBone_atom_1_str_or_NONE, LargeKindBackBone_atom_2_str_or_NONE ],
ExchangeSmallKind_str, [SmallKindBackBone_atom_1_str_or_NONE, SmallKindBackBone_atom_2_str_or_NONE ]],
...,
[ExchangeRatio_int (> 0), ExchangeLargeKind_str,
[LargeKindBackBone_atom_1_str_or_NONE, LargeKindBackBone_atom_2_str_or_NONE ],
ExchangeSmallKind_str, [SmallKindBackBone_atom_1_str_or_NONE, SmallKindBackBone_atom_2_str_or_NONE ].
NOTE: CURRENTLY ALL THESE INPUTS NEED TO BE SPECIFIED, REGARDLESS OF THE MEMC TYPE
SELECTION. IF THE SmallKindBackBone or LargeKindBackBone IS NOT REQUIRED FOR THE
MEMC TYPE, None CAN BE USED IN PLACE OF A STRING.
Note: These strings must match the residue in the psf and psb files or it will fail.
It is recommended that the user print the Charmm object psf and pdb files
and review the residue names that match the atom name before using the in
the MEMC_DataInput variable input.
Note: see the below data explanations for the ExchangeRatio, ExchangeSmallKind,
ExchangeLargeKind, LargeKindBackBone, SmallKindBackBone.
Example 1 (MEMC-1) : [ [1, 'WAT', [None, None], 'wat', [None, None]] ,
[1, 'WAT', [None, None], 'wat', [None, None]]
Example 2 (MEMC-2): [ [1, 'WAT', ['O1', 'H1'], 'wat', ['O1', 'H1' ]] ,
[1, 'WAT', ['H1', 'H2'], 'wat', ['H1', 'H2' ]]
Example 3 (MEMC-3) : [ [2, 'WAT', 'O1', 'H1'], 'wat', [None, None]] ,
[2, 'WAT', ['H1', 'H2'], 'wat', [None, None]]
--- ExchangeRatio = MEMC parameters (all ensembles): int (> 0), default = None
The Ratio of exchanging small molecule/molecules with 1 large molecule.
To use all variation of MEMC and Intra-MEMC Monte Carlo moves,
the exchange ratio must be defined. The exchange ratio defines how
many small molecule will be exchanged with 1 large molecule. For each
large-small molecule pairs, one exchange ratio must be defined.
--- ExchangeSmallKind = MEMC parameters (all ensembles): str, default = None
The small molecule kind (resname) to be exchanged.
Note: ONLY 4 characters can be used for the strings.
To use all variation of MEMC and Intra-MEMC Monte Carlo moves,
the small molecule kind to be exchanged with a large molecule
kind must be defined. Multiple small molecule kind can be specified.
--- ExchangeLargeKind = MEMC parameters (all ensembles): str, default = None
The large molecule kind (resname) to be exchanged.
Note: ONLY 4 characters can be used for the strings.
To use all variation of MEMC and Intra-MEMC Monte Carlo moves,
the large molecule kind to be exchanged with small molecule
kind must be defined. Multiple large molecule kind can be specified.
--- LargeKindBackBone = MEMC parameters (all ensembles): list [str, str] or [None, None], default = None
Note: ONLY 4 characters can be used for the strings.
The [None, None] values can only be used if that MEMC type does
not require them. The strings for the the atom name 1 and atom name 2
that belong to the large molecule’s backbone
(i.e., [str_for_atom_name_1, str_for_atom_name_2])
To use MEMC-2, MEMC-3, IntraMEMC-2, and IntraMEMC-3 Monte Carlo moves, the
large molecule backbone must be defined. The backbone of the molecule is defined
as a vector that connects two atoms belong to the large molecule. The large
molecule backbone will be used to align the sub-volume in MEMC-2 and IntraMEMC-2
moves, while in MEMC-3 and IntraMEMC-3 moves, it uses the atom name to start
growing the large molecule using coupled-decoupled configurational-bias. For
each large-small molecule pairs, two atom names must be defined.
Note: all atom names in the molecule must be unique.
Note: In MEMC-3 and IntraMEMC-3 Monte Carlo moves, both atom names must be same,
otherwise program will be terminated.
Note: If the large molecule has only one atom (mono atomic molecules),
same atom name must be used for str_for_atom_name_1 and str_for_atom_name_2
of the LargeKindBackBone.
--- SmallKindBackBone = MEMC parameters (all ensembles): list [str, str] or [None, None], default = None
Note: ONLY 4 characters can be used for the strings.
The [None, None] values can only be used if that MEMC type does not
require them. The strings for the the atom name 1 and atom name 2 that
belong to the small molecule’s backbone
(i.e., [str_for_atom_name_1, str_for_atom_name_2])
To use MEMC-2, and IntraMEMC-2 Monte Carlo moves, the small molecule backbone
must be defined. The backbone of the molecule is defined as a vector that
connects two atoms belong to the small molecule and will be used to align the
sub-volume. For each large-small molecule pairs, two atom names must be defined.
Note: all atom names in the molecule must be unique.
Note: If the small molecule has only one atom (mono atomic molecules), same atom
name must be used str_for_atom_name_1 and str_for_atom_name_2
of the SmallKindBackBone.
# *******************************************************************
# input_variables_dict options (keys and values) - (end)
# Note: the input_variables_dict keys are also attributes
# *******************************************************************
Attributes
----------
input_error : bool
This error is typically incurred from an error in the user input values.
However, it could also be due to a bug, provided the user is inputting
the data as this Class intends.
all_failed_input_List : list
A list of all the inputs that failed, but there may be some inputs that
ensemble_typ : str, ['NVT', 'NPT', 'GEMC_NPT', 'GCMC-NVT', 'GCMC']
The ensemble type of the simulation.
RunSteps : int (>0), must be an integer greater than zero.
Sets the total number of simulation steps.
Temperature : float or int (>0), must be an integer greater than zero.
Temperature of system in Kelvin (K)
ff_psf_pdb_file_directory : str (optional), default=None (i.e., the current directory).
The full or relative directory added to the force field, psf, and pdb
file names, created via the Charmm object.
check_input_files_exist: bool (default=True)
Check if the force field, psf, and pdb files exist.
If the files are checked and do not exist, the writer will throw a ValueError.
True, check if the force field, psf, and pdb files exist.
False, do not check if the force field, psf, and pdb files exist.
Restart : boolean, default = False
Determines whether to restart the simulation from restart file
(``*_restart.pdb`` and ``*_restart.psf``) or not.
RestartCheckpoint : boolean, default = False
Determines whether to restart the simulation with the checkpoint
file (checkpoint.dat) or not. Restarting the simulation with checkpoint.dat
would result in an identical outcome, as if previous simulation was continued.
Parameters : str, (default=None)
Override all other force field directory and filename input with the correct extension (.inp or .par).
Note: the default directory is the current directory with the Charmm object file name.
Coordinates_box_0 : str, (default=None)
Override all other box 0 pdb directory and filename inputs with the correct extension.
Note: the default directory is the current directory with the Charmm object file name.
Structure_box_0 : str, (default=None)
Override all other box 0 psf directory and filename inputs with the correct extension.
Note: the default directory is the current directory with the Charmm object file name.
Coordinates_box_1 : str, (default=None)
Override all other box 1 pdb directory and filename inputs with the correct extension.
Note: the default directory is the current directory with the Charmm object file name.
Structure_box_1 : str, (default=None)
Override all other box 1 psf directory and filename inputs with the correct extension.
Note: the default directory is the current directory with the Charmm object file name.
binCoordinates_box_0 : str, (default=None)
The box 0 binary coordinate file is used only for restarting a GOMC simulation,
which provides increased numerical accuracy.
extendedSystem_box_0 : str, (default=None)
The box 0 vectors and origin file is used only for restarting a GOMC simulation.
binVelocities_box_0 : str, (default=None)
The box 0 binary velocity file is used only for restarting a GOMC simulation,
which provides increased numerical accuracy. These velocities are only passed thru
GOMC since Monte Carlo simulations do not utilize any velocity information.
binCoordinates_box_1 : str, (default=None)
The box 1 binary coordinate file is used only for restarting a GOMC simulation,
which provides increased numerical accuracy.
extendedSystem_box_1 : str, (default=None)
The box 1 vectors and origin file is used only for restarting a GOMC simulation.
binVelocities_box_1 : str, (default=None)
The box 1 binary velocity file is used only for restarting a GOMC simulation,
which provides increased numerical accuracy. These velocities are only passed thru
GOMC since Monte Carlo simulations do not utilize any velocity information.
input_variables_dict: dict, default = None
These input variables are optional and override the default settings.
Changing these variables likely required for more advanced systems.
The details of the acceptable input variables for the selected
ensembles can be found by running the code below in python,
>>> print_valid_ensemble_input_variables('GCMC', description = True)
which prints the input_variables with their subsection description
for the selected 'GCMC' ensemble (other ensembles can be set as well).
Example : input_variables_dict = {'PRNG' : 123,
'ParaTypeCHARMM' : True }
conf_filename : str
The name of the GOMC contol file, which will be created. The extension
of the GOMC control file can be .conf, or no extension can be provided.
If no extension is provided, this writer will automatically add the
.conf extension to the provided string.
box_0_vectors : numpy.ndarray, [[float float float], [float float float], [float float float]]
Three (3) sets vectors for box 0 each with 3 float values, which represent
the vectors for the Charmm-style systems (units in Angstroms (Ang))
box_1_vectors : numpy.ndarray, [[float float float], [float float float], [float float float]]
Three (3) sets vectors for box 1 each with 3 float values, which represent
the vectors for the Charmm-style systems (units in Angstroms (Ang))
coul_1_4 : float or int
The non-bonded 1-4 coulombic scaling factor, which is the
same for all the residues/molecules, regardless if
differenct force fields are utilized.
residues : list, [str, ..., str]
Labels of unique residues in the Compound. Residues are assigned by
checking against Compound.name. Only supply residue names as 4 character
strings, as the residue names are truncated to 4 characters to fit in the
psf and pdb file.
all_res_unique_atom_name_dict : dict, {str : [str, ..., str]}
A dictionary that provides the residue names (keys) and a list
of the unique atom names in the residue (value), for the
combined structures (box 0 and box 1 (if supplied)).
any input_variables_dict key : varies (see each input_variables_dict key and value)
Any of the input variables keys is also an Attribute and can be called
the same way. Please see the input_variables_dict keys in the
Parameters section above for all the available attributes.
Notes
-------
The user input variables (input_variables_dict) and the specific
ensembles.
The details of the required inputs for the selected
ensembles can be found by running this python workbook,
>>> print_valid_required_input_variables('NVT', description = True)
which prints the required inputs with their subsection description
for the selected 'NVT' ensemble (other ensembles can be set as well).
The details of the input variables for the selected
ensembles can be found by running this python workbook,
>>> print_valid_ensemble_input_variables('NPT', description = True)
which prints the input variables with their subsection description
for the selected 'NPT' ensemble (other ensembles can be set as well).
Note: The box units imported are in nm (standard MoSDeF units).
The units for this writer are auto-scaled to Angstroms, so they
can be directly used in the GOMC or NAMD engines.
Note: all of the move types are not available in for every ensemble.
Note: all of the move fractions must sum to 1, or the control file
writer will fail.
The input variables (input_variables_dict) and text extracted with permission from
the GOMC manual version 2.60. Some of the text was modified from its original version.
Cite: Potoff, Jeffrey; Schwiebert, Loren; et. al. GOMC Documentation.
https://raw.githubusercontent.com/GOMC-WSU/GOMC/master/GOMC_Manual.pdf, 2021.
Returns
-------
If completed without errors: str
returns "GOMC_CONTROL_FILE_WRITTEN" when the GOMC input control file is writen
If completed with errors: None
"""
# write the control file and return a testable value
gomc_control = GOMCControl(
charmm_object,
ensemble_type,
RunSteps,
Temperature,
ff_psf_pdb_file_directory=ff_psf_pdb_file_directory,
check_input_files_exist=check_input_files_exist,
Restart=Restart,
RestartCheckpoint=RestartCheckpoint,
ExpertMode=ExpertMode,
Parameters=Parameters,
Coordinates_box_0=Coordinates_box_0,
Structure_box_0=Structure_box_0,
Coordinates_box_1=Coordinates_box_1,
Structure_box_1=Structure_box_1,
binCoordinates_box_0=binCoordinates_box_0,
extendedSystem_box_0=extendedSystem_box_0,
binVelocities_box_0=binVelocities_box_0,
binCoordinates_box_1=binCoordinates_box_1,
extendedSystem_box_1=extendedSystem_box_1,
binVelocities_box_1=binVelocities_box_1,
input_variables_dict=input_variables_dict,
)
test_gomc_control_write_conf_file = gomc_control.write_conf_file(
conf_filename
)
if (
gomc_control.input_error is False
and test_gomc_control_write_conf_file == "GOMC_CONTROL_FILE_WRITTEN"
):
return "GOMC_CONTROL_FILE_WRITTEN"
else:
return None