Loading in Forcefield Files#

Lennard-Jones forcefield parameters are stored in comma-separated-value format in PorousMaterials.PATH_TO_FORCEFIELDS.

Interaction of an adsorbate with the framework is modeled as pair-wise additive and with Lennard-Jones potentials of the form:

V(r) = 4 * epsilon * [ x ^ 12 - x ^ 6 ], where x = sigma / r

The Lennard Jones force field input files, e.g. UFF.csv contain a list of pure (i.e. X-X, where X is an atom) sigmas and epsilons in units Angstrom and Kelvin, respectively. Note that, e.g., in the UFF paper, the Lennard Jones potential is written in a different form and thus parameters need to be converted to correspond to the functional form used in PorousMaterials.jl.

using PorousMaterials

ljff = LJForceField("UFF.csv")

PorousMaterials will the output information about the forcefield file you just loaded:

    Force field: UFF.csv
    Number of atoms included: 106
    Cut-off radius (Å) = 14.0    

This also prints all of the atoms included in the loaded forcefield with their given ϵ and σ. This was excluded because it would use too much space on this page.

Building Blocks of PorousMaterials: Lennard-Jones forcefields#

# read in Lennard-Jones force field parameters from the Universal Force Field
forcefield = LJForceField("UFF.csv", cutoffradius=14.0, mixing_rules="Lorentz-Berthelot")

# access the Lennard-Jones epsilon & sigma for Xe
forcefield.pure_ϵ[:Xe] # K
forcefield.pure_σ[:Xe] # Å

# access the Lennard-Jones epsilon & sigma for Xe-C interactions
forcefield.ϵ[:Xe][:C] # K                                                                 
forcefield.σ²[:Xe][:C] # Å (store σ² for faster computation)

Building Blocks of PorousMaterials: Potential energies#

First, set the fractional coordinates of the molecule in the context of some unit cell box.

# molecule in a framework
set_fractional_coords!(molecule, framework.box)

# molecule in a 10 by 10 by 10 cube
box = Box(10.0, 10.0, 10.0, π/2, π/2, π/2) # make a box
set_fractional_coords!(molecule, box)

Potential Energies: Van der Waals#

What is the van der Waals potential energy of a Xe adsorbate inside SBMOF-1 at [0.0, 1.0, 3.0] Cartesian coordinates using the UFF as a molecular model?

using PorousMaterials

framework = Framework("SBMOF-1.cif")

forcefield = LJForceField("UFF.csv")

molecule = Molecule("Xe")
set_fractional_coords!(molecule, framework.box)

translate_to!(molecule, [0.0, 1.0, 0.0], framework.box) # need box b/c we're talking Cartesian

energy = vdw_energy(framework, molecule, forcefield) # K

Potential Energies: Electrostatics#

What is the electrostatic potential energy of a CO2 adsorbate inside CAXVII_clean at [0.0, 1.0, 0.0] Cartesian coordinate?

using PorousMaterials

framework = Framework("CAXVII_clean.cif") # has charges

molecule = Molecule("CO2")
set_fractional_coords!(molecule, framework.box)

translate_to!(molecule, [0.0, 1.0, 0.0], framework.box) # need box b/c we're talking Cartesian

rotate!(molecule, framework.box) # let's give it a random orientation

# this is for speed. pre-compute k-vectors and allocate memory
eparams, kvectors, eikar, eikbr, eikcr = setup_Ewald_sum(12.0, framework.box)

energy = electrostatic_potential_energy(framework, molecule, eparams, kvectors, eikar, eikbr, eikcr)

Potential Energies: Equations of state#

Calculate fugacity of methane at 298 K and 65 bar using the Peng-Robinson EOS:

fluid = PengRobinsonFluid(:CH4)
props = calculate_properties(fluid, 298.0, 65.0) # dictionary of PREOS properties
props["fugacity coefficient"] # 0.8729

Calculate compressibility factor of hydrogen at 300 K and 50 bar using van der Waals EOS:

fluid = VdWFluid(:H2)
props = calculate_properties(fluid, 300.0, 50.0) # dictionary of VdW properties
props["compressibility factor"] # 1.03511

Pass eos=:PengRobinson to gcmc_simulation to automatically convert pressure to fugacity using the Peng-Robinson equation of state.

Forcefields#

# PorousMaterials.LJForceFieldType.

Data structure for a Lennard Jones forcefield.

Attributes

source

# PorousMaterials.replication_factorsFunction.

repfactors = replication_factors(unitcell, cutoffradius)

Find the replication factors needed to make a supercell big enough to fit a sphere with the specified cutoff radius. In PorousMaterials.jl, rather than replicating the atoms in the home unit cell to build the supercell that serves as a simulation box, we replicate the home unit cell to form the supercell (simulation box) in a for loop. This function ensures enough replication factors such that the nearest image convention can be applied.

A non-replicated supercell has 1 as the replication factor in each dimension (repfactors = (1, 1, 1)).

Arguments

Returns

source

# PorousMaterials.check_forcefield_coverageFunction.

check_forcefield_coverage(framework, ljforcefield)
check_forcefield_coverage(molecule, ljforcefield)

Check that the force field contains parameters for every atom present in a framework or molecule. Will print out which atoms are missing.

Arguments

Returns

source

Potential Energy#

# PorousMaterials.PotentialEnergyType.

pe = PotentialEnergy()

Data structure to store potential energy, partitioned into van der Waals (energy.vdw) and electrostatic (energy.coulomb) interactions, both Float64.

