Skip to content

Commit

Permalink
More detailed printing
Browse files Browse the repository at this point in the history
  • Loading branch information
mfherbst committed Dec 16, 2022
1 parent e161fb7 commit 0331a85
Show file tree
Hide file tree
Showing 13 changed files with 150 additions and 49 deletions.
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ version = "0.2.3"

[deps]
PeriodicTable = "7b2266bf-644c-5ea3-82d8-af4bbd25a884"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
UnitfulAtomic = "a7773ee8-282e-5fa2-be4e-bd808c38a91a"
Expand Down
4 changes: 3 additions & 1 deletion src/AtomsBase.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
module AtomsBase
using Unitful
using UnitfulAtomic
import PeriodicTable: elements
using Printf
using StaticArrays

include("interface.jl")
include("element.jl")
include("properties.jl")
include("show.jl")
include("flexible_system.jl")
include("atom.jl")
include("atomview.jl")
Expand Down
19 changes: 7 additions & 12 deletions src/atom.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
#
export Atom, atomic_system, periodic_system, isolated_system

# Valid types for atom identifiers
const AtomId = Union{Symbol,AbstractString,Integer}

struct Atom{D, L<:Unitful.Length, V<:Unitful.Velocity, M<:Unitful.Mass}
position::SVector{D, L}
velocity::SVector{D, V}
Expand All @@ -19,8 +16,7 @@ position(atom::Atom) = atom.position
atomic_mass(atom::Atom) = atom.atomic_mass
atomic_symbol(atom::Atom) = atom.atomic_symbol
atomic_number(atom::Atom) = atom.atomic_number
element(atom::Atom) = elements[atomic_symbol(atom)]
n_dimensions(atom::Atom{D}) where {D} = D
n_dimensions(::Atom{D}) where {D} = D

