diff --git a/src/implementation/atom.jl b/src/implementation/atom.jl index 533e550..548d895 100644 --- a/src/implementation/atom.jl +++ b/src/implementation/atom.jl @@ -12,13 +12,13 @@ struct Atom{D, L<:Unitful.Length, V<:Unitful.Velocity, M<:Unitful.Mass} position::SVector{D, L} velocity::SVector{D, V} species::ChemicalSpecies - atomic_mass::M + mass::M data::Dict{Symbol, Any} # Store arbitrary data about the atom. end velocity(atom::Atom) = atom.velocity position(atom::Atom) = atom.position -atomic_mass(atom::Atom) = atom.atomic_mass +mass(atom::Atom) = atom.mass species(atom::Atom) = atom.species n_dimensions(::Atom{D}) where {D} = D @@ -33,7 +33,7 @@ function Base.get(at::Atom, x::Symbol, default) hasfield(Atom, x) ? getfield(at, x) : get(at.data, x, default) end function Base.keys(at::Atom) - (:position, :velocity, :species, :atomic_mass, keys(at.data)...) + (:position, :velocity, :species, :mass, keys(at.data)...) end Base.pairs(at::Atom) = (k => at[k] for k in keys(at)) @@ -45,17 +45,17 @@ Base.pairs(at::Atom) = (k => at[k] for k in keys(at)) Construct an atomic located at the cartesian coordinates `position` with (optionally) the given cartesian `velocity`. Note that `AtomId = Union{Symbol,AbstractString,Integer}`. -Supported `kwargs` include `atomic_symbol`, `atomic_number`, `atomic_mass`, `charge`, +Supported `kwargs` include `atomic_symbol`, `atomic_number`, `mass`, `charge`, `multiplicity` as well as user-specific custom properties. """ function Atom(identifier::AtomId, position::AbstractVector{L}, velocity::AbstractVector{V}=zeros(length(position))u"bohr/s"; species = ChemicalSpecies(identifier), - atomic_mass::M=element(species).atomic_mass, + mass::M=element(species).atomic_mass, kwargs...) where {L <: Unitful.Length, V <: Unitful.Velocity, M <: Unitful.Mass} Atom{length(position), L, V, M}(position, velocity, species, - atomic_mass, Dict(kwargs...)) + mass, Dict(kwargs...)) end # TODO: what about the default unit? @@ -80,7 +80,7 @@ end Update constructor. Construct a new `Atom`, by amending the data contained in the passed `atom` object. -Supported `kwargs` include `atomic_symbol`, `atomic_number`, `atomic_mass`, `charge`, +Supported `kwargs` include `atomic_symbol`, `atomic_number`, `mass`, `charge`, `multiplicity` as well as user-specific custom properties. # Examples @@ -90,7 +90,7 @@ julia> hydrogen = Atom(:H, zeros(3)u"Å") ``` and now amend its charge and atomic mass ```julia-repl -julia> Atom(atom; atomic_mass=1.0u"u", charge=-1.0u"e_au") +julia> Atom(atom; mass=1.0u"u", charge=-1.0u"e_au") ``` """ Atom(atom::Atom; kwargs...) = Atom(; pairs(atom)..., kwargs...) diff --git a/src/implementation/fast_system.jl b/src/implementation/fast_system.jl index db335fe..20350cf 100644 --- a/src/implementation/fast_system.jl +++ b/src/implementation/fast_system.jl @@ -3,75 +3,88 @@ # export FastSystem -struct FastSystem{D, L <: Unitful.Length, M <: Unitful.Mass} <: AbstractSystem{D} - bounding_box::SVector{D, SVector{D, L}} - boundary_conditions::SVector{D, BoundaryCondition} +struct FastSystem{D, TCELL, L <: Unitful.Length, M <: Unitful.Mass, S} <: SystemWithCell{D} + cell::TCELL position::Vector{SVector{D, L}} - atomic_symbol::Vector{Symbol} - atomic_number::Vector{Int} - atomic_mass::Vector{M} + species::Vector{S} + mass::Vector{M} end # Constructor to fetch the types -function FastSystem(box, boundary_conditions, positions, atomic_symbols, atomic_numbers, atomic_masses) - FastSystem{length(box),eltype(eltype(positions)),eltype(atomic_masses)}( - box, boundary_conditions, positions, atomic_symbols, atomic_numbers, atomic_masses - ) +function FastSystem(box::NTuple{D, <: AbstractVector}, pbc::NTuple{D, Bool}, + positions, species, masses) where {D} + cell = PCell(box, pbc) + FastSystem(cell, positions, species, masses) +end + +function FastSystem(cell::TCELL, positions::AbstractVector{<: SVector{D, L}}, + species::AbstractVector{S}, masses) where {TCELL, D, L, S} + @assert D == n_dimensions(cell) + FastSystem{D, TCELL, L, typeof(masses), S}( + cell, positions, species, masses) end +get_cell(sys::FastSystem) = sys.cell + # Constructor to take data from another system function FastSystem(system::AbstractSystem) - FastSystem(bounding_box(system), boundary_conditions(system), position(system), - atomic_symbol(system), atomic_number(system), atomic_mass(system)) + FastSystem(get_cell(system), position(system, :), species(system, :), mass(system, :)) end # Convenience constructor where we don't have to preconstruct all the static stuff... -function FastSystem(particles, box, boundary_conditions) +function FastSystem(particles, box, pbc) D = length(box) if !all(length.(box) .== D) throw(ArgumentError("Box must have D vectors of length D=$D.")) end - if length(boundary_conditions) != D + if length(pbc) != D throw(ArgumentError("Boundary conditions should be of length D=$D.")) end if !all(n_dimensions.(particles) .== D) throw(ArgumentError("Particles must have positions of length D=$D.")) end - FastSystem(box, boundary_conditions, position.(particles), atomic_symbol.(particles), - atomic_number.(particles), atomic_mass.(particles)) + FastSystem(box, pbc, position.(particles), species.(particles), mass.(particles)) end -bounding_box(sys::FastSystem) = sys.bounding_box -boundary_conditions(sys::FastSystem) = sys.boundary_conditions Base.length(sys::FastSystem) = length(sys.position) Base.size(sys::FastSystem) = size(sys.position) -species_type(::FS) where {FS <: FastSystem} = AtomView{FS} -Base.getindex(sys::FastSystem, i::Integer) = AtomView(sys, i) +# TODO +# species_type(::FS) where {FS <: FastSystem} = AtomView{FS} -position(s::FastSystem) = s.position -atomic_symbol(s::FastSystem) = s.atomic_symbol -atomic_number(s::FastSystem) = s.atomic_number -atomic_mass(s::FastSystem) = s.atomic_mass -velocity(::FastSystem) = missing +Base.getindex(sys::FastSystem, i::Integer) = AtomView(sys, i) # System property access function Base.getindex(system::FastSystem, x::Symbol) if x === :bounding_box bounding_box(system) - elseif x === :boundary_conditions - boundary_conditions(system) + elseif x === :periodicity + periodicity(system) else throw(KeyError(x)) end end -Base.haskey(::FastSystem, x::Symbol) = x in (:bounding_box, :boundary_conditions) -Base.keys(::FastSystem) = (:bounding_box, :boundary_conditions) +Base.haskey(::FastSystem, x::Symbol) = x in (:bounding_box, :periodicity) +Base.keys(::FastSystem) = (:bounding_box, :periodicity) # Atom and atom property access -atomkeys(::FastSystem) = (:position, :atomic_symbol, :atomic_number, :atomic_mass) +atomkeys(::FastSystem) = (:position, :species, :mass) + hasatomkey(system::FastSystem, x::Symbol) = x in atomkeys(system) + function Base.getindex(system::FastSystem, i::Union{Integer,AbstractVector}, x::Symbol) getfield(system, x)[i] end + Base.getindex(system::FastSystem, ::Colon, x::Symbol) = getfield(system, x) + +position(s::FastSystem, ::Colon) = s.position +position(sys::FastSystem, i::Union{Integer, AbstractVector}) = sys.position[i] + +velocity(::FastSystem, args...) = missing + +mass(s::FastSystem, ::Colon) = s.mass +mass(sys::FastSystem, i::Union{Integer, AbstractVector}) = sys.mass[i] + +species(s::FastSystem, ::Colon) = s.species +species(sys::FastSystem, i::Union{Integer, AbstractVector}) = sys.species[i] diff --git a/src/implementation/flexible_system.jl b/src/implementation/flexible_system.jl index d780044..6726fb3 100644 --- a/src/implementation/flexible_system.jl +++ b/src/implementation/flexible_system.jl @@ -117,11 +117,11 @@ velocity(sys::FlexibleSystem, i::Integer) = velocity(sys::FlexibleSystem, i::Union{AbstractVector, Colon}) = [ velocity(x) for x in sys.particles[i] ] -atomic_mass(sys::FlexibleSystem, i::Integer) = - atomic_mass(sys.particles[i]) +mass(sys::FlexibleSystem, i::Integer) = + mass(sys.particles[i]) -atomic_mass(sys::FlexibleSystem, i::Union{AbstractVector, Colon}) = - [ atomic_mass(x) for x in sys.particles[i] ] +mass(sys::FlexibleSystem, i::Union{AbstractVector, Colon}) = + [ mass(x) for x in sys.particles[i] ] species(sys::FlexibleSystem, i::Integer) = species(sys.particles[i]) diff --git a/src/implementation/impl.jl b/src/implementation/impl.jl index 56ec4f2..491f618 100644 --- a/src/implementation/impl.jl +++ b/src/implementation/impl.jl @@ -8,13 +8,13 @@ import AtomsBase: AbstractSystem, SystemWithCell, n_dimensions, species, position, velocity, element, atomic_number, atomic_symbol, - atomic_mass, element, + mass, element, show_atom import AtomsBase: ChemicalSpecies, PCell, OpenSystemCell include("atom.jl") include("flexible_system.jl") -# include("fast_system.jl") +include("fast_system.jl") end \ No newline at end of file diff --git a/src/interface.jl b/src/interface.jl index d1fc2fc..72bbe39 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -13,6 +13,7 @@ export AbstractSystem, element, element_symbol, atomic_mass, + mass, atomic_number, atomic_symbol, atomkeys, diff --git a/src/utils/atomview.jl b/src/utils/atomview.jl index fd70f48..75bb879 100644 --- a/src/utils/atomview.jl +++ b/src/utils/atomview.jl @@ -17,7 +17,7 @@ using `AtomView` as its species type. julia> system = FastSystem(atoms, box, boundary_conditions); julia> atom = system[2] -AtomView(C, atomic_number = 6, atomic_mass = 12.011 u): +AtomView(C, atomic_number = 6, mass = 12.011 u): position : [0.75,0.75,0.75]u"Å" julia> atom isa AtomView{typeof(system)} diff --git a/src/utils/chemspecies.jl b/src/utils/chemspecies.jl index 9487a71..c54bec1 100644 --- a/src/utils/chemspecies.jl +++ b/src/utils/chemspecies.jl @@ -64,7 +64,7 @@ Base.convert(::Type{Symbol}, element::ChemicalSpecies) = Symbol(element) Base.Symbol(element::ChemicalSpecies) = _chem_el_info[element.atomic_number].symbol -atomic_mass(element::ChemicalSpecies) = _chem_el_info[element.atomic_number].atomic_mass +mass(element::ChemicalSpecies) = _chem_el_info[element.atomic_number].atomic_mass rich_info(element::ChemicalSpecies) = PeriodicTable.elements[element.atomic_number] diff --git a/src/utils/show.jl b/src/utils/show.jl index 669c4b1..96af537 100644 --- a/src/utils/show.jl +++ b/src/utils/show.jl @@ -89,8 +89,8 @@ end function show_atom(io::IO, ::MIME"text/plain", at) print(io, typeof(at).name.name, "(") - println(io, atomic_symbol(at), ", atomic_number = ", atomic_number(at), - ", atomic_mass = ", atomic_mass(at), "):") + println(io, atomic_symbol(at), ", Z = ", atomic_number(at), + ", m = ", mass(at), "):") pos = [(@sprintf "%.8g" ustrip(p)) for p in position(at)] posunit = unit(eltype(position(at))) @@ -101,7 +101,7 @@ function show_atom(io::IO, ::MIME"text/plain", at) @printf io " %-17s : [%s]u\"%s\"\n" "velocity" join(vel, ",") string(velunit) end for (k, v) in pairs(at) - k in (:atomic_number, :atomic_mass, :atomic_symbol, :position, :velocity) && continue + k in (:atomic_number, :mass, :atomic_symbol, :position, :velocity) && continue @printf io " %-17s : %s\n" string(k) string(v) end end diff --git a/test/atom.jl b/test/atom.jl index 2a236e8..bbfcde4 100644 --- a/test/atom.jl +++ b/test/atom.jl @@ -19,13 +19,13 @@ using AtomsBase.Implementation: Atom @test atomic_symbol(at) == :Si @test atomic_number(at) == 14 @test species(at) == ChemicalSpecies(:Si) - @test haskey(at, :atomic_mass) + @test haskey(at, :mass) @test haskey(at, :species) @test haskey(at, :extradata) @test at[:extradata] == 42 @test keys(at) == (:position, :velocity, :species, - :atomic_mass, :extradata) + :mass, :extradata) # Test update constructor newatom = Atom(at; extradata=43, atomic_number=15) diff --git a/test/fast_system.jl b/test/fast_system.jl index 6718652..20b2a2d 100644 --- a/test/fast_system.jl +++ b/test/fast_system.jl @@ -4,16 +4,18 @@ using Unitful using PeriodicTable using StaticArrays +using AtomsBase.Implementation: Atom, FastSystem + @testset "Fast system" begin - box = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]u"m" - bcs = [Periodic(), Periodic(), DirichletZero()] + box = ([1, 0, 0]u"m", [0, 1, 0]u"m", [0, 0, 1]u"m") + pbcs = (true, true, false) atoms = Atom[:C => [0.25, 0.25, 0.25]u"m", :C => [0.75, 0.75, 0.75]u"m"] system = FastSystem(atoms, box, bcs) @test length(system) == 2 @test size(system) == (2, ) - @test atomic_mass(system) == [12.011, 12.011]u"u" + @test mass(system) == [12.011, 12.011]u"u" @test boundary_conditions(system) == bcs @test bounding_box(system) == box @test system[:boundary_conditions] == bcs @@ -23,16 +25,16 @@ using StaticArrays @test keys(system) == (:bounding_box, :boundary_conditions) @test haskey(system, :boundary_conditions) @test system[:boundary_conditions][1] == Periodic() - @test atomkeys(system) == (:position, :atomic_symbol, :atomic_number, :atomic_mass) - @test keys(system[1]) == (:position, :atomic_symbol, :atomic_number, :atomic_mass) - @test hasatomkey(system, :atomic_symbol) + @test atomkeys(system) == (:position, :species, :mass) + @test keys(system[1]) == (:position, :species, :mass) + @test hasatomkey(system, :species) @test system[1] == AtomView(system, 1) @test system[1:2] == [system[1], system[2]] @test system[[2, 1]] == [system[2], system[1]] @test system[[1 2; 2 1]] == [system[1] system[2]; system[2] system[1]] @test system[:] == [system[1], system[2]] @test system[[false, true]] == [AtomView(system, 2)] - @test system[1, :atomic_number] == 6 + @test atomic_number(system, 1) == 6 @test system[1:2, :atomic_symbol] == [:C, :C] @test system[[1, 2], :atomic_symbol] == [:C, :C] @test system[:, :atomic_symbol] == [:C, :C] @@ -46,9 +48,8 @@ using StaticArrays @test collect(pairs(system)) == [(:bounding_box => box), (:boundary_conditions => bcs)] @test collect(pairs(system[1])) == [ :position => position(atoms[1]), - :atomic_symbol => :C, - :atomic_number => 6, - :atomic_mass => atomic_mass(atoms[1]), + :species => ChemicalSpecies(:C), + :mass => mass(atoms[1]), ] # check type stability @@ -58,7 +59,7 @@ using StaticArrays @test ismissing(@inferred(velocity(system, 2))) # Test AtomView - for method in (position, atomic_mass, atomic_symbol, atomic_number) + for method in (position, mass, species, atomic_number, atomic_symbol) @test method(system[1]) == method(system, 1) @test method(system[2]) == method(system, 2) end diff --git a/test/interface.jl b/test/interface.jl index 9f33fe0..3b5b262 100644 --- a/test/interface.jl +++ b/test/interface.jl @@ -4,7 +4,7 @@ using Unitful using UnitfulAtomic using PeriodicTable -using AtomsBase.Implementation: Atom, FlexibleSystem +using AtomsBase.Implementation: Atom, FlexibleSystem, FastSystem @testset "Interface" begin box = ([1, 0, 0]u"m", [0, 1, 0]u"m", [0, 0, 1]u"m") @@ -18,15 +18,14 @@ using AtomsBase.Implementation: Atom, FlexibleSystem @test velocity(atoms[1]) == [0.0, 0.0, 0.0]u"bohr/s" @test atomic_symbol(atoms[1]) == :C @test atomic_number(atoms[1]) == 6 - @test atomic_mass(atoms[1]) == 12.011u"u" + @test mass(atoms[1]) == 12.011u"u" @test element(atoms[1]) == element(:C) - @test keys(atoms[1]) == (:position, :velocity, :species, :atomic_mass) + @test keys(atoms[1]) == (:position, :velocity, :species, :mass) @test get(atoms[1], :blubber, :adidi) == :adidi end @testset "System" begin flexible = FlexibleSystem(atoms, box, pbcs) - # TODO # fast = FastSystem(flexible) @test length(flexible) == 2 @test size(flexible) == (2, ) @@ -38,8 +37,8 @@ using AtomsBase.Implementation: Atom, FlexibleSystem @test position(flexible, 1) == [0.25, 0.25, 0.25]u"m" @test velocity(flexible, :)[1] == [0.0, 0.0, 0.0]u"bohr/s" @test velocity(flexible, 2) == [0.0, 0.0, 0.0]u"bohr/s" - @test atomic_mass(flexible, :) == [12.011, 12.011]u"u" - @test atomic_mass(flexible, 1) == 12.011u"u" + @test mass(flexible, :) == [12.011, 12.011]u"u" + @test mass(flexible, 1) == 12.011u"u" @test atomic_number(flexible, :) == [6, 6] # TODO fast # @test atomic_number(fast, 1) == 6 @@ -47,7 +46,7 @@ using AtomsBase.Implementation: Atom, FlexibleSystem @test atomic_symbol(flexible, 2) == :C @test atomic_number(flexible, 2) == 6 - @test atomkeys(flexible) == (:position, :velocity, :species, :atomic_mass) + @test atomkeys(flexible) == (:position, :velocity, :species, :mass) @test hasatomkey(flexible, :species) @test atomic_symbol(flexible, 1) == :C @test atomic_symbol(flexible, :,) == [:C, :C] diff --git a/test/runtests.jl b/test/runtests.jl index 9fde3ac..e18e02e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -8,7 +8,7 @@ if GROUP == "Core" @testset "AtomsBase.jl" begin include("interface.jl") include("atom.jl") - # include("fast_system.jl") + include("fast_system.jl") # include("properties.jl") # include("printing.jl") end