This returns a PotentialEnergy data type where the vdw and coulomb attributes are set to 0.0

Returns

Attributes

source

# PorousMaterials.SystemPotentialEnergyType.

system_potential_energy = SystemPotentialEnergy()

Data structure to facilitate storing/partitioning potential energy of a system. It stores the potential energy from guest-host and guest-guest interactions separately.

This initializes guesthost and guestguest with PotentialEnergy(), so when it is created the total energy recorded is 0.0

Returns

Attributes

source

Nearest Image Conventions#

# PorousMaterials.nearest_image!Function.

nearest_image!(dxf)

Applies the nearest image convention on a vector dxf between two atoms in fractional space; modifies dxf for nearest image convention. Fractional coordinates here fall in [0, 1] so that the box is [0, 1]^3 in fractional space.

Warning: this assumes the two molecules are in the box described by fractional coords [0, 1]³.

Arguments

source

Electrostatics Energy#

# PorousMaterials.EikrType.

eikr = Eikr(eikar, eikbr, eikcr)

mutable struct for holding the eikr vectors

Attributes

source

# PorousMaterials.electrostatic_potential_energyFunction.

ϕ = electrostatic_potential_energy(framework, molecule, eparams, eikr)

Compute the electrostatic potential energy of a molecule inside a framework.

The electrostatic potential is created by the point charges assigned to the framework atoms in framework.charges. Periodic boundary conditions are applied through the Ewald summation. The spurious self-interaction term is neglected here because we are looking at differences in energy in a Monte Carlo simulation.

Warning: it is assumed that the framework is replicated enough such that the nearest image convention can be applied for the short-range cutoff radius supplied in eparams.sr_cutoff_r.

Arguments

Returns

source

ϕ = electrostatic_potential_energy(molecules, eparams, box, eikr)

Compute the electrostatic potential energy of a system comprised of an array of Molecules.

The EWald summation is used here in a double for loop; do not use this function for Monte Carlo simulations because it is computationally expensive.

Returns an EwaldSum type containing short-range and long-range contributions to the Ewald sum as well as the spurious self-interaction and intramolecular interactions. Access via (ϕ.sr, ϕ.lr, ϕ.self, ϕ.intra).

Units of energy: Kelvin

Arguments

Returns

source

# PorousMaterials.precompute_kvec_wtsFunction.

kvectors = precompute_kvec_wts(kreps, box, α, max_mag_k_sqrd=Inf)

For speed, pre-compute the weights for each reciprocal lattice vector for the Ewald sum in Fourier space. This function takes advantage of the symmetry: cos(-k⋅(x-xᵢ)) + cos(k⋅(x-xᵢ)) = 2 cos(k⋅(x-xᵢ))

If max_mag_k_sqrd is passed, k-vectors with a magnitude greater than max_mag_k_sqrd are not included.

Arguments

k-vectors with magnitude squared greater than this.

Returns

corresponding weights indicating the contribution to the Fourier sum.

source

# PorousMaterials.setup_Ewald_sumFunction.

eparams = setup_Ewald_sum(box, sr_cutoff_r; ϵ=1e-6, verbose=false)

Given the short-range cutoff radius and simulation box, automatically compute Ewald convergence parameter and number of k-vector replications in Fourier space required for a given precision. Constructs and returns Ewald parameters data type with this information.

Also, pre-compute weights on k-vector contributions to Ewald sum in Fourier space.

Also, allocate OffsetArrays for storing e^{i * k ⋅ r} where r = x - xⱼ and k is a reciprocal lattice vector.

Arguments

Returns

corresponding weights indicating the contribution to the Fourier sum.

source

# PorousMaterials.total_electrostatic_potential_energyFunction.

total_ϕ = total_electrostatic_potential_energy(molecules, eparams, box, eikr)

Calculates the total electrostatic potential energy of an array of Molecules using a Grand Canonical Monte Carlo (GCMC) algorithm. #TODO add to this

Arguments

Returns

source

total_ϕ = total_electrostatic_potential_energy(framework, molecules, eparams, eikr)

Explanation of totalelectrostaticpotential_energy that uses framework

Arguments

source

Van der Waals Energy#

# PorousMaterials.lennard_jonesFunction.

energy = lennard_jones(r², σ², ϵ)  (units: Kelvin)

Calculate the lennard jones potential energy given the square of the radius r between two lennard-jones spheres. σ and ϵ are specific to interaction between two elements. Return the potential energy in units Kelvin (well, whatever the units of ϵ are).

Arguments

Returns

source

# PorousMaterials.vdw_energyFunction.

energy = vdw_energy(framework, molecule, ljforcefield)

Calculates the van der Waals interaction energy between a molecule and a framework. Applies the nearest image convention to find the closest replicate of a specific atom.

WARNING: it is assumed that the framework is replicated sufficiently such that the nearest image convention can be applied. See replicate.

Arguments

Returns

source

gg_energy = vdw_energy(molecule_id, molecules, ljforcefield, simulation_box)

Calculates van der Waals interaction energy of a single adsorbate molecules[molecule_id] with all of the other molecules in the system. Periodic boundary conditions are applied, using the nearest image convention.

Arguments

Returns

source

# PorousMaterials.vdw_energy_no_PBCFunction.

pot_energy = vdw_energy_no_PBC(atoms, molecule, ljff)

Assumes unit cell box is a unit cube and no periodic boundary conditions are applied.

source