Base.hasproperty(at::Atom, x::Symbol) = hasfield(Atom, x) || haskey(at.data, x)
Base.getproperty(at::Atom, x::Symbol) = hasfield(Atom, x) ? getfield(at, x) : getindex(at.data, x)
Expand All @@ -35,9 +31,9 @@ end
function Atom(identifier::AtomId,
position::AbstractVector{L},
velocity::AbstractVector{V}=zeros(length(position))u"bohr/s";
atomic_symbol=Symbol(elements[identifier].symbol),
atomic_number=elements[identifier].number,
atomic_mass::M=elements[identifier].atomic_mass,
atomic_symbol=Symbol(element(identifier).symbol),
atomic_number=element(identifier).number,
atomic_mass::M=element(identifier).atomic_mass,
kwargs...) where {L <: Unitful.Length, V <: Unitful.Velocity, M <: Unitful.Mass}
Atom{length(position), L, V, M}(position, velocity, atomic_symbol,
atomic_number, atomic_mass, Dict(kwargs...))
Expand All @@ -58,10 +54,9 @@ function Base.convert(::Type{Atom}, id_pos::Pair{<:AtomId,<:AbstractVector{<:Uni
Atom(id_pos...)
end

function Base.show(io::IO, at::Atom{D, L}) where {D, L}
pos = ustrip.(at.position)
print(io, "Atom($(at.atomic_symbol), [", join(pos, ", "), "]u\"$(unit(L))\")")
end
Base.show(io::IO, at::Atom) = show_atom(io, at)
Base.show(io::IO, mime::MIME"text/plain", at::Atom) = show_atom(io, mime, at)


#
# Special high-level functions to construct atomic systems
Expand Down
4 changes: 3 additions & 1 deletion src/atomview.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ position(v::AtomView) = position(v.system, v.index)
atomic_mass(v::AtomView) = atomic_mass(v.system, v.index)
atomic_symbol(v::AtomView) = atomic_symbol(v.system, v.index)
atomic_number(v::AtomView) = atomic_number(v.system, v.index)
element(v::AtomView) = elements[atomic_symbol(v)]
n_dimensions(v::AtomView) = n_dimensions(v.system)

Base.show(io::IO, at::AtomView) = show_atom(io, at)
Base.show(io::IO, mime::MIME"text/plain", at::AtomView) = show_atom(io, mime, at)
7 changes: 7 additions & 0 deletions src/element.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import PeriodicTable

# Valid types for atom identifiers
const AtomId = Union{Symbol,AbstractString,Integer}

# Lookup element in PeriodicTable
element(id::AtomId) = PeriodicTable.elements[id]
5 changes: 0 additions & 5 deletions src/fast_system.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,6 @@ function FastSystem(particles, box, boundary_conditions)
atomic_number.(particles), atomic_mass.(particles))
end

function Base.show(io::IO, system::FastSystem)
print(io, "FastSystem")
show_system(io, system)
end

bounding_box(sys::FastSystem) = sys.box
boundary_conditions(sys::FastSystem) = sys.boundary_conditions
Base.length(sys::FastSystem) = length(sys.positions)
Expand Down
5 changes: 0 additions & 5 deletions src/flexible_system.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ function FlexibleSystem(system::AbstractSystem;
end
FlexibleSystem(;system::FlexibleSystem, kwargs...) = FlexibleSystem(system; kwargs...)

function Base.show(io::IO, system::FlexibleSystem)
print(io, "FlexibleSystem")
show_system(io, system)
end

bounding_box(sys::FlexibleSystem) = sys.box
boundary_conditions(sys::FlexibleSystem) = sys.boundary_conditions
species_type(sys::FlexibleSystem{D, S, L}) where {D, S, L} = S
Expand Down
16 changes: 15 additions & 1 deletion src/interface.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Base.position

export AbstractSystem
export BoundaryCondition, DirichletZero, Periodic, infinite_box
export BoundaryCondition, DirichletZero, Periodic, infinite_box, isinfinite
export bounding_box, boundary_conditions, periodicity, n_dimensions, species_type
export position, velocity, element, atomic_mass, atomic_number, atomic_symbol

Expand Down Expand Up @@ -52,6 +52,10 @@ function species_type end
"""Return vector indicating whether the system is periodic along a dimension."""
periodicity(sys::AbstractSystem) = [isa(bc, Periodic) for bc in boundary_conditions(sys)]

"""Returns true if the given system is infinite"""
isinfinite(sys::AbstractSystem{D}) where {D} = bounding_box(sys) == infinite_box(D)


"""
n_dimensions(::AbstractSystem)
n_dimensions(atom)
Expand Down Expand Up @@ -126,6 +130,11 @@ atomic_mass(sys::AbstractSystem, index) = atomic_mass(sys[index])
Vector of atomic symbols in the system `sys` or the atomic symbol of a particular `species` /
the `i`th species in `sys`.
The intention is that [`atomic_number`](@ref) carries the meaning
of identifying the type of a `species` (e.g. the element for the case of an atom), whereas
[`atomic_symbol`](@ref) may return a more unique identifier. For example for a deuterium atom
this may be `:D` while `atomic_number` is still `1`.
"""
atomic_symbol(sys::AbstractSystem) = atomic_symbol.(sys)
atomic_symbol(sys::AbstractSystem, index) = atomic_symbol(sys[index])
Expand All @@ -138,6 +147,11 @@ atomic_symbol(sys::AbstractSystem, index) = atomic_symbol(sys[index])
Vector of atomic numbers in the system `sys` or the atomic number of a particular `species` /
the `i`th species in `sys`.
The intention is that [`atomic_number`](@ref) carries the meaning
of identifying the type of a `species` (e.g. the element for the case of an atom), whereas
[`atomic_symbol`](@ref) may return a more unique identifier. For example for a deuterium atom
this may be `:D` while `atomic_number` is still `1`.
"""
atomic_number(sys::AbstractSystem) = atomic_number.(sys)
atomic_number(sys::AbstractSystem, index) = atomic_number(sys[index])
18 changes: 0 additions & 18 deletions src/properties.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export chemical_formula


"""
Returns the chemical formula of an AbstractSystem as a string.
"""
Expand All @@ -18,20 +17,3 @@ function chemical_formula(symbols::AbstractVector{Symbol})
join(sort(parts))
end
chemical_formula(system) = chemical_formula(atomic_symbol(system))


function show_system(io::IO, system::AbstractSystem{D}) where {D}
print(io, "($(chemical_formula(system)), ")
bc = boundary_conditions(system)
if all(isequal(bc[1]), bc)
print(io, typeof(bc[1]), ", ")
end
box = bounding_box(system)
if box != infinite_box(D)
box_str = ["[" * join(ustrip.(bvector), ", ") * "]" for bvector in box]
print(io, "box=[", join(box_str, ", "), "]u\"$(unit(box[1][1]))\"")
else
print(io, "box=infinite")
end
print(io, ")")
end
104 changes: 104 additions & 0 deletions src/show.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@

"""
Suggested function to print AbstractSystem objects to screen
"""
function show_system(io::IO, system::AbstractSystem{D}) where {D}
bc = boundary_conditions(system)

print(io, typeof(system).name.name, "($(chemical_formula(system))")
if isinfinite(system)
print(io, ", infinite")
else
perstr = [p ? "T" : "F" for p in periodicity(system)]
print(io, ", periodic = ", join(perstr, ""))
end

if !isinfinite(system)
box_str = ["[" * join(ustrip.(bvector), ", ") * "]"
for bvector in bounding_box(system)]
bunit = unit(eltype(first(bounding_box(system))))
print(io, ", bounding_box = [", join(box_str, ", "), "]u\"$bunit\"")
end
print(io, ")")
end
function show_system(io::IO, ::MIME"text/plain", system::AbstractSystem{D}) where {D}
bc = boundary_conditions(system)
box = bounding_box(system)
print(io, typeof(system).name.name, "($(chemical_formula(system))")
if isinfinite(system)
print(io, ", infinite")
else
perstr = [p ? "T" : "F" for p in periodicity(system)]
print(io, ", periodic = ", join(perstr, ""))
end
println(io, "):")

extra_line = false
if !isinfinite(system)
extra_line = true
box = bounding_box(system)
bunit = unit(eltype(first(bounding_box(system))))
for (i, bvector) in enumerate(box)
if i == 1
@printf io " %-17s : [" "bounding_box"
else
print(io, " "^25)
end
boxstr = [(@sprintf "%8.6g" ustrip(b)) for b in bvector]
print(io, join(boxstr, " "))
println(io, i == D ? "]u\"$bunit\"" : ";")
end
end

if system isa FlexibleSystem
for (k, v) in pairs(system.data)
extra_line = true
@printf io " %-17s : %s\n" string(k) string(v)
end
end

# TODO Better would be some ascii-graphical representation of the structure
if length(system) < 20
extra_line && println(io)
for atom in system
println(io, " ", atom)
end
end
end

Base.show(io::IO, system::AbstractSystem) = show_system(io, system)
function Base.show(io::IO, mime::MIME"text/plain", system::AbstractSystem)
show_system(io, mime, system)
end

function show_atom(io::IO, at)
pos = [(@sprintf "%8.6g" ustrip(p)) for p in position(at)]
posunit = unit(eltype(position(at)))
print(io, "Atom($(atomic_symbol(at)), [", join(pos, ", "), "]u\"$posunit\"")
if ismissing(velocity(at)) || iszero(velocity(at))
print(io, ")")
else
vel = [(@sprintf "%8.6g" ustrip(p)) for p in velocity(at)]
velunit = unit(eltype(velocity(at)))
print(io, ", [", join(vel, ", "), "]u\"$velunit\")")
end
end

function show_atom(io::IO, ::MIME"text/plain", at)
println(io, "Atom(", atomic_symbol(at), ", atomic_number = ", atomic_number(at),
", atomic_mass = ", atomic_mass(at), "):")

pos = [(@sprintf "%.8g" ustrip(p)) for p in position(at)]
posunit = unit(eltype(position(at)))
@printf io " %-17s : [%s]u\"%s\"\n" "position" join(pos, ",") string(posunit)
if !ismissing(velocity(at)) && !iszero(velocity(at))
vel = [(@sprintf "%.8g" ustrip(p)) for p in velocity(at)]
velunit = unit(eltype(velocity(at)))
@printf io " %-17s : [%s]u\"%s\"\n" "velocity" join(vel, ",") string(velunit)
end
if at isa Atom
for (k, v) in pairs(at.data)
@printf io " %-17s : %s\n" string(k) string(v)
end
end
end
2 changes: 1 addition & 1 deletion test/fast_system.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ using PeriodicTable
@test atomic_mass(system) == [12.011, 12.011]u"u"
@test boundary_conditions(system) == bcs
@test bounding_box(system) == box
@test !isinfinite(system)


# Test AtomView
Expand All @@ -24,5 +25,4 @@ using PeriodicTable
end
@test ismissing(velocity(system[1]))
@test n_dimensions(system[1]) == n_dimensions(system)
@test element(system[1]) == elements[:C]
end
2 changes: 1 addition & 1 deletion test/interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ using PeriodicTable
@testset "Atoms" begin
@test position(atoms[1]) == [0.25, 0.25, 0.25]u"m"
@test velocity(atoms[1]) == [0.0, 0.0, 0.0]u"bohr/s"
@test element(atoms[1]) == PeriodicTable.elements[:C]
@test atomic_symbol(atoms[1]) == :C
@test atomic_number(atoms[1]) == 6
@test atomic_mass(atoms[1]) == 12.011u"u"
Expand All @@ -29,6 +28,7 @@ using PeriodicTable
@test bounding_box(flexible) == [[1, 0, 0], [0, 1, 0], [0, 0, 1]]u"m"
@test boundary_conditions(flexible) == [Periodic(), Periodic(), DirichletZero()]
@test periodicity(flexible) == [1, 1, 0]
@test !isinfinite(flexible)
@test n_dimensions(flexible) == 3
@test position(flexible) == [[0.25, 0.25, 0.25], [0.75, 0.75, 0.75]]u"m"
@test position(flexible, 1) == [0.25, 0.25, 0.25]u"m"
Expand Down
12 changes: 8 additions & 4 deletions test/printing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@ using Test

@testset "Printing atomic systems" begin
at = Atom(:Si, zeros(3) * u"m", extradata=42)
@test repr(at) == "Atom(Si, [0.0, 0.0, 0.0]u\"m\")"

@test repr(at) == "Atom(Si, [ 0, 0, 0]u\"m\")"
show(stdout, MIME("text/plain"), at)

atoms = [:Si => [0.0, -0.125, 0.0],
:C => [0.125, 0.0, 0.0]]
box = [[10, 0.0, 0.0], [0.0, 5, 0.0], [0.0, 0.0, 7]]u"Å"

flexible_system = periodic_system(atoms, box; fractional=true)
@test repr(flexible_system) == """
FlexibleSystem(CSi, Periodic, box=[[10.0, 0.0, 0.0], [0.0, 5.0, 0.0], [0.0, 0.0, 7.0]]u"Å")"""
FlexibleSystem(CSi, periodic = TTT, bounding_box = [[10.0, 0.0, 0.0], [0.0, 5.0, 0.0], [0.0, 0.0, 7.0]]u"Å")"""
show(stdout, MIME("text/plain"), flexible_system)

fast_system = FastSystem(flexible_system)
@test repr(fast_system) == """
FastSystem(CSi, Periodic, box=[[10.0, 0.0, 0.0], [0.0, 5.0, 0.0], [0.0, 0.0, 7.0]]u"Å")"""
FastSystem(CSi, periodic = TTT, bounding_box = [[10.0, 0.0, 0.0], [0.0, 5.0, 0.0], [0.0, 0.0, 7.0]]u"Å")"""
show(stdout, MIME("text/plain"), fast_system)
show(stdout, MIME("text/plain"), fast_system[1])
end

0 comments on commit 0331a85

Please sign in to comment.