PorousMaterials relies on functions that fall outside of the sections discussed up to this point. They are useful, but operate on their own for the most part.
Control over directories for input and output files#
Call print_file_paths()
to show where input/output files are read from/written to.
To change the directory where certain files are read from/output to, for example:
@eval PorousMaterials PATH_TO_CRYSTALS = joinpath(pwd(), "my_xtals")
@eval PorousMaterials PATH_TO_FORCEFIELDS = joinpath(pwd(), "my_ffs")
@eval PorousMaterials PATH_TO_GRIDS = joinpath(pwd(), "my_grids")
@eval PorousMaterials PATH_TO_MOLECULES = joinpath(pwd(), "my_molecules")
@eval PorousMaterials PATH_TO_DATA = pwd()
To use absolute file paths when reading in e.g. crystals via the Framework
constructor, you can simply:
@eval PorousMaterials PATH_TO_CRYSTALS = ""
Call set_default_file_paths()
to set input/output file paths back to default.
The PATH_TO_DATA is crucial for loading in data files. These functions allow the user to control this after they have done using PorousMaterials
. The set_tutorial_mode()
function has been discussed before, and it allows you to recreate our example and try PorousMaterials before loading your data. The other functions allow the user to reset the PATH_TO_DATA to the data folder in their current directory or to another directory on their machine if their files are stored in many places.
Reading in Atomic Values#
These functions are used to read in the atomicmasses.csv
, atom_properties.csv
, and cpk_atom_colors.csv
files from the current PATH_TO_DATA
directory. They contain information on the masses, radii, and cpk color scheme for atoms.
Using .xyz files#
These functions allow the user to load and save .xyz files describing where molecules appear in a given space. This can be used to save the location of molecules in the middle of a simulation or to visualize what is happening.
Fitting data to adsorption models#
PorousMaterials allows for a DataFrame
to be read in and fitted to a single-site Langmuir model or to a Henry's law model.
using PorousMaterials
using DataFrames
adsorption_data = DataFrame(Dict("Pressure (bar)" => [0.008045, 0.042218, 0.078772, 0.108018, 0.156741, 0.312670, 0.414986, 0.517303, 0.619628,
0.719519, 0.821872, 0.863296, 0.912055, 0.960878, 0.982918, 0.990353, 0.995361, 0.998043,
1.000610, 1.005600, 1.005720],
"Adsorption (mmol/g)" => [4.062603, 4.462196, 4.560714, 4.659598, 4.707321, 4.950402, 5.045670, 5.140938,
5.286339, 5.431875, 5.727768, 5.826027, 6.074420, 6.673929, 7.324955, 8.026830,
8.778973, 10.133170, 10.835313, 11.487143, 12.189375]))
# We can fit the adsorption data to a Langmuir isotherm with the following call. Note that we need to enter the column names for the pressure and adsorption.
results = fit_adsorption_isotherm(adsorption_data, Symbol("Pressure (bar)"), Symbol("Adsorption (mmol/g)"), :langmuir)
M, K = results["M"], results["K"]
# We can also use the function to get the Henry Coefficient
results = fit_adsorption_isotherm(adsorption_data, Symbol("Pressure (bar)"), Symbol("Adsorption (mmol/g)"), :henry)
H = results["H"]
PATH_TO_DATA Control#
#
PorousMaterials.print_file_paths
— Function.
print_file_paths()
Print off paths where PorousMaterials.jl looks for input files and writes output files.
#
PorousMaterials.set_default_file_paths
— Function.
set_default_file_paths(print_paths=true)
Sets the default paths for where input files and some output files are stored. To see current set up, call print_file_paths
#
PorousMaterials.set_tutorial_mode
— Function.
set_tutorial_mode()
Places PorousMaterials in "Tutorial Mode". It changes the PATH_TO_DATA
variable to the directory where the PorousMaterials test data is stored. It can be used to follow examples shown in the README. It displays a warning so that the user knows They are no longer using their own data.
Reading in Atomic Values#
#
PorousMaterials.read_atomic_radii
— Function.
atomic_radii = read_atomic_radii()
Return atomic_radii::Dict{Symbol, Float64}
, where atom_masses[":C"]
gives the atomic radii of carbon (10.87 Angstrom).
Returns
atomic_radii::Dict{Symbol, Float64}
: A dictionary linking an element symbol to its' corresponding atomic radius
#
PorousMaterials.read_atomic_masses
— Function.
atomic_masses = read_atomic_masses()
Read the data/atomicmasses.csv
file to construct a dictionary of atoms and their atomic masses in amu.
Returns
atomic_masses::Dict{Symbol, Float64}
: A dictionary containing the atomic masses of each atom stored indata/atomicmasses.csv
#
PorousMaterials.read_cpk_colors
— Function.
atom_colors = read_cpk_colors()
Read in CPK color scheme for atoms. Return atom_colors::Dict{Symbol, Tuple{Int, Int, Int}}
such that atom_colors[":C"]
gives RGB code for carbon as a tuple, (144, 144, 144)
. https://en.wikipedia.org/wiki/CPK_coloring
Returns
atom_colors::Dict{Symbol, Tuple{Int, Int, Int}}
: A dictionary linking an element symbol to its' corresponding CPK color in RGB
Using .xyz files#
#
PorousMaterials.read_xyz
— Function.
atoms, x = read_xyz(filename)
Return the list of atoms
(Array{Symbol, 1}) and their Cartesian coordinates x::Array{Float64, 2}
as stored in the .xyz file. x[:, k]
will return Cartesian coords of the kth atom.
Arguments
filename::AbstractString
: The filename of the .xyz file
Returns
atoms::Array{Symbol, 1}
: An array of atoms stored as symbols e.g. [:H, :H, :O] read
from the .xyz file.
x::Array{Float64, 2}
: The Cartesian coordinates of the atoms.x[:, k]
will return cartesian coordinates of the k-th atom
#
PorousMaterials.write_xyz
— Function.
write_xyz(atoms, x, filename; comment="")
write_xyz(molecules, box, filename; comment="")
write_xyz(framework, filename; comment="", center=false)
Write a molecule, framework, or array of atoms & positions to an .xyz file.
Arguments
atoms::Array{Symbol, 1}
: An array of atoms stored as symbols e.g. [:H, :H, :O]x::Array{Float64, 2}
: The Cartesian coordinates of the atoms.
x[:, k]
contains Cartesian coordinates of the k-th atom
molecules::Array{Molecule, 1}
: an array of molecules whose atoms to write to .xyzframework::Framework
: a crystal structure whose atoms to write to .xyzfilename::AbstractString
: The filename of the .xyz file. (".xyz" appended automatically
if the extension is not provided.) (absolute path)
comment::AbstractString
: comment if you'd like to write to the file.center::Bool
: shift atoms so that origin is the center of theframework.box
write_xyz(box, molecules, xyz_file)
Writes the coordinates of all atoms in molecules to the given xyz_file file object passing a file object around is faster for simulation because it can be opened once at the beginning of the simulation and closed at the end.
This writes the coordinates of the molecules in cartesian coordinates, so the box is needed for the conversion.
Arguments
box::Box
: The box the molecules are in, to convert molecule positions to cartesian coordinatesmolecules::Array{Molecule, 1}
: The array of molecules to be written to the filexyz_file::IOStream
: The open 'write' file stream the data will be saved to
Generic Rotations#
#
PorousMaterials.rotation_matrix
— Function.
r = rotation_matrix()
Generate a 3x3 random rotation matrix r
such that when a point x
is rotated using this rotation matrix via r * x
, this point x
is placed at a uniform random distributed position on the surface of a sphere of radius norm(x)
. See James Arvo. Fast Random Rotation Matrices.
https://pdfs.semanticscholar.org/04f3/beeee1ce89b9adf17a6fabde1221a328dbad.pdf
Returns
r::Array{Float64, 2}
: A 3x3 random rotation matrix
R = rotation_matrix(θ, u, assume_unit_vector=false) # 3 by 3 rotation matrix, angle θ about vector u
R = rotation_matrix(θ, dim) # 3 by 3 rotation matrix, angle θ about axis `dim`
Determine the 3D rotation matrix to rotate an angle θ (radians) about axis u
.
See Wikipedia.
Arguments
θ::Float64
: angle to rotate about an axis, in radiansu::Array{Float64, 1}
: axis about which to rotatedim::Int
: 1, 2, 3 for rotation about x-, y-, or z-axis, respectively.assume_unit_vector::Bool
: assumeu
is a unit vector; otherwise,u
will be normalized
internal to this function.
Returns
R::Array{Float64, 2}
: 3D rotation matrix. soR * x
will rotate vectorx
as desired.
Fitting data#
#
PorousMaterials.fit_adsorption_isotherm
— Function.
params = fit_adsorption_isotherm(df, pressure_col_name, loading_col_name, model)
Takes in a DataFrame df
containing adsorption isotherm data and fits an analytical model to the data to identify its parameters of best fit, returned as a dictionary. Available models are :henry
and :langmuir
The Henry model takes the following form: N = HP The identified Henry coefficient is params["H"]
.
The Langmuir model takes the following form: N = (MKP)/(1+KP) where N is the total adsorption, M is the maximum monolayer coverage, K is the Langmuir constant. and P is the pressure of the gas.
Arguments
df::DataFrame
: The DataFrame containing the pressure and adsorption data for the isothermpressure_col_name::Symbol
: The header of the pressure column. Can be found withnames(df)
loading_col_name::Symbol
: The header of the loading/adsorption column. Can be found withnames(df)
model::Symbol
: The model chosen to fit to the adsorption isotherm data
Returns
params::Dict{AbstractString, Float64}
: A Dictionary with the parameters corresponding to each model along with the MSE of the fit.:langmuir
contains "M" and "K".:henry
contains "H".