I am trying to re-structure a molecular simulation code I've been working on, to make it more readily extendable. I am puzzling over how to do this most effectively in Julia, and would appreciate any thoughts from more experienced Julia programmers. I am roughly trying to mimic the structure of CAMPOS ASE ( a Python package ).
The main type that contains the simulation state is abstract AbstractAtoms The simplest sub-type is (here a simplified version) type Atoms X::Array{Float64, 2} # positions of atoms calc # calculator for computing energies, forces, etc neigs # neighbourlist precon # preconditioner end but there could be many other sub-types that store atom positions differently, or live on manifolds, or contain information for continuum mechanics boundary conditions, etc. I now need functions that depends on the type of the atoms object and on the type of calculator object. (for example). OPTION 1: At the moment, my thinking is that I can do function get_forces(atoms::AbstractAtoms) return get_forces(atoms, atoms.calc) end and the type of `atoms` and of `atoms.calc` will then determine which function is called. This feels a bit clunky to be honest, but looks like the best way to go? OPTION 2: Another thought that I had, was to define type Atoms{CT, NT, PT} X::Array{Float64, 2} # positions of atoms calc::CT # calculator for computing energies, forces, etc neigs::NT # neighbourlist precon::PT # preconditioner end function get_forces(atoms::Atoms{MyCalculator,NT,PT}) # . . . end and to determine the type of the calculator this way. The problem there is that I cannot give AbstractAtoms the parameters {CT, NT, PT} because other sub-types might use a different, possibly longer, possibly shorter list of parameters. I'd be very grateful for any advise what sort of constructions would be the most convenient / useful to try out here. Many thanks, Christoph