Skip to content

Commit

Permalink
Merge pull request #114 from SimonEnsemble/symmetry_reader
Browse files Browse the repository at this point in the history
Symmetry reader
  • Loading branch information
SimonEnsemble committed Nov 28, 2019
2 parents 13d5d81 + 2c0e629 commit 5fc9a85
Show file tree
Hide file tree
Showing 27 changed files with 2,662 additions and 295 deletions.
2 changes: 1 addition & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ using PorousMaterials
repo = "github.com/SimonEnsemble/PorousMaterials.jl.git",
# This is a link to the main repo and the master branch
# target = "build",
julia = "1.0",
julia = "1.2",
osname = "linux",
deps = Deps.pip("mkdocs", "mkdocs-windmill", "pymdown-extensions") # These are dependencies for the site, not the package
)
8 changes: 4 additions & 4 deletions docs/src/guides/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ Yes! See [here](https://github.com/JuliaLang/IJulia.jl).

**How can I convert my `.cif` into P1 symmetry for `PorousMaterials.jl`?**

We hope someone will contribute this feature to `PorousMaterials.jl` eventually. For now, you can use [OpenBabel](http://openbabel.org/wiki/Main_Page):
`PorousMaterials.jl` will automatically do this for you! It looks for the
`_symmetry_equiv_pos_as_xyz` tag in the `.cif` file and uses those symmetry operations to replicate the structure in a lower symmetry into P1 symmetry.

```
obabel -icif non-P1.cif -ocif -O P1.cif --fillUC strict
```
It is important to note that `PorousMaterials.jl` will read in the space group
name, but it does **NOT** use this for converting your structure to P1.
2 changes: 1 addition & 1 deletion docs/src/guides/help_wanted.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* consolidate `eikar`, `eikbr`, `eikcr` somehow without slowing down the Ewald sum.
* more tests added to `tests/runtests.jl`, `tests/henry_tests.jl`, `tests/gcmc_tests.jl`
* geometric-based pore size calculations (largest free and included spheres), surface area, and porosity calculations that take `Framework`'s as input
* handle .cif's without P1 symmetry. i.e. convert any .cif to P1 symmetry
* ~~handle .cif's without P1 symmetry. i.e. convert any .cif to P1 symmetry~~
* extend `gcmc_simulation` to handle mixtures
* better default rules for choosing Ewald sum parameters? alpha, kvectors required...
* Henry coefficient code prints off Ewald sum params 5 times if run with one core...
Expand Down
98 changes: 96 additions & 2 deletions docs/src/manual/boxes_crystals_grids.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Loading in Crystal Structure Files

Place `.cif` and `.cssr` crystal structure files in `PorousMaterials.PATH_TO_CRYSTALS`. `PorousMaterials.jl` currently takes crystals in P1 symmetry only. From here you can start julia and do the following to load a framework and start working with it.
Place `.cif` and `.cssr` crystal structure files in `PorousMaterials.PATH_To_CRYSTALS`. `PorousMaterials.jl` can load in `.cif` files of any symmetry as long as the symmetry operations are included. From here you can start julia and do the following to load a framework and start working with it.

```julia
using PorousMaterials
Expand All @@ -22,6 +22,91 @@ Number of charges = 0
Chemical formula: Dict(:H=>8,:S=>1,:Ca=>1,:O=>6,:C=>14)
```

If the file is not in P1 symmetry, it will be converted within the framework reader and this message will be displayed.

```julia
┌ Warning: Name_of_file.cif is not in P1 symmetry. It is being converted to P1 for use in PorousMaterials.jl.
└ @ PorousMaterials ~/osu_undergrad/simon_ensemble/PorousMaterials.jl/src/Crystal.jl:284
```

PorousMaterials also gives the option to read in structures in the lower level
symmetries and convert them to P1 before simulation.

```julia
framework = Framework("ORIVOC_clean.cif"; remove_overlap=true, convert_to_p1=false)
# the remove_overlap argument is specific to this structure, not all frameworks need it

###
Perform any operation on the structure while it is not in P1
###

framework = apply_symmetry_rules(framework)
# the framework is now in P1 and it can be used in simulations
```

## Generating Bond Information for Frameworks

The bonds are stored in a `SimpleGraph` from the `LightGraphs.jl` package, and
can be accessed through the `bonds` attribute.

### Reading from a file

`PorousMaterials` can read in bonds from `.cif` files if they have the tags
`_geom_bond_atom_site_label_1` and `_geom_bond_atom_site_label_2`. To choose to
read bonds from a file, pass `read_bonds_from_file=true` to the `Framework`
constructor.

```julia
using PorousMaterials

f = Framework("KAXQIL_clean.cif"; read_bonds_from_file=true, convert_to_p1=false)

f.bonds
```

This example uses a structure that is not in P1 symmetry. `PorousMaterials`
cannot replicate a structure or apply symmetry rules if it currently has bonds.
However, this structure can be converted to P1 without bonds, and then bonds can
be inferred for the full P1 structure.

### Inferring bonds using `BondingRule`s

`PorousMaterials` can infer bonds for a structure and populate the bond graph by
using `BondingRule`s. Each `BondingRule` has two species of atoms that it works
for. It also has a minimum and maximum distance that a bond can be defined for
the two atoms.

```julia
using PorousMaterials

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

# define an array of BondingRule's that will be used to define bonds in the
# framework. These need to be in the order that they are applied
bonding_rules = [BondingRule(:H, :*, 0.4, 1.2),
BondingRule(:*, :*, 0.4, 1.9)]

# Alternatively, you could get the above bonding rules with the following command
bonding_rules = default_bondingrules()

# infer the bonds for the framework f with bonds across periodic boundaries
infer_bonds!(f, true, bonding_rules)

# redefine bonding_rules to account for edge cases between Ca and O atoms. `pushfirst!` adds the newly
# defined Bondingrule to the front of `bonding_rules`
pushfirst!(BondingRule(:Ca, :O, 0.4, 2.5), bonding_rules)

# remove old bonds from framework before inferring bonds with new rules
remove_bonds!(f)

# re-infer bonds
infer_bonds!(f, true, bonding_rules)

# output the bond information to visualize it and double check
write_bond_information(f, "SBMOF-1_bonds.vtk")
```


## Building Blocks of PorousMaterials: Bravais lattice

We later apply periodic boundary conditions to mimic a crystal of infinite extent. A `Box` describes a [Bravais lattice](https://en.wikipedia.org/wiki/Bravais_lattice).
Expand Down Expand Up @@ -111,13 +196,22 @@ write_cube(grid, "CH4_in_SBMOF1.cube")
Framework
remove_overlapping_atoms_and_charges
strip_numbers_from_atom_labels!
wrap_atoms_to_unit_cell
chemical_formula
molecular_weight
crystal_density
replicate(::Framework, ::Tuple{Int, Int, Int})
charged(::Framework; ::Bool)
write_cif
assign_charges
apply_symmetry_rules
is_symmetry_equal
write_cif
BondingRule
write_bond_information
infer_bonds!
remove_bonds!
compare_bonds_in_framework
default_bondingrules
```

## Grids
Expand Down
2 changes: 2 additions & 0 deletions src/Box.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
box = Box(a, b, c, α, β, γ, volume, f_to_c, c_to_f, reciprocal_lattice)
box = Box(a, b, c, α, β, γ)
box = Box(a, b, c) # α=β=γ=π/2 assumed.
box = Box(f_to_c)
Data structure to describe a unit cell box (Bravais lattice) and convert between
Expand Down Expand Up @@ -114,6 +115,7 @@ This function generates a unit cube, each side is 1.0 Angstrom long, and all the
corners are right angles.
"""
UnitCube() = Box(1.0, 1.0, 1.0, π/2, π/2, π/2)
Box(a::Float64, b::Float64, c::Float64) = Box(a, b, c, π/2, π/2, π/2) # right angle box

"""
new_box = replicate(original_box, repfactors)
Expand Down
Loading

0 comments on commit 5fc9a85

Please sign in to comment.