Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add bonds to AbstractSystem #90

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/AtomsBase.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ include("flexible_system.jl")
include("atomview.jl")
include("atom.jl")
include("fast_system.jl")
include("bonded_system.jl")

function __init__()
@require AtomsView="ee286e10-dd2d-4ff2-afcb-0a3cd50c8041" begin
Expand Down
82 changes: 82 additions & 0 deletions src/bonded_system.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#
# Implementation of AtomsBase interface in a struct-of-arrays style with bonds.
#
export BondedSystem

struct BondedSystem{D, L <: Unitful.Length, M <: Unitful.Mass} <: AbstractSystem{D}
bounding_box::SVector{D, SVector{D, L}}
boundary_conditions::SVector{D, BoundaryCondition}
position::Vector{SVector{D, L}}
bonds::Vector{Tuple{Integer, Integer, BondOrder}}
atomic_symbol::Vector{Symbol}
atomic_number::Vector{Int}
atomic_mass::Vector{M}
end

# Constructor to fetch the types
function BondedSystem(box, boundary_conditions, positions, bonds, atomic_symbols, atomic_numbers, atomic_masses)
BondedSystem{length(box),eltype(eltype(positions)),eltype(atomic_masses)}(

Check warning on line 18 in src/bonded_system.jl

View check run for this annotation

Codecov / codecov/patch

src/bonded_system.jl#L17-L18

Added lines #L17 - L18 were not covered by tests
box, boundary_conditions, positions, bonds, atomic_symbols, atomic_numbers, atomic_masses
)
end

# Constructor to take data from another system
function BondedSystem(system::AbstractSystem)
BondedSystem(bounding_box(system), boundary_conditions(system), position(system), bonds(system),

Check warning on line 25 in src/bonded_system.jl

View check run for this annotation

Codecov / codecov/patch

src/bonded_system.jl#L24-L25

Added lines #L24 - L25 were not covered by tests
atomic_symbol(system), atomic_number(system), atomic_mass(system))
end

# Convenience constructor where we don't have to preconstruct all the static stuff...
function BondedSystem(particles, box, boundary_conditions, bonds)
D = length(box)
if !all(length.(box) .== D)
throw(ArgumentError("Box must have D vectors of length D=$D."))

Check warning on line 33 in src/bonded_system.jl

View check run for this annotation

Codecov / codecov/patch

src/bonded_system.jl#L30-L33

Added lines #L30 - L33 were not covered by tests
end
if length(boundary_conditions) != D
throw(ArgumentError("Boundary conditions should be of length D=$D."))

Check warning on line 36 in src/bonded_system.jl

View check run for this annotation

Codecov / codecov/patch

src/bonded_system.jl#L35-L36

Added lines #L35 - L36 were not covered by tests
end
if !all(n_dimensions.(particles) .== D)
throw(ArgumentError("Particles must have positions of length D=$D."))

Check warning on line 39 in src/bonded_system.jl

View check run for this annotation

Codecov / codecov/patch

src/bonded_system.jl#L38-L39

Added lines #L38 - L39 were not covered by tests
end
BondedSystem(box, boundary_conditions, position.(particles), bonds, atomic_symbol.(particles),

Check warning on line 41 in src/bonded_system.jl

View check run for this annotation

Codecov / codecov/patch

src/bonded_system.jl#L41

Added line #L41 was not covered by tests
atomic_number.(particles), atomic_mass.(particles))
end

bounding_box(sys::BondedSystem) = sys.bounding_box
boundary_conditions(sys::BondedSystem) = sys.boundary_conditions
bonds(sys::BondedSystem) = sys.bonds

Check warning on line 47 in src/bonded_system.jl

View check run for this annotation

Codecov / codecov/patch

src/bonded_system.jl#L45-L47

Added lines #L45 - L47 were not covered by tests

Base.length(sys::BondedSystem) = length(sys.position)
Base.size(sys::BondedSystem) = size(sys.position)

Check warning on line 50 in src/bonded_system.jl

View check run for this annotation

Codecov / codecov/patch

src/bonded_system.jl#L49-L50

Added lines #L49 - L50 were not covered by tests

species_type(::FS) where {FS <: BondedSystem} = AtomView{FS}
Base.getindex(sys::BondedSystem, i::Integer) = AtomView(sys, i)

Check warning on line 53 in src/bonded_system.jl

View check run for this annotation

Codecov / codecov/patch

src/bonded_system.jl#L52-L53

Added lines #L52 - L53 were not covered by tests

