Developer setup
Source code installation
If you want to start developing DFTK it is highly recommended that you setup the sources in a way such that Julia can automatically keep track of your changes to the DFTK code files during your development. This means you should not Pkg.add
your package, but use Pkg.develop
instead. With this setup also tools such as Revise.jl can work properly. Note that using Revise.jl is highly recommended since this package automatically refreshes changes to the sources in an active Julia session (see its docs for more details).
To achieve such a setup you have two recommended options:
Clone DFTK into a location of your choice
$ git clone https://github.com/JuliaMolSim/DFTK.jl /some/path/
Whenever you want to use exactly this development version of DFTK in a Julia environment (e.g. the global one) add it as a
develop
package:import Pkg Pkg.develop("/some/path/")
To run a script or start a Julia REPL using exactly this source tree as the DFTK version, use the
--project
flag of Julia, see this documentation for details. For example to start a Julia REPL with this version of DFTK use$ julia --project=/some/path/
The advantage of this method is that you can easily have multiple clones of DFTK with potentially different modifications made.
Add a development version of DFTK to the global Julia environment:
import Pkg Pkg.develop("DFTK")
This clones DFTK to the path
~/.julia/dev/DFTK"
(on Linux). Note that with this method you cannot install both the stable and the development version of DFTK into your global environment.
Disabling precompilation
For the best experience in using DFTK we employ PrecompileTools.jl to reduce the time to first SCF. However, spending the additional time for precompiling DFTK is usually not worth it during development. We therefore recommend disabling precompilation in a development setup. See the PrecompileTools documentation for detailed instructions how to do this.
At the time of writing dropping a file LocalPreferences.toml
in DFTK's root folder (next to the Project.toml
) with the following contents is sufficient:
[DFTK]
precompile_workload = false
Running the tests
We use TestItemRunner to manage the tests. It reduces the risk to have undefined behavior by preventing tests from being run in global scope.
Moreover, it allows for greater flexibility by providing ways to launch a specific subset of the tests. For instance, to launch core functionality tests, one can use
using TestEnv # Optional: automatically installs required packages
TestEnv.activate() # for tests in a temporary environment.
using TestItemRunner
cd("test") # By default, the following macro runs everything from the parent folder.
@run_package_tests filter = ti -> :core ∈ ti.tags
Or to only run the tests of a particular file serialisation.jl
use
@run_package_tests filter = ti -> occursin("serialisation.jl", ti.filename)
If you need to write tests, note that you can create modules with @testsetup
. To use a function my_function
of a module MySetup
in a @testitem
, you can import it with
using .MySetup: my_function
It is also possible to use functions from another module within a module. But for this the order of the modules in the setup
keyword of @testitem
is important: you have to add the module that will be used before the module using it. From the latter, you can then use it with
using ..MySetup: my_function