Skip to content

Commit

Permalink
Interface and Docs Updates for v0.4.x (#107)
Browse files Browse the repository at this point in the history
Co-authored-by: Christoph Ortner <[email protected]>
Co-authored-by: Michael F. Herbst <[email protected]>
  • Loading branch information
3 people committed Aug 27, 2024
1 parent de3eebb commit 202ff91
Show file tree
Hide file tree
Showing 36 changed files with 1,445 additions and 831 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ jobs:
matrix:
version:
- '1.6'
- '1.9'
- '1.10'
- 'nightly'
group:
- Core
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ Manifest.toml
*.swp
*.swo
*~
.vscode
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "AtomsBase"
uuid = "a963bdd2-2df7-4f54-a1ee-49d51e6be12a"
authors = ["JuliaMolSim community"]
version = "0.3.5"
version = "0.4"

[deps]
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Expand Down
27 changes: 13 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,40 @@

AtomsBase is an abstract interface for representation of atomic geometries in
Julia. It aims to be a lightweight means of facilitating interoperability
between various tools including ...
between various tools including, e.g.,

* Chemical simulation engines:
- [DFTK.jl](https://github.com/JuliaMolSim/DFTK.jl) (density-functional theory)
- [Molly.jl](https://github.com/JuliaMolSim/Molly.jl) (molecular dynamics)
* Integration with third party-libraries:
- [ASEconvert.jl](https://github.com/mfherbst/ASEconvert.jl) (integration with the Atomistic Simulation Environment)
* Simulation engines, e.g. molecular dynamics, geometry optimization, etc
* Computing chemical or mechanical properties, e.g., via DFT, or interatomic potentials,
* Integration with third party-libraries
* I/O with standard file formats (.cif, .xyz, ...)
- E.g. [AtomIO.jl](https://github.com/mfherbst/AtomIO.jl)
* automatic differentiation and machine learning systems
- [ChemistryFeaturization.jl](https://github.com/Chemellia/ChemistryFeaturization.jl)
(featurization of atomic systems)
* numerical tools: sampling, integration schemes, etc.
* visualization (e.g. plot recipes)

While AtomsBase focusses on representation of atomic systems, the sister package [`AtomsCalculators`](https://github.com/JuliaMolSim/AtomsCalculators.jl) provides a general interface to compute properties of such systems.

Currently, the design philosophy is to be as lightweight as possible with a small set
of required function dispatches to make adopting the interface easy.
We also provide a couple of
[standard flexible implementations of the interface](https://juliamolsim.github.io/AtomsBase.jl/stable/atomicsystems/#atomic-systems)
We also provide
[prototype implementations](https://juliamolsim.github.io/AtomsBase.jl/stable/atomicsystems/#atomic-systems)
that we envision to be broadly applicable.
If features beyond these are required we
encourage developers to open PRs or provide their own implementations.
If features beyond these are required we encourage developers to open PRs or provide their own implementations.
For more on how to use the package,
see [the documentation](https://juliamolsim.github.io/AtomsBase.jl/stable).

## Packages using AtomsBase

The following (not all yet-registered) packages currently make use of AtomsBase:
* [ACEpotentials](https://github.com/ACEsuit/ACEpotentials.jl)
* [ASEPotential](https://github.com/jrdegreeff/ASEPotential.jl)
* [ASEconvert](https://github.com/mfherbst/ASEconvert.jl)
* [ASEconvert](https://github.com/mfherbst/ASEconvert.jl) : integration with the Atomistic Simulation Environment
* [AtomIO](https://github.com/mfherbst/AtomIO.jl): I/O for atomic structures, also wraps some ASE functionality
* [Atomistic](https://github.com/cesmix-mit/Atomistic.jl/tree/263ec97b5f380f1b2ba593bf8feaf36e7f7cff9a): integrated workflow for MD simulations, part of [CESMIX](https://computing.mit.edu/cesmix/)
* [AutoBZCore.jl](https://github.com/lxvm/AutoBZCore.jl/): Brillouin-zone integration
* [BFPIS](https://github.com/GDufenshuoo/BFPIS.jl)
* [ChemistryFeaturization](https://github.com/Chemellia/ChemistryFeaturization.jl): Interface for featurization of atomic structures for input into machine learning models, part of [Chemellia](https://chemellia.org)
* [DFTK](https://github.com/JuliaMolSim/DFTK.jl): density functional theory simulations
* [EmpiricalPotentials](https://github.com/JuliaMolSim/EmpiricalPotentials.jl)
* [ExtXYZ](https://github.com/libAtoms/ExtXYZ.jl): Parser for extended XYZ files
* [InteratomicPotentials](https://github.com/cesmix-mit/InteratomicPotentials.jl): implementations of a variety of interatomic potentials, also part of [CESMIX](https://computing.mit.edu/cesmix/)
* [Molly](https://github.com/JuliaMolSim/Molly.jl): molecular dynamics simulations
Expand Down
9 changes: 5 additions & 4 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ makedocs(;
),
pages=[
"Home" => "index.md",
"tutorial.md",
"overview.md",
"testing.md",
"apireference.md"
"Interface" => "interface.md",
"Utilities" => "utilities.md",
"Implementations" => "implementations.md",
"Tutorial" => "tutorial.md",
"Reference" => "apireference.md"
],
checkdocs=:exports,
)
Expand Down
45 changes: 31 additions & 14 deletions docs/src/apireference.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,40 +10,57 @@ CurrentModule = AtomsBase
Pages = ["apireference.md"]
```

## Types

```@docs
AbstractSystem
IsolatedCell
PeriodicCell
AtomView
ChemicalSpecies
```

## System properties

```@docs
boundary_conditions
bounding_box
chemical_formula
element_symbol
isinfinite
n_dimensions
set_bounding_box!
periodicity
species_type
set_periodicity!
cell
set_cell!
n_dimensions
atomkeys
hasatomkey
chemical_formula
visualize_ascii
```

## Species / atom properties

```@docs
atomic_mass
position
set_position!
mass
set_mass!
species
set_species!
velocity
set_velocity!
atomic_number
atomic_symbol
velocity
position
element
element_symbol
element
```

## Atom and system constructors

## Prototype Implementation

```@docs
Atom
AtomView
FlexibleSystem
AbstractSystem
FastSystem
atomic_system
isolated_system
periodic_system
periodic_system
```
43 changes: 43 additions & 0 deletions docs/src/implementations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
```@meta
CurrentModule = AtomsBase
```

# Prototype Implementations

`AtomsBase` provides two prototype implementations of `AbstractSystem{D}` that are exported:
- [`FlexibleSystem`](@ref)
- [`FastSystem`](@ref)
and are briefly discussed in more detail in the remainder of this page.

## Struct-of-Arrays vs. Array-of-Structs

The "struct-of-arrays" (SoA) vs. "array-of-structs" (AoS) is a common design
dilemma in representations of systems of particles. AtomsBase is deliberately
designed to be _agnostic_ to how a concrete implementation
chooses to structure its data. Some specific notes regarding how
implementations might differ for these two paradigms are included below.

A way to think about this broadly is that the difference amounts to the
ordering of function calls. For example, to get the position of a single
particle in an AoS implementation, the explicit function chaining would be
`position(getindex(sys))` (i.e. extract the single struct representing the
particle of interest and query its position), while for SoA, one should prefer
an implementation like `getindex(position(sys))` (extract the array of
positions, then index into it for a single particle). The beauty of an abstract
interface in Julia is that these details can be, in large part, abstracted away
through method dispatch such that the end user sees the same expected behavior
irrespective of how things are implemented "under the hood".

### Struct of Arrays / FastSystem

The file [`fast_system.jl`](https://github.com/JuliaMolSim/AtomsBase.jl/blob/master/src/implementation/fast_system.jl) contains an implementation of
AtomsBase based on the struct-of-arrays approach. All species data is stored
as plain arrays, but for convenience indexing of individual atoms is supported
by a light-weight [`AtomView`](@ref). See the implementation files
as well as the tests for how these can be used.

### Atoms and FlexibleSystem

A flexible implementation of the interface is provided by the
[`FlexibleSystem`](@ref) and the [`Atom`](@ref) structs
for representing atomic systems.These are discussed in detail in the tutorial.
137 changes: 137 additions & 0 deletions docs/src/interface.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
```@meta
CurrentModule = AtomsBase
```

# Interface

This page formally defines the `AtomsBase` interface for particle systems.
The main use-case for which the interface is designed is for systems of atoms. For this case some additional functionality is provided.
The main abstract type introduced in AtomsBase is
- [`AbstractSystem`](@ref).

An implementation of `AbstractSystem{D}`,
```julia
struct ConcreteSystem{D} <: AbstractSystem{D}
# ...
end
```
specifies a system of particles that have a position in `D` dimensional Euclidean space. That is, the parameter `D` indicates the number of spatial dimensions into which each particle is embedded.
A particle will normally also have additional properties such as mass, charge, chemical species, etc, but those are ignored in the interpretation of `D`.

The interface aims to achieve predictable behavior of several core functions to access information about a particle system.
- [Core Interface](@ref) : this is a minimal read-only core of the AtomsBase interface and must be implemented by a subtype of `AtomsBase.AbstractSystem` to enable the implementation to be used across the AtomsBase ecosystem.
- [Setter Interface](@ref) : (optional) It is strongly recommended that implementations requiring mutation follow this interface.
- [Optional properties interface](@ref) : (optional) For some use-cases (e.g. managing datasets) it can be useful to allow a system to store more general properties about a particle system (or the individual particles themselves). The *optional properties interface* specifies the recommended interface for such as scenario.



## Core Interface

A minimal implementation of the `AtomsBase` interface is read-only and must implement methods for the functions listed as follows.

- `Base.length(system)`
- `Base.getindex(system, i)`
- [`AtomsBase.cell(system)](@ref)
- [`AtomsBase.position(system, i)`](@ref)
- [`AtomsBase.mass(system, i)`](@ref)
- [`AtomsBase.species(system, i)`](@ref)


### System Properties and Cell Interface

A system is specified by a computational cell and particles within that cell (or, domain). System properties are properties of the entire particle system, as opposed to properties of individual particles.

- `Base.length(system)` : return an `Integer`, the number of particles in the system; if the system describes a periodic cell, then the number of particles in one period of the cell is returned.
- [`AtomsBase.cell(system)](@ref) : returns an object `cell` that specifies the computational cell. Two reference implementations, [`PeriodicCell`](@ref) and [`IsolatedCell`](@ref) that should serve most purposes are provided.

A cell object must implement methods for the following functions:
- [`AtomsBase.bounding_box(cell)`](@ref) : returns `NTuple{D, SVector{D, T}}` the cell vectors that specify the computational domain if it is finite. For isolated systems, the return values are unspecified.
- [`AtomsBase.periodicity(cell)`](@ref) : returns `NTuple{D, Bool}`, booleans that specify whether the system is periodic in the direction of the `D` cell vectors provided by `bounding_box`. For isolated systems `periodicity` must return `(false, ..., false)`.
- [`AtomsBase.n_dimensions(cell)`](@ref) : returns the dimensionality of the computational cell, it must match the dimensionality of the system.


AtomsBase provides `bounding_box` and `periodicity` methods so that they can be called with a system as argument, i.e.,
```julia
bounding_box(system) = bounding_box(cell(system))
periodicity(system) = periodicity(cell(system))
```

Two recommended general purpose implementations of computational cells are provided as part of `AtomsBase`:
- [`PeriodicCell`](@ref) : implementation of a periodic parallelepiped shaped cell
- [`IsolatedCell`](@ref) : implementation of a cell describing an isolated system within an infinite domain.


### Particle properties

- [`position(system, i::Integer)`](@ref) : return an `SVector{D, <: Unitful.Length}` enconding the position of the ith particle
- [`mass(system, i::Integer)`](@ref) : return a `<: Unitful.Mass`, the mass of the ith particle
- [`species(system, i::Integer)`](@ref) : return an object that defines the particle species (kind, type, ...). In most cases this should be a categorical variable on which no arithmetic is defined. In atomistic simulation this is normally the chemical element (cf. [`AtomsBase.ChemicalSpecies`](@ref)), possibly augmented with additional information about the atom. But the interface does not require use of any specific type to define the particle species.

For each of `property in [position, mass, species]` there must also be defined
- `property(system, inds::AbstractVector{<: Integer})` : return a list (e.g. `AbstractVector`) of the requested property of the particles indexed by `inds`;
- `property(system, :)` : return a list of the requested property for all particles in the system.
AtomsBase provides default fallbacks for these methods but they will normally be inefficient. The caller cannot assume whether a view or a copy are returned.

### Iteration and Indexing over systems

There is a presumption of the ability to somehow extract an individual
component (e.g. a single atom or molecule) of this system, though there are no
constraints on the type of this component. To achieve this, an [`AbstractSystem`](@ref)
object is expected to implement the Julia interfaces for
[iteration](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-iteration)
and [indexing](https://docs.julialang.org/en/v1/manual/interfaces/#Indexing) in
order to access representations of individual components of the system. Some
default dispatches of parts of these interfaces are already included, so the
minimal set of functions to dispatch in a concrete implementation is
`Base.getindex` and `Base.length`, though it may be desirable to customize
additional behavior depending on context.


## Setter Interface

The optional setter / mutation interface consists of the following functions to be overloaded.

- [`set_cell!(system, cell)`](@ref)
- [`set_position!(system, i, x)`](@ref)
- [`set_mass!(system, i, x)`](@ref)
- [`set_species!(system, i, x)`](@ref)
- [`set_bounding_box!(cell, bb)`](@ref)
- [`set_periodicity!(cell, pbc)`](@ref)
- `deleteat!(system, i)` : delete atoms `i` (or atoms `i` if a list of `":`)
- `append!(system1, system2)` : append system 2 to system 1, provided they are "compatible".

For each of the particle property setters, `i` may be an `Integer`, an `AbstractVector{<: Integer}` or `:`.


## Optional properties interface

For some use-cases (e.g. managing datasets) it can be useful to allow a system to store more general properties about a particle system or even the individual particles themselves. The *optional properties interface* specifies the recommended interface for such as scenario. The [Tutorial](@ref) provides a more detailed discussion and exmaples how these can be used. The prototype implementations also provide further details.

An implementation that wants to support the AtomsBase optional properties interface should implement the following methods:

System properties:
- `getindex`
- `haskey`
- `get`
- `keys`
- `pairs`

Particle properties
- `atomkeys`
- `hasatomkey`



## Future Interface Extensions

The AtomsBase developers are considering extending the AtomsBase interface with additional functions. Developers may keep this in mind during development. Issues or discussions related to this are welcome.

Here we maintain a list of possibly future interface functions:

- `charge`
- `charge_dipole`
- `velocity`
- `momentum`
- `spin`
- `magnetic_moment`
- `multiplicity`
Loading

4 comments on commit 202ff91

@mfherbst
Copy link
Member

Choose a reason for hiding this comment

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

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

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

Registration pull request created: JuliaRegistries/General/113907

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.4.0 -m "<description of version>" 202ff91bb835294795aedb720a4f10d3fd96ec1a
git push origin v0.4.0

@mfherbst
Copy link
Member

Choose a reason for hiding this comment

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

@JuliaRegistrator register subdir=lib/AtomsBaseTesting

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

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

Registration pull request created: JuliaRegistries/General/113909

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a AtomsBaseTesting-v0.2.0 -m "<description of version>" 202ff91bb835294795aedb720a4f10d3fd96ec1a
git push origin AtomsBaseTesting-v0.2.0

Please sign in to comment.