position(s::BondedSystem) = s.position
atomic_symbol(s::BondedSystem) = s.atomic_symbol
atomic_number(s::BondedSystem) = s.atomic_number
atomic_mass(s::BondedSystem) = s.atomic_mass
velocity(::BondedSystem) = missing

Check warning on line 59 in src/bonded_system.jl

View check run for this annotation

Codecov / codecov/patch

src/bonded_system.jl#L55-L59

Added lines #L55 - L59 were not covered by tests

# System property access
function Base.getindex(system::BondedSystem, x::Symbol)
if x === :bounding_box
bounding_box(system)
elseif x === :boundary_conditions
boundary_conditions(system)
elseif x === :bonds
bonds(system)

Check warning on line 68 in src/bonded_system.jl

View check run for this annotation

Codecov / codecov/patch

src/bonded_system.jl#L62-L68

Added lines #L62 - L68 were not covered by tests
else
throw(KeyError(x))

Check warning on line 70 in src/bonded_system.jl

View check run for this annotation

Codecov / codecov/patch

src/bonded_system.jl#L70

Added line #L70 was not covered by tests
end
end
Base.haskey(::BondedSystem, x::Symbol) = x in (:bounding_box, :boundary_conditions, :bonds)
Base.keys(::BondedSystem) = (:bounding_box, :boundary_conditions, :bonds)

Check warning on line 74 in src/bonded_system.jl

View check run for this annotation

Codecov / codecov/patch

src/bonded_system.jl#L73-L74

Added lines #L73 - L74 were not covered by tests

# Atom and atom property access
atomkeys(::BondedSystem) = (:position, :atomic_symbol, :atomic_number, :atomic_mass)
hasatomkey(system::BondedSystem, x::Symbol) = x in atomkeys(system)
function Base.getindex(system::BondedSystem, i::Union{Integer,AbstractVector}, x::Symbol)
getfield(system, x)[i]

Check warning on line 80 in src/bonded_system.jl

View check run for this annotation

Codecov / codecov/patch

src/bonded_system.jl#L77-L80

Added lines #L77 - L80 were not covered by tests
end
Base.getindex(system::BondedSystem, ::Colon, x::Symbol) = getfield(system, x)

Check warning on line 82 in src/bonded_system.jl

View check run for this annotation

Codecov / codecov/patch

src/bonded_system.jl#L82

Added line #L82 was not covered by tests
21 changes: 20 additions & 1 deletion src/interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import PeriodicTable

export AbstractSystem
export BoundaryCondition, DirichletZero, Periodic, infinite_box, isinfinite
export bounding_box, boundary_conditions, periodicity, n_dimensions, species_type

export bounding_box, boundary_conditions, periodicity, n_dimensions, species_type, bonds
export position, velocity, element, element_symbol, atomic_mass, atomic_number, atomic_symbol

export atomkeys, hasatomkey

#
Expand Down Expand Up @@ -51,6 +53,23 @@ Return the type used to represent a species or atom.
"""
function species_type end

"""
The possible bond orders that can be used in the `bonds` function
"""
@enum BondOrder begin
single
double
triple
Comment on lines +60 to +62
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should probably do this as

@enum BondOrder begin
    single = 1
    double = 2
    triple = 3
end

because it seems that if you don't do that, it actually assigns them numbers in a zero-indexed fashion (super weird), so the following can happen, which would be very confusing:

julia> BondOrder(2)
triple::BondOrder = 2

Separately, there might be a longer-term discussion about whether we should break out bonding types to be part of the interface since I could imagine people wanting more flexibility here, but my opinion is we start with this and file an issue for future conversations about this.

end

"""
bonds(::AbstractSystem)

Returns a Vector{Tuple{Integer, Integer, BondOrder}} where each entry stores the unique indices
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strictly, Integer should probably be typeof(firstindex(sys)) (in practice, I think all implementations do use integer indices right now, but this is more general)

i and j of the atoms participating in the bond and the order of the bond (e.g. [(13,21,5)])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the example at the end of this line is actually in line with what you want, since the third element should be a BondOrder enum...

"""
function bonds end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a default implementation that just returns an empty tuple? e.g. instead of this line, something like:

bonds(sys::AbstractSystem) = [()]

(I'm not sure if there's a type stability issue here with that return type not having the type parameters of the Tuple, though)


"""Return vector indicating whether the system is periodic along a dimension."""
periodicity(sys::AbstractSystem) = [isa(bc, Periodic) for bc in boundary_conditions(sys)]

Expand Down
Loading