├── MANIFEST.in ├── example ├── python_pkg │ ├── requirements.txt │ ├── visualisation │ │ ├── host.traj │ │ ├── converted_db.traj │ │ ├── POSCAR_AB_stack │ │ ├── POSCAR_lonsdaleite │ │ ├── POSCAR_AA_stack │ │ ├── POSCAR_diamond │ │ ├── POSCAR_ABC_stack │ │ ├── POSCAR_ABA_stack │ │ ├── POSCAR_AABBCC_stack │ │ └── POSCAR_ABAB_stack │ ├── agox_runs │ │ ├── Si-Ge_run │ │ │ ├── host.traj │ │ │ └── tidy.py │ │ ├── n-body_run │ │ │ └── tidy.py │ │ └── graphene_grain_boundary_run │ │ │ └── tidy.py │ ├── C_learn │ │ ├── DRSS │ │ │ ├── DOutput │ │ │ │ ├── rlxd_structures_seed0.traj │ │ │ │ └── unrlxd_structures_seed0.traj │ │ │ └── rss.py │ │ ├── DRAFFLE │ │ │ └── DOutput │ │ │ │ ├── rlxd_structures_seed0.traj │ │ │ │ ├── rlxd_structures_seed1.traj │ │ │ │ ├── rlxd_structures_seed2.traj │ │ │ │ ├── rlxd_structures_seed3.traj │ │ │ │ ├── rlxd_structures_seed4.traj │ │ │ │ ├── rlxd_structures_seed5.traj │ │ │ │ ├── rlxd_structures_seed6.traj │ │ │ │ ├── rlxd_structures_seed7.traj │ │ │ │ ├── rlxd_structures_seed8.traj │ │ │ │ ├── rlxd_structures_seed9.traj │ │ │ │ ├── rlxd_structures_seed10.traj │ │ │ │ ├── rlxd_structures_seed11.traj │ │ │ │ ├── rlxd_structures_seed12.traj │ │ │ │ ├── rlxd_structures_seed13.traj │ │ │ │ ├── rlxd_structures_seed14.traj │ │ │ │ ├── rlxd_structures_seed15.traj │ │ │ │ ├── rlxd_structures_seed16.traj │ │ │ │ ├── rlxd_structures_seed17.traj │ │ │ │ ├── rlxd_structures_seed18.traj │ │ │ │ ├── rlxd_structures_seed19.traj │ │ │ │ ├── unrlxd_structures_seed0.traj │ │ │ │ ├── unrlxd_structures_seed1.traj │ │ │ │ ├── unrlxd_structures_seed2.traj │ │ │ │ ├── unrlxd_structures_seed3.traj │ │ │ │ ├── unrlxd_structures_seed4.traj │ │ │ │ ├── unrlxd_structures_seed5.traj │ │ │ │ ├── unrlxd_structures_seed6.traj │ │ │ │ ├── unrlxd_structures_seed7.traj │ │ │ │ ├── unrlxd_structures_seed8.traj │ │ │ │ ├── unrlxd_structures_seed9.traj │ │ │ │ ├── unrlxd_structures_seed10.traj │ │ │ │ ├── unrlxd_structures_seed11.traj │ │ │ │ ├── unrlxd_structures_seed12.traj │ │ │ │ ├── unrlxd_structures_seed13.traj │ │ │ │ ├── unrlxd_structures_seed14.traj │ │ │ │ ├── unrlxd_structures_seed15.traj │ │ │ │ ├── unrlxd_structures_seed16.traj │ │ │ │ ├── unrlxd_structures_seed17.traj │ │ │ │ ├── unrlxd_structures_seed18.traj │ │ │ │ └── unrlxd_structures_seed19.traj │ │ └── Dgraphite_diamond │ │ │ ├── DOutput │ │ │ ├── rlxd_structures_seed0.traj │ │ │ └── unrlxd_structures_seed0.traj │ │ │ └── graphite.vasp │ ├── Al_learn │ │ ├── DRSS │ │ │ └── DOutput │ │ │ │ ├── rlxd_structures_seed0.traj │ │ │ │ └── unrlxd_structures_seed0.traj │ │ ├── DRAFFLE │ │ │ ├── DOutput │ │ │ │ ├── rlxd_structures_seed0.traj │ │ │ │ └── unrlxd_structures_seed0.traj │ │ │ └── DOutput_placements │ │ │ │ ├── method_v0.0_r0.0_w0.0_g0.0_m1.0 │ │ │ │ ├── rlxd_structures_seed0.traj │ │ │ │ └── unrlxd_structures_seed0.traj │ │ │ │ ├── method_v0.0_r0.0_w0.0_g1.0_m0.0 │ │ │ │ ├── rlxd_structures_seed0.traj │ │ │ │ └── unrlxd_structures_seed0.traj │ │ │ │ ├── method_v0.0_r0.0_w1.0_g0.0_m0.0 │ │ │ │ ├── rlxd_structures_seed0.traj │ │ │ │ └── unrlxd_structures_seed0.traj │ │ │ │ ├── method_v0.0_r1.0_w0.0_g0.0_m0.0 │ │ │ │ ├── rlxd_structures_seed0.traj │ │ │ │ └── unrlxd_structures_seed0.traj │ │ │ │ ├── method_v1.0_r0.0_w0.0_g0.0_m0.0 │ │ │ │ ├── rlxd_structures_seed0.traj │ │ │ │ └── unrlxd_structures_seed0.traj │ │ │ │ ├── method_v0.0_r15.0_w0.0_g0.0_m85.0 │ │ │ │ ├── rlxd_structures_seed0.traj │ │ │ │ └── unrlxd_structures_seed0.traj │ │ │ │ ├── method_v0.0_r15.0_w0.0_g85.0_m0.0 │ │ │ │ ├── rlxd_structures_seed0.traj │ │ │ │ └── unrlxd_structures_seed0.traj │ │ │ │ ├── method_v0.0_r15.0_w85.0_g0.0_m0.0 │ │ │ │ ├── rlxd_structures_seed0.traj │ │ │ │ └── unrlxd_structures_seed0.traj │ │ │ │ └── method_v85.0_r15.0_w0.0_g0.0_m0.0 │ │ │ │ ├── rlxd_structures_seed0.traj │ │ │ │ └── unrlxd_structures_seed0.traj │ │ └── known_phases │ │ │ ├── mp-998860.vasp │ │ │ ├── mp-134.vasp │ │ │ ├── mp-2647008.vasp │ │ │ └── mp-1183144.vasp │ ├── MoS2_learn │ │ ├── DRSS │ │ │ └── DOutput │ │ │ │ ├── rlxd_structures_seed0.traj │ │ │ │ └── unrlxd_structures_seed0.traj │ │ ├── DRAFFLE │ │ │ ├── DOutput │ │ │ │ ├── rlxd_structures_seed0.traj │ │ │ │ └── unrlxd_structures_seed0.traj │ │ │ └── DOutput_CHGNet-DFTD4 │ │ │ │ ├── rlxd_structures_seed0.traj │ │ │ │ └── unrlxd_structures_seed0.traj │ │ ├── MoS2_H-phase.poscar │ │ ├── MoS2_T-phase.poscar │ │ └── Mo.poscar │ ├── Si-Ge_learn │ │ ├── DRAFFLE │ │ │ ├── DOutput │ │ │ │ ├── rlxd_structures_seed2.traj │ │ │ │ └── unrlxd_structures_seed2.traj │ │ │ └── DOutput_CHGNet │ │ │ │ ├── rlxd_structures_seed0.traj │ │ │ │ └── unrlxd_structures_seed0.traj │ │ ├── abrupt_shifts.py │ │ ├── Ge_slab.vasp │ │ └── Si_slab.vasp │ ├── ScS2-Li_learn │ │ ├── DRAFFLE │ │ │ └── DOutput │ │ │ │ ├── rlxd_structures_seed0.traj │ │ │ │ └── unrlxd_structures_seed0.traj │ │ ├── Li.xyz │ │ └── ScS2.vasp │ ├── graphene_grain_boundary_learn │ │ ├── DRSS │ │ │ └── DOutput │ │ │ │ ├── rlxd_structures_seed42.traj │ │ │ │ └── unrlxd_structures_seed42.traj │ │ ├── DRAFFLE │ │ │ └── DOutput │ │ │ │ ├── rlxd_structures_seed0_combined.traj │ │ │ │ └── unrlxd_structures_seed0_combined.traj │ │ └── POSCAR_graphene │ ├── .gitattributes │ ├── graphite │ │ ├── POSCAR_host_missing_layer │ │ ├── POSCAR_host_graphene │ │ └── POSCAR_host_graphite_vacancy │ ├── diamond │ │ ├── POSCAR_host │ │ └── POSCAR_host_3x3 │ ├── perovskites │ │ └── database.xyz │ ├── README.md │ └── benchmarks │ │ ├── min_placement.py │ │ ├── placement_methods.py │ │ └── create_gdfs.py ├── fortran_exe │ ├── run.sh │ └── param.in └── data │ └── C-MgO_hosts │ ├── POSCAR_1x1_5.4A_separation │ ├── POSCAR_2x2_5.4A_separation │ ├── POSCAR_5x1_5.4A_separation │ ├── POSCAR_3x3_11.0A_separation │ ├── POSCAR_3x3_5.4A_separation │ ├── POSCAR_1x5_orthorhombic_11.0A_separation │ ├── POSCAR_orthorhombic_11.1A_separation_Mg_seeded │ ├── POSCAR_4x4_11.0A_separation │ └── POSCAR_4x4_14.7A_separation ├── docs ├── source │ ├── RAFFLE_logo.pdf │ ├── RAFFLE_logo_no_background.png │ ├── raffle.geom.rst │ ├── raffle.generator.rst │ ├── raffle.geom_rw_class.rst │ ├── raffle.generator_class.rst │ ├── raffle.distributions.rst │ ├── raffle.distributions_class.rst │ ├── raffle.geom_module.rst │ ├── about.rst │ ├── references.bib │ ├── raffle.generator_module.rst │ ├── tutorials │ │ ├── index.rst │ │ ├── aluminium_tutorial.rst │ │ ├── quick_guide.rst │ │ ├── host_tutorial.rst │ │ └── generating_tutorial.rst │ ├── modules.rst │ ├── conf.py │ └── index.rst ├── requirements.txt ├── Makefile ├── make.bat └── RAFFLE.bib ├── src ├── wrapper │ └── f90wrap_raffle.f90 ├── fortran │ ├── raffle.f90 │ └── lib │ │ ├── mod_constants.f90 │ │ ├── mod_cache.f90 │ │ ├── mod_io_utils.F90 │ │ └── mod_misc_maths.f90 └── raffle │ └── __init__.py ├── tools ├── .gitattributes ├── coverage_badge.py ├── version_number.py ├── check_accuracy_C-MgO.py ├── database.py ├── visualise_evaluator.py ├── check_accuracy_C-Li.py ├── check_accuracy_C.py ├── check_accuracy_MoS2.py ├── check_accuracy_Al.py ├── database.ipynb └── check_accuracy_ScS2-Li.py ├── test ├── data │ └── POSCAR_Si ├── CMakeLists.txt ├── test_io_utils.f90 ├── test_tools_infile.f90 ├── test_cache.f90 └── test_misc_maths.f90 ├── .pre-commit-config.yaml ├── conftest.py ├── kind_map ├── fpm.toml ├── .github ├── PULL_REQUEST_TEMPLATE │ └── pull_request_template.md ├── ISSUE_TEMPLATE │ ├── feature_request.yaml │ └── bug_report.yaml └── workflows │ ├── python.yml │ ├── fpm.yml │ └── coverage.yml ├── ford.md ├── .gitignore ├── .readthedocs.yaml ├── CITATION.cff ├── pyproject.toml └── CODE_OF_CONDUCT.md /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include src/raffle/*.py 2 | -------------------------------------------------------------------------------- /example/python_pkg/requirements.txt: -------------------------------------------------------------------------------- 1 | mace-torch==0.3.12 2 | chgnet==0.4.0 3 | joblib==1.4.2 4 | -------------------------------------------------------------------------------- /example/fortran_exe/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | $HOME/.local/raffle/bin/raffle_executable -f param.in 4 | -------------------------------------------------------------------------------- /docs/source/RAFFLE_logo.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/docs/source/RAFFLE_logo.pdf -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx==8.1.3 2 | sphinx-rtd-theme==3.0.2 3 | sphinxcontrib-bibtex==2.6.3 4 | f90wrap==0.2.16 5 | -------------------------------------------------------------------------------- /docs/source/RAFFLE_logo_no_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/docs/source/RAFFLE_logo_no_background.png -------------------------------------------------------------------------------- /example/python_pkg/visualisation/host.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/visualisation/host.traj -------------------------------------------------------------------------------- /src/wrapper/f90wrap_raffle.f90: -------------------------------------------------------------------------------- 1 | ! Module raffle defined in file ../raffle.f90 2 | 3 | ! End of module raffle defined in file ../raffle.f90 4 | 5 | -------------------------------------------------------------------------------- /example/python_pkg/agox_runs/Si-Ge_run/host.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/agox_runs/Si-Ge_run/host.traj -------------------------------------------------------------------------------- /example/python_pkg/visualisation/converted_db.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/visualisation/converted_db.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRSS/DOutput/rlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRSS/DOutput/rlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRSS/DOutput/rlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRSS/DOutput/rlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRSS/DOutput/unrlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRSS/DOutput/unrlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed1.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed1.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed2.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed2.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed3.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed3.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed4.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed4.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed5.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed5.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed6.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed6.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed7.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed7.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed8.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed8.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed9.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed9.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRSS/DOutput/unrlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRSS/DOutput/unrlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/MoS2_learn/DRSS/DOutput/rlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/MoS2_learn/DRSS/DOutput/rlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRAFFLE/DOutput/rlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRAFFLE/DOutput/rlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed10.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed10.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed11.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed11.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed12.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed12.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed13.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed13.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed14.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed14.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed15.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed15.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed16.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed16.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed17.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed17.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed18.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed18.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed19.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/rlxd_structures_seed19.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed1.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed1.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed2.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed2.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed3.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed3.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed4.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed4.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed5.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed5.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed6.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed6.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed7.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed7.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed8.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed8.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed9.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed9.traj -------------------------------------------------------------------------------- /example/python_pkg/MoS2_learn/DRSS/DOutput/unrlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/MoS2_learn/DRSS/DOutput/unrlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRAFFLE/DOutput/unrlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRAFFLE/DOutput/unrlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed10.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed10.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed11.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed11.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed12.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed12.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed13.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed13.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed14.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed14.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed15.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed15.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed16.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed16.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed17.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed17.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed18.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed18.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed19.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/DRAFFLE/DOutput/unrlxd_structures_seed19.traj -------------------------------------------------------------------------------- /example/python_pkg/MoS2_learn/DRAFFLE/DOutput/rlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/MoS2_learn/DRAFFLE/DOutput/rlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/MoS2_learn/DRAFFLE/DOutput/unrlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/MoS2_learn/DRAFFLE/DOutput/unrlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Si-Ge_learn/DRAFFLE/DOutput/rlxd_structures_seed2.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Si-Ge_learn/DRAFFLE/DOutput/rlxd_structures_seed2.traj -------------------------------------------------------------------------------- /example/python_pkg/ScS2-Li_learn/DRAFFLE/DOutput/rlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/ScS2-Li_learn/DRAFFLE/DOutput/rlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Si-Ge_learn/DRAFFLE/DOutput/unrlxd_structures_seed2.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Si-Ge_learn/DRAFFLE/DOutput/unrlxd_structures_seed2.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/Dgraphite_diamond/DOutput/rlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/Dgraphite_diamond/DOutput/rlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/ScS2-Li_learn/DRAFFLE/DOutput/unrlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/ScS2-Li_learn/DRAFFLE/DOutput/unrlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/C_learn/Dgraphite_diamond/DOutput/unrlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/C_learn/Dgraphite_diamond/DOutput/unrlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Si-Ge_learn/DRAFFLE/DOutput_CHGNet/rlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Si-Ge_learn/DRAFFLE/DOutput_CHGNet/rlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Si-Ge_learn/DRAFFLE/DOutput_CHGNet/unrlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Si-Ge_learn/DRAFFLE/DOutput_CHGNet/unrlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/MoS2_learn/DRAFFLE/DOutput_CHGNet-DFTD4/rlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/MoS2_learn/DRAFFLE/DOutput_CHGNet-DFTD4/rlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/MoS2_learn/DRAFFLE/DOutput_CHGNet-DFTD4/unrlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/MoS2_learn/DRAFFLE/DOutput_CHGNet-DFTD4/unrlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/graphene_grain_boundary_learn/DRSS/DOutput/rlxd_structures_seed42.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/graphene_grain_boundary_learn/DRSS/DOutput/rlxd_structures_seed42.traj -------------------------------------------------------------------------------- /example/python_pkg/graphene_grain_boundary_learn/DRSS/DOutput/unrlxd_structures_seed42.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/graphene_grain_boundary_learn/DRSS/DOutput/unrlxd_structures_seed42.traj -------------------------------------------------------------------------------- /tools/.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto-remove output from Jupyter notebooks 2 | # Follow the guide from this link to set up the filter: 3 | # https://gist.github.com/33eyes/431e3d432f73371509d176d0dfb95b6e 4 | *.ipynb filter=strip-notebook-output -------------------------------------------------------------------------------- /example/python_pkg/.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto-remove output from Jupyter notebooks 2 | # Follow the guide from this link to set up the filter: 3 | # https://gist.github.com/33eyes/431e3d432f73371509d176d0dfb95b6e 4 | *.ipynb filter=strip-notebook-output -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/known_phases/mp-998860.vasp: -------------------------------------------------------------------------------- 1 | Al mp-998860 2 | 1.0 3 | 3.182437 0.000000 0.000000 4 | -0.000000 3.182437 0.000000 5 | 0.000000 0.000000 3.182437 6 | Al 7 | 2 8 | direct 9 | 0.0 0.0 0.0 10 | 0.5 0.5 0.5 11 | -------------------------------------------------------------------------------- /example/python_pkg/graphene_grain_boundary_learn/DRAFFLE/DOutput/rlxd_structures_seed0_combined.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/graphene_grain_boundary_learn/DRAFFLE/DOutput/rlxd_structures_seed0_combined.traj -------------------------------------------------------------------------------- /example/python_pkg/graphene_grain_boundary_learn/DRAFFLE/DOutput/unrlxd_structures_seed0_combined.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/graphene_grain_boundary_learn/DRAFFLE/DOutput/unrlxd_structures_seed0_combined.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/known_phases/mp-134.vasp: -------------------------------------------------------------------------------- 1 | Al mp-134 2 | 1.0 3 | 4.03893 0.00000 0.00000 4 | 0.00000 4.03893 0.00000 5 | 0.00000 0.00000 4.03893 6 | Al 7 | 4 8 | direct 9 | 0.0 0.0 0.0 10 | 0.0 0.5 0.5 11 | 0.5 0.0 0.5 12 | 0.5 0.5 0.0 13 | -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/known_phases/mp-2647008.vasp: -------------------------------------------------------------------------------- 1 | Al mp-2647008 2 | 1.0 3 | 1.4062277 -2.4356578 0.00000 4 | 1.4062277 2.4356578 0.00000 5 | 0.0000000 0.0000000 4.86685 6 | Al 7 | 2 8 | direct 9 | 0.6666667 0.3333333 0.75 10 | 0.3333333 0.6666667 0.25 11 | -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r0.0_w0.0_g0.0_m1.0/rlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r0.0_w0.0_g0.0_m1.0/rlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r0.0_w0.0_g1.0_m0.0/rlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r0.0_w0.0_g1.0_m0.0/rlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r0.0_w1.0_g0.0_m0.0/rlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r0.0_w1.0_g0.0_m0.0/rlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r1.0_w0.0_g0.0_m0.0/rlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r1.0_w0.0_g0.0_m0.0/rlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v1.0_r0.0_w0.0_g0.0_m0.0/rlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v1.0_r0.0_w0.0_g0.0_m0.0/rlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r0.0_w0.0_g0.0_m1.0/unrlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r0.0_w0.0_g0.0_m1.0/unrlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r0.0_w0.0_g1.0_m0.0/unrlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r0.0_w0.0_g1.0_m0.0/unrlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r0.0_w1.0_g0.0_m0.0/unrlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r0.0_w1.0_g0.0_m0.0/unrlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r1.0_w0.0_g0.0_m0.0/unrlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r1.0_w0.0_g0.0_m0.0/unrlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r15.0_w0.0_g0.0_m85.0/rlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r15.0_w0.0_g0.0_m85.0/rlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r15.0_w0.0_g85.0_m0.0/rlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r15.0_w0.0_g85.0_m0.0/rlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r15.0_w85.0_g0.0_m0.0/rlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r15.0_w85.0_g0.0_m0.0/rlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v1.0_r0.0_w0.0_g0.0_m0.0/unrlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v1.0_r0.0_w0.0_g0.0_m0.0/unrlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v85.0_r15.0_w0.0_g0.0_m0.0/rlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v85.0_r15.0_w0.0_g0.0_m0.0/rlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r15.0_w0.0_g0.0_m85.0/unrlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r15.0_w0.0_g0.0_m85.0/unrlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r15.0_w0.0_g85.0_m0.0/unrlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r15.0_w0.0_g85.0_m0.0/unrlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r15.0_w85.0_g0.0_m0.0/unrlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v0.0_r15.0_w85.0_g0.0_m0.0/unrlxd_structures_seed0.traj -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v85.0_r15.0_w0.0_g0.0_m0.0/unrlxd_structures_seed0.traj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExeQuantCode/RAFFLE/HEAD/example/python_pkg/Al_learn/DRAFFLE/DOutput_placements/method_v85.0_r15.0_w0.0_g0.0_m0.0/unrlxd_structures_seed0.traj -------------------------------------------------------------------------------- /docs/source/raffle.geom.rst: -------------------------------------------------------------------------------- 1 | raffle.geom_rw module 2 | ======================= 3 | 4 | .. .. automodule:: raffle.Geom_Rw 5 | .. :members: 6 | .. :undoc-members: 7 | .. :show-inheritance: 8 | 9 | .. autoclass:: raffle.Geom_Rw 10 | :members: 11 | :undoc-members: 12 | :show-inheritance: 13 | -------------------------------------------------------------------------------- /test/data/POSCAR_Si: -------------------------------------------------------------------------------- 1 | Si 2 | 5.44 3 | 1.00 0.00 0.00 4 | 0.00 1.00 0.00 5 | 0.00 0.00 1.00 6 | Si 7 | 8 8 | direct 9 | 0.75 0.75 0.25 10 | 0.00 0.50 0.50 11 | 0.75 0.25 0.75 12 | 0.00 0.00 0.00 13 | 0.25 0.75 0.75 14 | 0.50 0.50 0.00 15 | 0.25 0.25 0.25 16 | 0.50 0.00 0.50 17 | -------------------------------------------------------------------------------- /docs/source/raffle.generator.rst: -------------------------------------------------------------------------------- 1 | raffle.generator module 2 | ======================= 3 | 4 | .. .. automodule:: raffle.Generator 5 | .. :members: 6 | .. :undoc-members: 7 | .. :show-inheritance: 8 | 9 | 10 | .. autoclass:: raffle.Generator 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: -------------------------------------------------------------------------------- /docs/source/raffle.geom_rw_class.rst: -------------------------------------------------------------------------------- 1 | raffle.Geom_Rw Class 2 | ======================= 3 | 4 | .. .. automodule:: raffle.Geom_Rw 5 | .. :members: 6 | .. :undoc-members: 7 | .. :show-inheritance: 8 | 9 | .. autoclass:: raffle.raffle.Geom_Rw 10 | :members: 11 | :undoc-members: 12 | :show-inheritance: 13 | -------------------------------------------------------------------------------- /docs/source/raffle.generator_class.rst: -------------------------------------------------------------------------------- 1 | raffle.Generator Class 2 | ======================= 3 | 4 | .. .. automodule:: raffle.Generator 5 | .. :members: 6 | .. :undoc-members: 7 | .. :show-inheritance: 8 | 9 | .. autoclass:: raffle.raffle.Generator 10 | :members: 11 | :undoc-members: 12 | :show-inheritance: -------------------------------------------------------------------------------- /example/python_pkg/Al_learn/known_phases/mp-1183144.vasp: -------------------------------------------------------------------------------- 1 | Al mp-1183144 2 | 1.0 3 | 1.413539 -2.448321 0.000000 4 | 1.413539 2.448321 0.000000 5 | 0.000000 0.000000 9.185993 6 | Al 7 | 4 8 | direct 9 | 0.0000000 0.0000000 0.00 10 | 0.3333333 0.6666666 0.25 11 | 0.0000000 0.0000000 0.50 12 | 0.6666666 0.3333333 0.75 13 | -------------------------------------------------------------------------------- /docs/source/raffle.distributions.rst: -------------------------------------------------------------------------------- 1 | raffle.distributions module 2 | =========================== 3 | 4 | .. .. automodule:: raffle.Raffle__Distribs_Container 5 | .. :members: 6 | .. :undoc-members: 7 | .. :show-inheritance: 8 | 9 | .. autoclass:: raffle.Raffle__Distribs_Container 10 | :members: 11 | :undoc-members: 12 | :show-inheritance: 13 | -------------------------------------------------------------------------------- /docs/source/raffle.distributions_class.rst: -------------------------------------------------------------------------------- 1 | raffle.distributions Class 2 | =========================== 3 | 4 | .. .. automodule:: raffle.Raffle__Distribs_Container 5 | .. :members: 6 | .. :undoc-members: 7 | .. :show-inheritance: 8 | 9 | .. autoclass:: raffle.raffle.Raffle__Distribs_Container 10 | :members: 11 | :undoc-members: 12 | :show-inheritance: 13 | -------------------------------------------------------------------------------- /example/python_pkg/MoS2_learn/MoS2_H-phase.poscar: -------------------------------------------------------------------------------- 1 | MoS2 H-phase 2 | 1.0 3 | 1.592716 -2.758665 0.000000 4 | 1.592716 2.758665 0.000000 5 | 0.000000 0.000000 13.178390 6 | Mo S 7 | 2 4 8 | direct 9 | 0.000000 0.000000 0.250000 10 | 0.000000 0.000000 0.750000 11 | 0.333333 0.666666 0.367743 12 | 0.666666 0.333333 0.632256 13 | 0.666666 0.333333 0.867743 14 | 0.333333 0.666666 0.132256 -------------------------------------------------------------------------------- /example/python_pkg/MoS2_learn/MoS2_T-phase.poscar: -------------------------------------------------------------------------------- 1 | MoS2 T-phase 2 | 1.0 3 | 1.592716 -2.758665 0.000000 4 | 1.592716 2.758665 0.000000 5 | 0.000000 0.000000 12.62495 6 | Mo S 7 | 2 4 8 | direct 9 | 0.000000 0.000000 0.250000 10 | 0.000000 0.000000 0.750000 11 | 0.333333 0.666666 0.127659 12 | 0.666666 0.333333 0.372341 13 | 0.333333 0.666666 0.627659 14 | 0.666666 0.333333 0.872341 -------------------------------------------------------------------------------- /example/python_pkg/visualisation/POSCAR_AB_stack: -------------------------------------------------------------------------------- 1 | AB stack 2 | 1.0 3 | 0.000000000 4.255049746 0.000000000 4 | 2.456364992 0.000000000 0.000000000 5 | 0.000000000 -1.163571728 -3.507435407 6 | C 7 | 4 8 | direct 9 | 0.833330769 0.000000000 0.999957858 10 | 0.666669230 0.500000000 0.000042141 11 | 0.333330769 0.500000000 0.999957858 12 | 0.166669230 0.000000000 0.000042141 13 | -------------------------------------------------------------------------------- /example/python_pkg/graphene_grain_boundary_learn/POSCAR_graphene: -------------------------------------------------------------------------------- 1 | C2 2 | 1.0 3 | 1.2336456308015411 -2.1367369110836258 0.0000000000000000 4 | 1.2336456308015411 2.1367369110836258 0.0000000000000000 5 | 0.0000000000000000 0.0000000000000000 10.0 6 | C 7 | 2 8 | direct 9 | 0.0000000000000000 0.0000000000000000 0.2500000000000000 C0+ 10 | 0.3333333333333330 0.6666666666666661 0.2500000000000000 C0+ 11 | -------------------------------------------------------------------------------- /example/python_pkg/visualisation/POSCAR_lonsdaleite: -------------------------------------------------------------------------------- 1 | lonsdaleite 2 | 1.0 3 | 1.251651409 -2.167923835 0.000000000 4 | 1.251651409 2.167923835 0.000000000 5 | 0.000000000 0.000000000 4.168968810 6 | C 7 | 4 8 | direct 9 | 0.333333333 0.666666666 0.062805350 10 | 0.666666666 0.333333333 0.562805350 11 | 0.666666666 0.333333333 0.937194650 12 | 0.333333333 0.666666666 0.437194650 13 | -------------------------------------------------------------------------------- /example/python_pkg/visualisation/POSCAR_AA_stack: -------------------------------------------------------------------------------- 1 | AA stack 2 | 1.0 3 | 1.2279976842911540 -2.1269543807692060 0.0000000000000000 4 | 1.2279976842911540 2.1269543807692060 0.0000000000000000 5 | 0.0000000000000000 0.0000000000000000 3.6596614593024759 6 | C 7 | 2 8 | direct 9 | 0.3333333333333330 0.6666666666666661 0.0000000000000000 C0+ 10 | 0.6666666666666661 0.3333333333333330 0.0000000000000000 C0+ 11 | -------------------------------------------------------------------------------- /example/python_pkg/visualisation/POSCAR_diamond: -------------------------------------------------------------------------------- 1 | diamond 2 | 1.0 3 | 3.560745109 0.000000000 0.000000000 4 | -0.000000000 3.560745109 0.000000000 5 | 0.000000000 0.000000000 3.560745109 6 | C 7 | 8 8 | direct 9 | 0.00 0.00 0.50 10 | 0.25 0.25 0.75 11 | 0.00 0.50 0.00 12 | 0.25 0.75 0.25 13 | 0.50 0.00 0.00 14 | 0.75 0.25 0.25 15 | 0.50 0.50 0.50 16 | 0.75 0.75 0.75 17 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v5.0.0 # Use the ref you want to point at 4 | hooks: 5 | - id: trailing-whitespace 6 | - id: end-of-file-fixer 7 | - repo: https://github.com/nedtaylor/fortran-format-hooks 8 | rev: 749c61fce3a5f29f6d5d3b236ed9b693c6b2bf4e 9 | hooks: 10 | - id: check-fortran-indentation 11 | args: [--line-length=80, --ignore-directories=src/wrapper] 12 | -------------------------------------------------------------------------------- /conftest.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | def pytest_addoption(parser): 4 | parser.addoption( 5 | "--fortran-compiler", 6 | action="store", 7 | default="gfortran", # Default compiler 8 | help="Specify the Fortran compiler to use" 9 | ) 10 | 11 | def pytest_configure(config): 12 | # Make the Fortran compiler available globally during tests 13 | compiler = config.getoption("--fortran-compiler") 14 | os.environ["FORTRAN_COMPILER"] = compiler -------------------------------------------------------------------------------- /example/python_pkg/MoS2_learn/Mo.poscar: -------------------------------------------------------------------------------- 1 | Mo2 2 | 1.00000000000000 3 | 3.1229640216873942 -0.0000000000000000 -0.0000000000000000 4 | 0.0000000000000000 3.1229640216873942 -0.0000000000000000 5 | 0.0000000000000000 0.0000000000000000 3.1229640216873942 6 | Mo 7 | 2 8 | Direct 9 | 0.0000000000000000 0.0000000000000000 0.0000000000000000 10 | 0.5000000000000000 0.5000000000000000 0.5000000000000000 11 | -------------------------------------------------------------------------------- /example/python_pkg/ScS2-Li_learn/Li.xyz: -------------------------------------------------------------------------------- 1 | 2 2 | Lattice="3.35384128 0.0 0.0 0.0 3.35384128 0.0 0.0 0.0 3.35384128" Properties=species:S:1:pos:R:3:forces:R:3 energy=-7.55514851 stress="-0.0005756199522743655 0.0 -0.0 0.0 -0.0005756199522743655 -0.0 -0.0 -0.0 -0.0005756199522743655" free_energy=-7.55531811 pbc="T T T" 3 | Li 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 4 | Li 1.67692064 1.67692064 1.67692064 0.00000000 0.00000000 0.00000000 5 | -------------------------------------------------------------------------------- /src/fortran/raffle.f90: -------------------------------------------------------------------------------- 1 | module raffle 2 | use raffle__constants, only: real32 3 | use raffle__io_utils, only: raffle__version__ 4 | use raffle__generator, only: raffle_generator_type 5 | use raffle__distribs_container, only: distribs_container_type 6 | use raffle__cache, only: & 7 | store_probability_density, retrieve_probability_density 8 | implicit none 9 | 10 | 11 | private 12 | public :: real32 13 | public :: distribs_container_type 14 | public :: raffle_generator_type 15 | 16 | 17 | end module raffle 18 | -------------------------------------------------------------------------------- /example/python_pkg/graphite/POSCAR_host_missing_layer: -------------------------------------------------------------------------------- 1 | C 2 | 1.000000000 3 | 1.233645631 -2.136736911 0.000000000 4 | 1.233645631 2.136736911 0.000000000 5 | 0.000000000 0.000000000 15.606146000 6 | C 7 | 6 8 | Direct 9 | 0.000000000 0.000000000 0.125000000 10 | 0.000000000 0.000000000 0.375000000 11 | 0.000000000 0.000000000 0.875000000 12 | 0.333333333 0.666666667 0.125000000 13 | 0.666666667 0.333333333 0.375000000 14 | 0.666666667 0.333333333 0.875000000 15 | 16 | -------------------------------------------------------------------------------- /kind_map: -------------------------------------------------------------------------------- 1 | { 2 | 'real': {'': 'float', 3 | '4': 'float', 4 | '8': 'double', 5 | 'dp': 'double', 6 | 'idp':'double', 7 | 'real32': 'float'}, 8 | 'complex' : {'': 'complex_float', 9 | '8' : 'complex_double', 10 | '16': 'complex_long_double', 11 | 'dp': 'complex_double', 12 | 'real32': 'complex_float'}, 13 | 'integer' : {'' : 'int', 14 | '4': 'int', 15 | '8': 'long_long', 16 | 'dp': 'long_long', 17 | 'quadint_k': 'long_long'} 18 | } -------------------------------------------------------------------------------- /example/python_pkg/ScS2-Li_learn/ScS2.vasp: -------------------------------------------------------------------------------- 1 | ScS2 2 | 1.00000000000000 3 | 3.4373550228202143 1.2722491953399284 -0.0985749251780342 4 | 0.6164998078516010 3.5730165704323316 -0.5636062457623744 5 | -0.1941735091202983 0.9816038800609169 6.1273390509283345 6 | Sc S 7 | 1 2 8 | Direct 9 | 0.6762039103400640 0.1332178797064758 0.9103732174536018 10 | 0.0097462202190008 0.4656228504900874 0.6731159326278954 11 | 0.3427267534832620 0.8007351821914250 0.1476299218798714 12 | 13 | -------------------------------------------------------------------------------- /fpm.toml: -------------------------------------------------------------------------------- 1 | name = "raffle" 2 | version = "1.1.1" 3 | author = "Ned Thaddeus Taylor" 4 | maintainer = "n.t.taylor@exeter.ac.uk" 5 | description = "A Fortran library and executable for structure prediction at material interfaces" 6 | 7 | [preprocess] 8 | [preprocess.cpp] 9 | suffixes = ["F90", "f90"] 10 | 11 | [library] 12 | source-dir="src/fortran" 13 | 14 | [dependencies] 15 | openmp = "*" 16 | 17 | [fortran] 18 | implicit-typing = false 19 | implicit-external = false 20 | source-form = "free" 21 | 22 | [[executable]] 23 | name="raffle_executable" 24 | source-dir="app" 25 | main="main.f90" 26 | -------------------------------------------------------------------------------- /example/python_pkg/C_learn/Dgraphite_diamond/graphite.vasp: -------------------------------------------------------------------------------- 1 | C4 2 | 1.0 3 | 0.0000000000000000 4.2546406144450799 0.0000000000000000 4 | 2.4565648800000002 0.0000000000000000 0.0000000000000000 5 | 0.0000000000000000 -1.3790696309310659 -3.5028300786042923 6 | C 7 | 4 8 | direct 9 | 0.1666444699999990 0.0000000000000000 0.9999069600000000 C0+ 10 | 0.8333555300000001 0.0000000000000000 0.0000930400000000 C0+ 11 | 0.6666444699999990 0.5000000000000000 0.9999069600000000 C0+ 12 | 0.3333555300000000 0.5000000000000000 0.0000930400000000 C0+ 13 | -------------------------------------------------------------------------------- /example/python_pkg/diamond/POSCAR_host: -------------------------------------------------------------------------------- 1 | C8 2 | 1.000000000 3 | 3.560745109 0.000000000 0.000000000 4 | 0.000000000 3.560745109 0.000000000 5 | 0.000000000 0.000000000 7.121490218 6 | C 7 | 8 8 | Direct 9 | 0.000000000 0.000000000 0.000000000 10 | 0.500000000 0.500000000 0.000000000 11 | 0.500000000 0.000000000 0.250000000 12 | 0.000000000 0.500000000 0.250000000 13 | 0.250000000 0.250000000 0.125000000 14 | 0.750000000 0.750000000 0.125000000 15 | 0.750000000 0.250000000 0.375000000 16 | 0.250000000 0.750000000 0.375000000 17 | -------------------------------------------------------------------------------- /example/python_pkg/visualisation/POSCAR_ABC_stack: -------------------------------------------------------------------------------- 1 | ABC stack 2 | 2.4500000000000002 3 | 1.0066380067671441 -0.0000007331712457 0.0000003579759198 4 | -0.5033196383284964 0.8717737197054177 -0.0000003579759198 5 | 0.0000009726444368 -0.0000005615565274 4.0456738842247359 6 | C 7 | 6 8 | Direct 9 | 0.9998104166167796 0.9996664427628408 0.9996638036663712 10 | 0.3331436245480242 0.6663332899081239 0.9997301605660306 11 | 0.3328565033263268 0.6661897228378959 0.3329667808200413 12 | 0.6661897228378950 0.3328565033263259 0.3330332191799555 13 | 0.9996664427628416 0.9998104166167796 0.6663361963336256 14 | 0.6663332899081230 0.3331436245480243 0.6662698394339662 15 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= python -m sphinx 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /src/fortran/lib/mod_constants.f90: -------------------------------------------------------------------------------- 1 | module raffle__constants 2 | !! Module with global constants 3 | !! 4 | !! This module contains global constants that may be used throughout the 5 | !! library. 6 | implicit none 7 | integer, parameter, public :: real32 = Selected_real_kind(6,37)!(15,307) 8 | real(real32), parameter, public :: tau = 8._real32 * atan(1._real32) 9 | real(real32), parameter, public :: pi = 4._real32 * atan(1._real32) 10 | real(real32), parameter, public :: c = 0.26246582250210965422_real32 11 | real(real32), parameter, public :: c_vasp = 0.262465831_real32 12 | real(real32), parameter, public :: INF = huge(0._real32) 13 | complex(real32), parameter, public :: imag=(0._real32, 1._real32) 14 | end module raffle__constants 15 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | > _Briefly describe the purpose and content of this merge request._ 4 | > _E.g. "Add structure generation constraints", or "Fix bug in energy parsing"._ 5 | 6 | # Checklist 7 | 8 | Mark with `x` when complete, or `~` if not applicable. 9 | 10 | - [ ] [I have read and followed the **RAFFLE's contribution guidelines.**](https://github.com/ExeQuantCode/RAFFLE/blob/main/CONTRIBUTING.md) 11 | - [ ] **Code is commented** appropriately, and API docstrings follow NumPy or FORD style. 12 | - [ ] **Read*the*Docs** documentation is added/updated (if applicable). 13 | - [ ] **Unit tests** are added/updated (if applicable). 14 | - [ ] **Linked issue** is resolved with a `closes #XXXX` reference (if applicable). 15 | -------------------------------------------------------------------------------- /docs/source/raffle.geom_module.rst: -------------------------------------------------------------------------------- 1 | raffle.geom Module 2 | ======================= 3 | 4 | This is a simulated module that holds the following class: 5 | 6 | - :class:`raffle.Geom_Rw()` 7 | 8 | This class cannot be directly accessed, but the two user-facing classes within it can be. 9 | Within this class, there exist two directly accessible sub-classes: 10 | 11 | - :class:`raffle.geom.basis()` 12 | - :class:`raffle.geom.basis_array()` 13 | 14 | These are used to handle the geometry of the system, where the former is a single instance of the geometry and the latter is an array of instances. 15 | The documentation for these can be found here: :doc:`raffle.geom_rw_class`. 16 | 17 | .. automodule:: raffle.geom 18 | :members: 19 | :undoc-members: 20 | :show-inheritance: 21 | -------------------------------------------------------------------------------- /example/python_pkg/visualisation/POSCAR_ABA_stack: -------------------------------------------------------------------------------- 1 | ABA vacuum 2 | 1.0 3 | 1.228124980 -2.127174863 0.000000000 4 | 1.228124980 2.127174863 0.000000000 5 | 0.000000000 0.000000000 29.491878700 6 | C 7 | 12 8 | direct 9 | 0.666666666 0.333333333 0.998371799 10 | 0.666666666 0.333333333 0.498371910 11 | 0.666666666 0.333333333 0.732787949 12 | 0.666666666 0.333333333 0.232790329 13 | 0.000000000 0.000000000 0.615837989 14 | 0.333333333 0.666666666 0.232787949 15 | 0.000000000 0.000000000 0.115837989 16 | 0.666666666 0.333333333 0.615840009 17 | 0.333333333 0.666666666 0.732790329 18 | 0.333333333 0.666666666 0.115840009 19 | 0.333333333 0.666666666 0.498371799 20 | 0.333333333 0.666666666 0.998371910 21 | -------------------------------------------------------------------------------- /ford.md: -------------------------------------------------------------------------------- 1 | project: 2 | summary: A Fortran library and executable for structure prediction at material interfaces 3 | src_dir: ./src/fortran 4 | ./app 5 | exclude: **/f90wrap_*.f90 6 | output_dir: docs/html 7 | preprocess: false 8 | predocmark: !! 9 | fpp_extensions: f90 10 | F90 11 | display: public 12 | protected 13 | private 14 | source: true 15 | graph: true 16 | md_extensions: markdown.extensions.toc 17 | coloured_edges: true 18 | sort: permission-alpha 19 | author: RAFFLE developers 20 | github: https://github.com/ExeQuantCode 21 | print_creation_date: true 22 | creation_date: %Y-%m-%d %H:%M %z 23 | project_github: https://github.com/ExeQuantCode/raffle 24 | project_download: https://github.com/ExeQuantCode/raffle/releases 25 | github: https://github.com/ExeQuantCode 26 | 27 | {!README.md!} -------------------------------------------------------------------------------- /example/python_pkg/visualisation/POSCAR_AABBCC_stack: -------------------------------------------------------------------------------- 1 | AABBCC vacuum 2 | 1.0 3 | 1.228133983 -2.127190457 0.000000000 4 | 1.228133983 2.127190457 0.000000000 5 | 0.000000000 0.000000000 21.520840786 6 | C 7 | 12 8 | direct 9 | 0.666666666 0.333333333 0.251933742 10 | 0.000000000 0.000000000 0.251941534 11 | 0.666666666 0.333333333 0.081391799 12 | 0.000000000 0.000000000 0.081399590 13 | 0.333333333 0.666666666 0.585267076 14 | 0.666666666 0.333333333 0.585274867 15 | 0.333333333 0.666666666 0.414725132 16 | 0.666666666 0.333333333 0.414732923 17 | 0.000000000 0.000000000 0.918600409 18 | 0.333333333 0.666666666 0.918608200 19 | 0.000000000 0.000000000 0.748058465 20 | 0.333333333 0.666666666 0.748066257 21 | -------------------------------------------------------------------------------- /tools/coverage_badge.py: -------------------------------------------------------------------------------- 1 | from bs4 import BeautifulSoup 2 | 3 | html_file = "./build/coverage/index.html" 4 | 5 | colour_dict = {'coverage-low':"red", 'coverage-medium':"yellow", 'coverage-high':"brightgreen"} 6 | 7 | with open(html_file, 'r') as file: 8 | soup = BeautifulSoup(file, 'html.parser') 9 | 10 | # Find the "coverage" table 11 | coverage_table = soup.find('table', {'class': 'coverage'}) 12 | 13 | # Find the second row of the "coverage" table 14 | second_row = coverage_table.find_all('tr')[1] 15 | 16 | # Find the third column of the second row 17 | third_column = second_row.find_all('td')[2] 18 | 19 | percentage = third_column.get_text() 20 | 21 | # Get the class of the element 22 | td_class = third_column.get('class')[0] 23 | 24 | print(int(float(percentage.replace("%", "")))) -------------------------------------------------------------------------------- /docs/source/about.rst: -------------------------------------------------------------------------------- 1 | .. _about: 2 | 3 | ===== 4 | About 5 | ===== 6 | 7 | 8 | RAFFLE (pseudoRandom Approach For Finding Local Energetic minima) is a package for structural prediction applied to material interfaces. 9 | RAFFLE can interface with the `Atomic Simulation Environment (ASE) `_. 10 | 11 | RAFFLE is both a Fortran and a Python library, with the option of a Fortran executable. 12 | The code heavily relies on features of Fortran 2018 and above, so there is no backwards compatibility with Fortran95. 13 | 14 | The library enables users to fill a host structure with additional atoms, where placement of those atoms is determined by a set of placement methods. 15 | These methods are meant to bias towards energetically favourable configurations, whilst still providing a thorough search of the configuration space. -------------------------------------------------------------------------------- /example/data/C-MgO_hosts/POSCAR_1x1_5.4A_separation: -------------------------------------------------------------------------------- 1 | c1 2 | 1.00000000000000 3 | 2.4639999866000002 0.0000000000000000 0.0000000000000000 4 | -1.2319999933000001 2.1338865833999998 0.0000000000000000 5 | 0.0000000000000000 0.0000000000000000 10.7109999657000001 6 | C 7 | 4 8 | Direct 9 | 0.0000000000000000 0.0000000000000000 0.2500000000000000 10 | 0.0000000000000000 0.0000000000000000 0.7499999819999985 11 | 0.3333333400000029 0.6666666830000025 0.2500000000000000 12 | 0.6666666570000004 0.3333333140000008 0.7499999819999985 13 | 14 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 15 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 16 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 17 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 18 | -------------------------------------------------------------------------------- /example/fortran_exe/param.in: -------------------------------------------------------------------------------- 1 | &setup 2 | task = 0, 3 | filename_host = "../data/C-MgO_hosts/POSCAR_MgO_HEX", 4 | database_format = "xyz" 5 | database = "./", 6 | seed = 1, 7 | grid_spacing = 0.05, 8 | verbose = 0, 9 | output_dir = "iteration1" 10 | / 11 | 12 | &placement_method 13 | void = 1.0, 14 | rand = 1.0, 15 | walk = 1.0, 16 | grow = 1.0, 17 | min = 1.0 18 | / 19 | 20 | &structure 21 | num_structures=10, 22 | stoichiometry="{Mg:8, O:8}", 23 | / 24 | 25 | &volume 26 | vdW=10, 27 | volvar=10 28 | / 29 | 30 | &distribution 31 | cutoff_min = 0.5 0.0 0.0, 32 | cutoff_max = 6.0 "pi" "pi", 33 | sigma = 0.5 0.1 0.1 34 | / 35 | 36 | &element_info 37 | energies = "{ 38 | C: -9.0266865, 39 | Mg: -1.5478236, 40 | O: -4.3707458 41 | }" 42 | bond_radii = "{ 43 | C-C: 1.54461, 44 | C-Mg: 2.3 45 | } 46 | / 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | \# 3 | bin/ 4 | obj/ 5 | *.mod 6 | *.smod 7 | *.so 8 | *.txt 9 | DTESTING/ 10 | DTEST/ 11 | build/ 12 | src/*.egg-info 13 | *.egg-info 14 | iteration* 15 | doc/html 16 | docs/html 17 | settings.json 18 | example/**/database*.xyz 19 | **/POSCAR* 20 | iteration/ 21 | *.traj 22 | *.png 23 | *.param 24 | fort.* 25 | *.o 26 | *.out 27 | *.dat 28 | *.err 29 | *.e 30 | *.log 31 | *.agr 32 | *.pdf 33 | *.eps 34 | *.pyc 35 | *.xyz 36 | .coverage 37 | *CAR 38 | *.pckl 39 | .DS_Store 40 | fortranobject.c* 41 | *.db 42 | CHG 43 | EIGENVAL 44 | IBZKPT 45 | KPOINTS 46 | PCDAT 47 | REPORT 48 | [0-9][0-9][0-9][0-9]_*.json 49 | vasprun.xml 50 | DVASP_MACE_comparison/ 51 | pca_model*.pkl 52 | .benchmarks/ 53 | .local-pre-commit-config.yaml 54 | *.tgz 55 | .ipynb_checkpoints 56 | *.model 57 | *.vasp 58 | *.pkl 59 | meta.json 60 | context.json 61 | options.json 62 | procedure.py 63 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the OS, Python version and other tools you might need 9 | build: 10 | os: ubuntu-22.04 11 | tools: 12 | python: "3.12" 13 | # You can also specify other tool versions: 14 | # nodejs: "19" 15 | # rust: "1.64" 16 | # golang: "1.19" 17 | 18 | # Build documentation in the "docs/" directory with Sphinx 19 | sphinx: 20 | configuration: docs/source/conf.py 21 | 22 | # Optionally build your docs in additional formats such as PDF and ePub 23 | # formats: 24 | # - pdf 25 | # - epub 26 | 27 | # Optional but recommended, declare the Python requirements required 28 | # to build your documentation 29 | # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html 30 | python: 31 | install: 32 | - requirements: docs/requirements.txt -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | message(STATUS "Building tests") 2 | foreach(execid 3 | misc 4 | misc_maths 5 | misc_linalg 6 | cache 7 | element_utils 8 | geom_rw 9 | geom_utils 10 | geom_extd 11 | dist_calcs 12 | place_methods 13 | viability 14 | distribs_container 15 | evaluator_C 16 | evaluator_BTO 17 | generator 18 | io_utils 19 | tools_infile 20 | ) 21 | add_executable(test_${execid} test_${execid}.f90) 22 | # Specify the include directories 23 | target_include_directories(test_${execid} PRIVATE "${CMAKE_BUILD_DIR}" "${CMAKE_BUILD_DIR}/mod") 24 | 25 | target_link_libraries(test_${execid} PRIVATE ${PROJECT_NAME}) 26 | 27 | # Link against OpenMP if the build type is Parallel 28 | if (CMAKE_BUILD_TYPE MATCHES "Parallel*") 29 | target_link_libraries(test_${execid} PRIVATE ${PROJECT_NAME} OpenMP::OpenMP_Fortran) 30 | endif() 31 | 32 | add_test(NAME test_${execid} COMMAND test_${execid}) 33 | endforeach() 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yaml: -------------------------------------------------------------------------------- 1 | name: Feature Proposal 2 | description: Suggest new functionality for RAFFLE 3 | title: "[PROPOSAL]" 4 | labels: [enhancement] 5 | body: 6 | - type: textarea 7 | id: reasoning 8 | attributes: 9 | label: Reasoning 10 | placeholder: | 11 | Provide clear reasoning why the proposed functionality should be added to the RAFFLE library. 12 | validations: 13 | required: true 14 | - type: textarea 15 | id: prior_art 16 | attributes: 17 | label: Prior Art 18 | placeholder: | 19 | Provide examples of where this has been implemented for machine learning before to help justify its presence in this library. 20 | validations: 21 | required: false 22 | - type: textarea 23 | id: additional 24 | attributes: 25 | label: Additional information 26 | placeholder: | 27 | Add any other context or screenshots about the feature request here. 28 | validations: 29 | required: false -------------------------------------------------------------------------------- /docs/RAFFLE.bib: -------------------------------------------------------------------------------- 1 | @article{Pitfield2024PredictingPhaseStability, 2 | title = {Predicting Phase Stability at Interfaces}, 3 | author = {Pitfield, J. and Taylor, N. T. and Hepplestone, S. P.}, 4 | journal = {Phys. Rev. Lett.}, 5 | volume = {132}, 6 | issue = {6}, 7 | pages = {066201}, 8 | numpages = {8}, 9 | year = {2024}, 10 | month = {Feb}, 11 | publisher = {American Physical Society}, 12 | doi = {10.1103/PhysRevLett.132.066201}, 13 | url = {https://link.aps.org/doi/10.1103/PhysRevLett.132.066201} 14 | } 15 | 16 | @article{Taylor2025RAFFLEActiveLearning, 17 | title = {RAFFLE: Active learning accelerated interface structure prediction}, 18 | author = {Taylor, Ned Thaddeus and Pitfield, Joe and Davies, Francis Huw and Hepplestone, Steven Paul}, 19 | year = {2025}, 20 | eprint={2504.02528}, 21 | archivePrefix={arXiv}, 22 | primaryClass={cond-mat.mtrl-sci}, 23 | doi = {10.48550/ARXIV.2504.02528}, 24 | url = {https://arxiv.org/abs/2504.02528}, 25 | publisher = {arXiv}, 26 | } 27 | -------------------------------------------------------------------------------- /example/data/C-MgO_hosts/POSCAR_2x2_5.4A_separation: -------------------------------------------------------------------------------- 1 | c1 2 | 1.000000000 3 | 4.927999973 0.000000000 0.000000000 4 | -2.463999987 4.267773167 0.000000000 5 | 0.000000000 0.000000000 10.710999966 6 | C 7 | 16 8 | Direct 9 | 0.000000000 0.000000000 0.250000000 10 | 0.500000000 0.000000000 0.250000000 11 | 0.000000000 0.500000000 0.250000000 12 | 0.500000000 0.500000000 0.250000000 13 | 0.000000000 0.000000000 0.749999982 14 | 0.500000000 0.000000000 0.749999982 15 | 0.000000000 0.500000000 0.749999982 16 | 0.500000000 0.500000000 0.749999982 17 | 0.166666670 0.333333342 0.250000000 18 | 0.666666670 0.333333342 0.250000000 19 | 0.166666670 0.833333342 0.250000000 20 | 0.666666670 0.833333342 0.250000000 21 | 0.333333329 0.166666657 0.749999982 22 | 0.833333329 0.166666657 0.749999982 23 | 0.333333329 0.666666657 0.749999982 24 | 0.833333329 0.666666657 0.749999982 25 | -------------------------------------------------------------------------------- /test/test_io_utils.f90: -------------------------------------------------------------------------------- 1 | program test_io_utils 2 | use raffle__io_utils 3 | implicit none 4 | 5 | ! Test variables 6 | logical :: success = .true. 7 | character(100) :: message 8 | 9 | ! Test stop_program subroutine 10 | test_error_handling = .true. 11 | message = "Test error message" 12 | call stop_program(message) 13 | 14 | ! Test print_warning subroutine 15 | call print_warning("This is a test warning message") 16 | 17 | ! Test print_version subroutine 18 | call print_version() 19 | 20 | ! Test print_build_info subroutine 21 | call print_build_info() 22 | 23 | !----------------------------------------------------------------------------- 24 | ! check for any failed tests 25 | !----------------------------------------------------------------------------- 26 | write(*,*) "----------------------------------------" 27 | if(success)then 28 | write(*,*) 'test_misc_linalg passed all tests' 29 | else 30 | write(0,*) 'test_misc_linalg failed one or more tests' 31 | stop 1 32 | end if 33 | 34 | end program test_io_utils -------------------------------------------------------------------------------- /docs/source/references.bib: -------------------------------------------------------------------------------- 1 | @article{Christiansen2022AtomisticGlobalOptimization, 2 | title = {Atomistic global optimization {X}: {A Python} package for optimization of atomistic structures}, 3 | volume = {157}, 4 | ISSN = {1089-7690}, 5 | url = {http://dx.doi.org/10.1063/5.0094165}, 6 | DOI = {10.1063/5.0094165}, 7 | number = {5}, 8 | journal = {The Journal of Chemical Physics}, 9 | publisher = {AIP Publishing}, 10 | author = {Christiansen, Mads-Peter V. and Rønne, Nikolaj and Hammer, Bjørk}, 11 | year = {2022}, 12 | month = aug 13 | } 14 | 15 | @article{Schusteritsch2014PredictingInterfaceStructures, 16 | title = {Predicting interface structures: From {SrTiO$_3$} to graphene}, 17 | volume = {90}, 18 | ISSN = {1550-235X}, 19 | url = {http://dx.doi.org/10.1103/PhysRevB.90.035424}, 20 | DOI = {10.1103/physrevb.90.035424}, 21 | number = {3}, 22 | journal = {Physical Review B}, 23 | publisher = {American Physical Society (APS)}, 24 | author = {Schusteritsch, Georg and Pickard, Chris J.}, 25 | year = {2014}, 26 | month = jul 27 | } 28 | -------------------------------------------------------------------------------- /docs/source/raffle.generator_module.rst: -------------------------------------------------------------------------------- 1 | raffle.generator Module 2 | ======================= 3 | 4 | This is a simulated module that holds the following class: 5 | 6 | - :class:`raffle.Generator()` 7 | 8 | This class cannot be directly accessed, but the two user-facing classes within it can be. 9 | Within this class, there exist two directly accessible sub-classes: 10 | 11 | - :class:`raffle.generator.stoichiometry_array()` 12 | - :class:`raffle.generator.raffle_generator()` 13 | 14 | The documentation for these can be found here: :doc:`raffle.generator_class`. 15 | 16 | Finally, the :class:`raffle.generator.raffle_generator()` contains instances of the following classes: 17 | 18 | - :class:`raffle.Raffle__Distribs_Container()` - raffle.generator.raffle_generator().distributions 19 | - :class:`raffle.Geom_Rw().basis()` - raffle.generator.raffle_generator().host 20 | - :class:`raffle.Geom_Rw().basis_arary()` - raffle.generator.raffle_generator().structures 21 | 22 | 23 | 24 | .. automodule:: raffle.generator 25 | :members: 26 | :undoc-members: 27 | :show-inheritance: 28 | -------------------------------------------------------------------------------- /example/python_pkg/graphite/POSCAR_host_graphene: -------------------------------------------------------------------------------- 1 | C4 2 | 1.000000000 3 | 3.700936892 -6.410210733 0.000000000 4 | 3.700936892 6.410210733 0.000000000 5 | 0.000000000 0.000000000 7.803073000 6 | C 7 | 18 8 | Direct 9 | 0.000000000 0.000000000 0.250000000 10 | 0.333333333 0.000000000 0.250000000 11 | 0.666666667 0.000000000 0.250000000 12 | 0.000000000 0.333333333 0.250000000 13 | 0.333333333 0.333333333 0.250000000 14 | 0.666666667 0.333333333 0.250000000 15 | 0.000000000 0.666666667 0.250000000 16 | 0.333333333 0.666666667 0.250000000 17 | 0.666666667 0.666666667 0.250000000 18 | 0.111111111 0.222222222 0.250000000 19 | 0.444444444 0.222222222 0.250000000 20 | 0.777777778 0.222222222 0.250000000 21 | 0.111111111 0.555555556 0.250000000 22 | 0.444444444 0.555555556 0.250000000 23 | 0.777777778 0.555555556 0.250000000 24 | 0.111111111 0.888888889 0.250000000 25 | 0.444444444 0.888888889 0.250000000 26 | 0.777777778 0.888888889 0.250000000 -------------------------------------------------------------------------------- /tools/version_number.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | def update_version(new_version): 4 | # Update fpm.toml 5 | with open('fpm.toml', 'r') as file: 6 | content = file.read() 7 | content = re.sub(r'version = "\d+\.\d+\.\d+.*"', f'version = "{new_version}"', content) 8 | with open('fpm.toml', 'w') as file: 9 | file.write(content) 10 | 11 | # Update Fortran module 12 | with open('src/fortran/lib/mod_io_utils.F90', 'r') as file: 13 | content = file.read() 14 | content = re.sub(r'character\(len=\*\), parameter :: raffle__version__ = "\d+\.\d+\.\d+.*"', f'character(len=*), parameter :: raffle__version__ = "{new_version}"', content) 15 | with open('src/fortran/lib/mod_io_utils.F90', 'w') as file: 16 | file.write(content) 17 | 18 | def get_version(): 19 | # get the version number from fpm.toml 20 | with open('fpm.toml', 'r') as file: 21 | content = file.read() 22 | match = re.search(r'version = "(\d+\.\d+\.\d+.*)"', content) 23 | print(match.group(1)) 24 | if match: 25 | return match.group(1) 26 | 27 | if __name__ == '__main__': 28 | update_version(get_version()) 29 | -------------------------------------------------------------------------------- /example/data/C-MgO_hosts/POSCAR_5x1_5.4A_separation: -------------------------------------------------------------------------------- 1 | c1 2 | 1.000000000 3 | 12.319999933 0.000000000 0.000000000 4 | -1.231999993 2.133886583 0.000000000 5 | 0.000000000 0.000000000 10.710999966 6 | C 7 | 20 8 | Direct 9 | 0.000000000 0.000000000 0.250000000 10 | 0.200000000 0.000000000 0.250000000 11 | 0.400000000 0.000000000 0.250000000 12 | 0.600000000 0.000000000 0.250000000 13 | 0.800000000 0.000000000 0.250000000 14 | 0.000000000 0.000000000 0.749999982 15 | 0.200000000 0.000000000 0.749999982 16 | 0.400000000 0.000000000 0.749999982 17 | 0.600000000 0.000000000 0.749999982 18 | 0.800000000 0.000000000 0.749999982 19 | 0.066666668 0.666666683 0.250000000 20 | 0.266666668 0.666666683 0.250000000 21 | 0.466666668 0.666666683 0.250000000 22 | 0.666666668 0.666666683 0.250000000 23 | 0.866666668 0.666666683 0.250000000 24 | 0.133333331 0.333333314 0.749999982 25 | 0.333333331 0.333333314 0.749999982 26 | 0.533333331 0.333333314 0.749999982 27 | 0.733333331 0.333333314 0.749999982 28 | 0.933333331 0.333333314 0.749999982 29 | -------------------------------------------------------------------------------- /src/fortran/lib/mod_cache.f90: -------------------------------------------------------------------------------- 1 | module raffle__cache 2 | use raffle__constants, only: real32 3 | implicit none 4 | 5 | private 6 | public :: store_probability_density, retrieve_probability_density 7 | 8 | real(real32), allocatable, dimension(:,:), save :: cached_probability_density 9 | 10 | contains 11 | 12 | subroutine store_probability_density(probability_density) 13 | implicit none 14 | real(real32), intent(in) :: probability_density(:,:) 15 | if (allocated(cached_probability_density)) & 16 | deallocate(cached_probability_density) 17 | allocate(cached_probability_density, source = probability_density) 18 | 19 | end subroutine store_probability_density 20 | 21 | function retrieve_probability_density() result(probability_density) 22 | implicit none 23 | real(real32), allocatable :: probability_density(:,:) 24 | if(.not.allocated(cached_probability_density)) then 25 | write(0,*) "Probability density not allocated. Returning zero array." 26 | allocate(probability_density(1,1), source = 0._real32) 27 | else 28 | allocate(probability_density, source = cached_probability_density) 29 | end if 30 | end function retrieve_probability_density 31 | 32 | end module raffle__cache 33 | -------------------------------------------------------------------------------- /example/python_pkg/agox_runs/n-body_run/tidy.py: -------------------------------------------------------------------------------- 1 | # This script tidies up the n-body database files by organizing them into subdirectories based on the number of bodies. 2 | # By running this script, then the following agox line in the command line: 3 | # agox analysis n-bodies/* 4 | # you will get analysis of the n-body successes split up by the number of contributing n-body distribution functions. 5 | 6 | import os 7 | import re 8 | import shutil 9 | from math import gcd 10 | from functools import reduce 11 | 12 | src_dir = "n-body" 13 | dst_base = "n-bodies" 14 | 15 | # Regex to match the filename pattern 16 | pattern = re.compile( 17 | r"^db(?P\d+)_dist_(?P[\d\.]+)\.db$" 18 | ) 19 | 20 | os.makedirs(dst_base, exist_ok=True) 21 | 22 | for fname in os.listdir(src_dir): 23 | match = pattern.match(fname) 24 | if match: 25 | parts = match.groupdict() 26 | subdir_name = f"{parts['nbody']}-body" 27 | fname_new = f"db{parts['seed']}.db" #_{subdir_name}.db" 28 | subdir_path = os.path.join(dst_base, subdir_name) 29 | os.makedirs(subdir_path, exist_ok=True) 30 | 31 | src_path = os.path.join(src_dir, fname) 32 | dst_path = os.path.join(subdir_path, fname_new) 33 | shutil.copy2(src_path, dst_path) 34 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | # This CITATION.cff file was generated with cffinit. 2 | # Visit https://bit.ly/cffinit to generate yours today! 3 | 4 | cff-version: 1.2.0 5 | title: >- 6 | RAFFLE: pseudoRandom Approach For Finding Local Energy 7 | minima 8 | message: >- 9 | If you use this software, please cite it using the 10 | metadata from this file and the following papers: 11 | https://link.aps.org/doi/10.1103/PhysRevLett.132.066201 12 | https://arxiv.org/abs/2504.02528 13 | type: software 14 | authors: 15 | - given-names: Ned Thaddeus 16 | family-names: Taylor 17 | orcid: 'https://orcid.org/0000-0002-9134-9712' 18 | affiliation: University of Exeter 19 | - given-names: Joe 20 | family-names: Pitfield 21 | orcid: 'https://orcid.org/0000-0002-9758-5230' 22 | affiliation: Aarhus Universitet 23 | - given-names: Steven Paul 24 | family-names: Hepplestone 25 | orcid: 'https://orcid.org/0000-0002-2528-1270' 26 | affiliation: University of Exeter 27 | repository-code: 'https://github.com/ExeQuantCode/RAFFLE' 28 | keywords: 29 | - materials science 30 | - interfaces 31 | - material interfaces 32 | - structure prediction 33 | - random structure search 34 | license: GPL-3.0 35 | commit: 1a4e7aacf07b4d9623d846df30aa7ac3a5e98e81 36 | version: 1.0.0 37 | date-released: '2025-03-03' 38 | -------------------------------------------------------------------------------- /docs/source/tutorials/index.rst: -------------------------------------------------------------------------------- 1 | .. tutorials: 2 | 3 | ========= 4 | Tutorials 5 | ========= 6 | 7 | Whilst RAFFLE is a random sturcture search package designed primarlily for interfaces, the tutorials will use bulk systems to demonstrate its functionality. 8 | 9 | .. note:: 10 | If you are looking for bulk random structure search, we recommend using packages such as `AIRSS `_, which are specifically designed for this purpose. 11 | They take advantage of symmetries prevalent in bulk structures to reduce the search space and improve efficiency. 12 | RAFFLE does not account for these symmetries, due to their usual absence in interfaces. 13 | 14 | .. toctree:: 15 | :maxdepth: 2 16 | :caption: Setup and parameters: 17 | 18 | databases_tutorial 19 | parameters_tutorial 20 | host_tutorial 21 | generating_tutorial 22 | quick_guide 23 | 24 | .. toctree:: 25 | :maxdepth: 2 26 | :caption: Static structure prediction: 27 | 28 | diamond_tutorial 29 | graphite_tutorial 30 | 31 | .. toctree:: 32 | :maxdepth: 2 33 | :caption: Iterative structure learning: 34 | 35 | aluminium_tutorial 36 | Si-Ge_tutorial 37 | graphene_grain_boundary_tutorial 38 | agox_tutorial 39 | 40 | .. toctree:: 41 | :maxdepth: 2 42 | :caption: Visualisation: 43 | 44 | visualisation 45 | -------------------------------------------------------------------------------- /docs/source/modules.rst: -------------------------------------------------------------------------------- 1 | raffle 2 | ====== 3 | 4 | .. Submodules 5 | .. ---------- 6 | 7 | .. raffle.raffle module 8 | .. -------------------- 9 | 10 | .. .. automodule:: raffle.raffle 11 | .. :members: 12 | .. :undoc-members: 13 | .. :show-inheritance: 14 | 15 | Module contents 16 | --------------- 17 | 18 | RAFFLE is a python package for performing structure prediction at interfaces. 19 | The package provides functionality for generating atomic structures by filling in host structures with additional atoms. 20 | The method involves iteratively generating structures and learning the energetically favourable features of the structures (see https://link.aps.org/doi/10.1103/PhysRevLett.132.066201). 21 | The package is built to accommodate energetic and structure data provided by the Atomic Simulation Environment (ASE) package (https://wiki.fysik.dtu.dk/ase/). 22 | 23 | Submodules 24 | ---------- 25 | 26 | .. toctree:: 27 | :maxdepth: 2 28 | 29 | raffle.generator_module 30 | raffle.geom_module 31 | 32 | Classes 33 | ------- 34 | 35 | These are the main classes of the package (they are only indirectly accessible): 36 | 37 | .. toctree:: 38 | :maxdepth: 2 39 | 40 | raffle.generator_class 41 | raffle.geom_rw_class 42 | raffle.distributions_class 43 | 44 | .. .. automodule:: raffle 45 | .. :members: 46 | .. :undoc-members: 47 | .. :show-inheritance: 48 | -------------------------------------------------------------------------------- /example/python_pkg/visualisation/POSCAR_ABAB_stack: -------------------------------------------------------------------------------- 1 | ABAB vacuum 2 | 1.0 3 | 1.227975709 -2.126916320 0.000000000 4 | 1.227975709 2.126916320 0.000000000 5 | 0.000000000 0.000000000 54.715156838 6 | C 7 | 24 8 | direct 9 | 0.000000000 0.000000000 0.031579449 10 | 0.666666666 0.333333333 0.238822903 11 | 0.666666666 0.333333333 0.094505113 12 | 0.000000000 0.000000000 0.094510430 13 | 0.666666666 0.333333333 0.301753883 14 | 0.333333333 0.666666666 0.031587736 15 | 0.000000000 0.000000000 0.238828220 16 | 0.333333333 0.666666666 0.301745596 17 | 0.666666666 0.333333333 0.364912783 18 | 0.333333333 0.666666666 0.572156236 19 | 0.333333333 0.666666666 0.427838446 20 | 0.666666666 0.333333333 0.427843763 21 | 0.333333333 0.666666666 0.635087216 22 | 0.000000000 0.000000000 0.364921069 23 | 0.666666666 0.333333333 0.572161553 24 | 0.000000000 0.000000000 0.635078930 25 | 0.333333333 0.666666666 0.698246116 26 | 0.000000000 0.000000000 0.905489569 27 | 0.000000000 0.000000000 0.761171779 28 | 0.333333333 0.666666666 0.761177096 29 | 0.000000000 0.000000000 0.968420550 30 | 0.666666666 0.333333333 0.698254403 31 | 0.333333333 0.666666666 0.905494886 32 | 0.666666666 0.333333333 0.968412263 33 | -------------------------------------------------------------------------------- /example/python_pkg/perovskites/database.xyz: -------------------------------------------------------------------------------- 1 | 5 2 | Lattice="3.93796462 0.0 0.0 0.0 3.93796462 0.0 0.0 0.0 3.93891698" Properties=species:S:1:pos:R:3:forces:R:3 energy=-40.12032428 stress="-0.0008424844130642804 -0.0 -0.0 -0.0 -0.0008424844130642804 0.0 -0.0 0.0 -0.000512511616596921" free_energy=-40.12032428 pbc="T T T" 3 | Sr 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 4 | Ti 1.96898231 1.96898231 1.96945849 0.00000000 0.00000000 0.00000000 5 | O 0.00000000 1.96898231 1.96945849 0.00000000 0.00000000 0.00000000 6 | O 1.96898231 0.00000000 1.96945849 0.00000000 0.00000000 0.00000000 7 | O 1.96898231 1.96898231 0.00000000 0.00000000 0.00000000 0.00000000 8 | 5 9 | Lattice="4.03084376 0.0 0.0 0.0 4.03084376 0.0 0.0 0.0 4.03254345" Properties=species:S:1:pos:R:3:forces:R:3 energy=-40.00295673 stress="-0.0002488092354018701 -0.0 -0.0 -0.0 -0.0002488092354018701 0.0 -0.0 0.0 0.0002890913610814811" free_energy=-40.00295673 pbc="T T T" 10 | Ba 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 11 | Ti 2.01542188 2.01542188 2.01627173 0.00000000 0.00000000 0.00000000 12 | O 2.01542188 0.00000000 2.01627173 0.00000000 0.00000000 0.00000000 13 | O 0.00000000 2.01542188 2.01627173 0.00000000 0.00000000 0.00000000 14 | O 2.01542188 2.01542188 0.00000000 0.00000000 0.00000000 0.00000000 15 | -------------------------------------------------------------------------------- /src/raffle/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | raffle package 3 | 4 | This package provides functionality to interface with a Fortran library, 5 | including a Python wrapper around the Fortran code. 6 | """ 7 | 8 | from importlib.metadata import PackageNotFoundError, version 9 | try: 10 | __version__ = version(__name__) 11 | except PackageNotFoundError: 12 | __version__ = "unknown" 13 | 14 | from .raffle import generator as _generator_class 15 | from .raffle import geom_rw as _geom_rw_class 16 | # from .raffle import generator 17 | 18 | 19 | # Use the 'types' module to create simulated 'generator' and 'geom submodules 20 | import types 21 | generator = types.ModuleType('generator') 22 | geom = types.ModuleType('geom') 23 | 24 | # Assign the respective class to the simulated 'generator' and 'geom' modules 25 | generator.raffle_generator = _generator_class.raffle_generator 26 | generator.stoichiometry_array = _generator_class.stoichiometry_array 27 | 28 | # Assign the class to the simulated 'geom' module 29 | geom.basis_array = _geom_rw_class.basis_array 30 | geom.basis = _geom_rw_class.basis 31 | 32 | 33 | # Add the simulated 'generator' and 'geom' module to the current package 34 | import sys 35 | sys.modules['raffle.generator'] = generator 36 | sys.modules['raffle.geom'] = geom 37 | 38 | # Clean up internal imports (remove access to the direct classes) 39 | del _generator_class 40 | del _geom_rw_class 41 | del PackageNotFoundError 42 | del version 43 | del sys 44 | del types 45 | del raffle 46 | 47 | __all__ = ['__version__', 'generator', 'geom'] 48 | 49 | def __getattr__(name): 50 | if name == "generator": 51 | return generator 52 | elif name == "geom": 53 | return geom 54 | raise AttributeError(f"module {__name__} has no attribute {name}") -------------------------------------------------------------------------------- /example/python_pkg/agox_runs/Si-Ge_run/tidy.py: -------------------------------------------------------------------------------- 1 | # This script tidies up the n-body database files by organizing them into subdirectories based on the number of bodies. 2 | # By running this script, then the following agox line in the command line: 3 | # agox analysis method_ratios/* 4 | # you will get analysis of the success split up by the method ratios used in the generation of the structures. 5 | 6 | import os 7 | import re 8 | import shutil 9 | from math import gcd 10 | from functools import reduce 11 | 12 | src_dir = "method_ratio" 13 | dst_base = "method_ratios" 14 | 15 | # Regex to match the filename pattern 16 | pattern = re.compile( 17 | r"^db(?P\d+)_dist_grow(?P[\d\.]+)_min(?P[\d\.]+)_rand(?P[\d\.]+)_void(?P[\d\.]+)_walk(?P[\d\.]+)\.db$" 18 | ) 19 | 20 | def float_str_to_int_ratios(values): 21 | # Convert all to floats 22 | floats = [float(v) for v in values] 23 | scale = 1000 # To avoid float precision issues 24 | ints = [round(f * scale) for f in floats] 25 | divisor = reduce(gcd, ints) 26 | return [i // divisor for i in ints] 27 | 28 | os.makedirs(dst_base, exist_ok=True) 29 | 30 | for fname in os.listdir(src_dir): 31 | match = pattern.match(fname) 32 | if match: 33 | parts = match.groupdict() 34 | ratios = float_str_to_int_ratios([ 35 | parts["void"], parts["rand"], parts["walk"], parts["grow"], parts["min"] 36 | ]) 37 | # Assign to the appropriate method 38 | v, r, w, g, m = ratios 39 | # exit() 40 | subdir_name = f"v{v}_r{r}_w{w}_g{g}_m{m}" 41 | fname_new = f"db{parts['seed']}.db" #_{subdir_name}.db" 42 | subdir_path = os.path.join(dst_base, subdir_name) 43 | os.makedirs(subdir_path, exist_ok=True) 44 | 45 | src_path = os.path.join(src_dir, fname) 46 | dst_path = os.path.join(subdir_path, fname_new) 47 | shutil.copy2(src_path, dst_path) 48 | -------------------------------------------------------------------------------- /example/python_pkg/agox_runs/graphene_grain_boundary_run/tidy.py: -------------------------------------------------------------------------------- 1 | # This script tidies up the n-body database files by organizing them into subdirectories based on the number of bodies. 2 | # By running this script, then the following agox line in the command line: 3 | # agox analysis method_ratios/* 4 | # you will get analysis of the success split up by the method ratios used in the generation of the structures. 5 | 6 | import os 7 | import re 8 | import shutil 9 | from math import gcd 10 | from functools import reduce 11 | 12 | src_dir = "method_ratio" 13 | dst_base = "method_ratios" 14 | 15 | # Regex to match the filename pattern 16 | pattern = re.compile( 17 | r"^db(?P\d+)_grow(?P[\d\.]+)_min(?P[\d\.]+)_rand(?P[\d\.]+)_void(?P[\d\.]+)_walk(?P[\d\.]+)\.db$" 18 | ) 19 | 20 | def float_str_to_int_ratios(values): 21 | # Convert all to floats 22 | floats = [float(v) for v in values] 23 | scale = 1000 # To avoid float precision issues 24 | ints = [round(f * scale) for f in floats] 25 | divisor = reduce(gcd, ints) 26 | return [i // divisor for i in ints] 27 | 28 | os.makedirs(dst_base, exist_ok=True) 29 | 30 | for fname in os.listdir(src_dir): 31 | match = pattern.match(fname) 32 | if match: 33 | parts = match.groupdict() 34 | ratios = float_str_to_int_ratios([ 35 | parts["void"], parts["rand"], parts["walk"], parts["grow"], parts["min"] 36 | ]) 37 | # Assign to the appropriate method 38 | v, r, w, g, m = ratios 39 | # exit() 40 | subdir_name = f"v{v}_r{r}_w{w}_g{g}_m{m}" 41 | fname_new = f"db{parts['seed']}.db" #_{subdir_name}.db" 42 | subdir_path = os.path.join(dst_base, subdir_name) 43 | os.makedirs(subdir_path, exist_ok=True) 44 | 45 | src_path = os.path.join(src_dir, fname) 46 | dst_path = os.path.join(subdir_path, fname_new) 47 | shutil.copy2(src_path, dst_path) 48 | -------------------------------------------------------------------------------- /tools/check_accuracy_C-MgO.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | 4 | # import ASE (Atomic Simulation Environment) modules 5 | from ase import Atoms 6 | from ase.io import read, write 7 | 8 | 9 | ## load calculator 10 | calculator = "CHGNet" 11 | match calculator: 12 | case "CHGNet": 13 | from chgnet.model.dynamics import CHGNetCalculator 14 | print("Initialising CHGNet calculator") 15 | calc = CHGNetCalculator() 16 | label = "CHGNet" 17 | case "MACE": 18 | from mace.calculators import mace_mp 19 | print("Initialising MACE calculator") 20 | calc = mace_mp(model="medium", dispersion=False, default_dtype="float32", device='cpu') 21 | label = "MACE" 22 | 23 | ## Read the database 24 | print("Reading database") 25 | database = read("../example/data/C-MgO.xyz", index=":") 26 | 27 | ## Calculate the energies 28 | energies_dft = [] 29 | energies_mlp = [] 30 | for i, atoms in enumerate(database): 31 | if atoms.calc is None: 32 | database.remove(atoms) 33 | continue 34 | energies_dft.append(atoms.get_potential_energy()/len(atoms)) 35 | atoms.calc = calc 36 | energies_mlp.append(atoms.get_potential_energy()/len(atoms)) 37 | # if energies_mlp[-1] - energies_dft[-1] > 3e-1 and energies_mlp[-1] < -7.9: 38 | # print(f"Energy difference for structure {i} is {energies_mlp[-1] - energies_dft[-1]}, energy_mace: {energies_mlp[-1]}") 39 | # view(atoms) 40 | 41 | 42 | import matplotlib.pyplot as plt 43 | 44 | ## Write energies to a file 45 | with open("C-MgO_energies_comparison.txt", "w") as f: 46 | f.write("# DFT_Energy_per_atom "+label+"_Energy_per_atom\n") 47 | for dft_energy, mace_energy in zip(energies_dft, energies_mlp): 48 | f.write(f"{dft_energy} {mace_energy}\n") 49 | 50 | # Plotting the energies 51 | plt.figure(figsize=(10, 6)) 52 | plt.scatter(energies_dft, energies_mlp, c='blue', marker='o', label=label+' vs DFT') 53 | plt.show() -------------------------------------------------------------------------------- /example/python_pkg/graphite/POSCAR_host_graphite_vacancy: -------------------------------------------------------------------------------- 1 | C4 2 | 1.000000000 3 | 3.700936892 -6.410210733 0.000000000 4 | 3.700936892 6.410210733 0.000000000 5 | 0.000000000 0.000000000 7.803073000 6 | C 7 | 35 8 | Direct 9 | 0.000000000 0.000000000 0.250000000 10 | 0.333333333 0.000000000 0.250000000 11 | 0.666666667 0.000000000 0.250000000 12 | 0.000000000 0.333333333 0.250000000 13 | 0.333333333 0.333333333 0.250000000 14 | 0.666666667 0.333333333 0.250000000 15 | 0.000000000 0.666666667 0.250000000 16 | 0.333333333 0.666666667 0.250000000 17 | 0.666666667 0.666666667 0.250000000 18 | 0.000000000 0.000000000 0.750000000 19 | 0.333333333 0.000000000 0.750000000 20 | 0.666666667 0.000000000 0.750000000 21 | 0.000000000 0.333333333 0.750000000 22 | 0.333333333 0.333333333 0.750000000 23 | 0.666666667 0.333333333 0.750000000 24 | 0.000000000 0.666666667 0.750000000 25 | 0.333333333 0.666666667 0.750000000 26 | 0.666666667 0.666666667 0.750000000 27 | 0.111111111 0.222222222 0.250000000 28 | 0.444444444 0.222222222 0.250000000 29 | 0.777777778 0.222222222 0.250000000 30 | 0.111111111 0.555555556 0.250000000 31 | 0.444444444 0.555555556 0.250000000 32 | 0.777777778 0.555555556 0.250000000 33 | 0.111111111 0.888888889 0.250000000 34 | 0.444444444 0.888888889 0.250000000 35 | 0.777777778 0.888888889 0.250000000 36 | 0.222222222 0.111111111 0.750000000 37 | 0.555555556 0.111111111 0.750000000 38 | 0.888888889 0.111111111 0.750000000 39 | 0.222222222 0.444444444 0.750000000 40 | 0.555555556 0.444444444 0.750000000 41 | 0.888888889 0.444444444 0.750000000 42 | 0.222222222 0.777777778 0.750000000 43 | 0.555555556 0.777777778 0.750000000 44 | 45 | -------------------------------------------------------------------------------- /example/data/C-MgO_hosts/POSCAR_3x3_11.0A_separation: -------------------------------------------------------------------------------- 1 | c1 2 | 1.000000000 3 | 7.391999960 0.000000000 0.000000000 4 | -3.695999980 6.401659750 0.000000000 5 | 0.000000000 0.000000000 14.710999966 6 | C 7 | 36 8 | Direct 9 | 0.000000000 0.000000000 0.000000000 10 | 0.333333333 0.000000000 0.000000000 11 | 0.666666667 0.000000000 0.000000000 12 | 0.000000000 0.333333333 0.000000000 13 | 0.333333333 0.333333333 0.000000000 14 | 0.666666667 0.333333333 0.000000000 15 | 0.000000000 0.666666667 0.000000000 16 | 0.333333333 0.666666667 0.000000000 17 | 0.666666667 0.666666667 0.000000000 18 | 0.000000000 0.000000000 0.749999982 19 | 0.333333333 0.000000000 0.749999982 20 | 0.666666667 0.000000000 0.749999982 21 | 0.000000000 0.333333333 0.749999982 22 | 0.333333333 0.333333333 0.749999982 23 | 0.666666667 0.333333333 0.749999982 24 | 0.000000000 0.666666667 0.749999982 25 | 0.333333333 0.666666667 0.749999982 26 | 0.666666667 0.666666667 0.749999982 27 | 0.111111113 0.222222228 0.000000000 28 | 0.444444447 0.222222228 0.000000000 29 | 0.777777780 0.222222228 0.000000000 30 | 0.111111113 0.555555561 0.000000000 31 | 0.444444447 0.555555561 0.000000000 32 | 0.777777780 0.555555561 0.000000000 33 | 0.111111113 0.888888894 0.000000000 34 | 0.444444447 0.888888894 0.000000000 35 | 0.777777780 0.888888894 0.000000000 36 | 0.222222219 0.111111105 0.749999982 37 | 0.555555552 0.111111105 0.749999982 38 | 0.888888886 0.111111105 0.749999982 39 | 0.222222219 0.444444438 0.749999982 40 | 0.555555552 0.444444438 0.749999982 41 | 0.888888886 0.444444438 0.749999982 42 | 0.222222219 0.777777771 0.749999982 43 | 0.555555552 0.777777771 0.749999982 44 | 0.888888886 0.777777771 0.749999982 45 | -------------------------------------------------------------------------------- /example/data/C-MgO_hosts/POSCAR_3x3_5.4A_separation: -------------------------------------------------------------------------------- 1 | c1 2 | 1.000000000 3 | 7.391999960 0.000000000 0.000000000 4 | -3.695999980 6.401659750 0.000000000 5 | 0.000000000 0.000000000 10.710999966 6 | C 7 | 36 8 | Direct 9 | 0.000000000 0.000000000 0.250000000 10 | 0.333333333 0.000000000 0.250000000 11 | 0.666666667 0.000000000 0.250000000 12 | 0.000000000 0.333333333 0.250000000 13 | 0.333333333 0.333333333 0.250000000 14 | 0.666666667 0.333333333 0.250000000 15 | 0.000000000 0.666666667 0.250000000 16 | 0.333333333 0.666666667 0.250000000 17 | 0.666666667 0.666666667 0.250000000 18 | 0.000000000 0.000000000 0.749999982 19 | 0.333333333 0.000000000 0.749999982 20 | 0.666666667 0.000000000 0.749999982 21 | 0.000000000 0.333333333 0.749999982 22 | 0.333333333 0.333333333 0.749999982 23 | 0.666666667 0.333333333 0.749999982 24 | 0.000000000 0.666666667 0.749999982 25 | 0.333333333 0.666666667 0.749999982 26 | 0.666666667 0.666666667 0.749999982 27 | 0.111111113 0.222222228 0.250000000 28 | 0.444444447 0.222222228 0.250000000 29 | 0.777777780 0.222222228 0.250000000 30 | 0.111111113 0.555555561 0.250000000 31 | 0.444444447 0.555555561 0.250000000 32 | 0.777777780 0.555555561 0.250000000 33 | 0.111111113 0.888888894 0.250000000 34 | 0.444444447 0.888888894 0.250000000 35 | 0.777777780 0.888888894 0.250000000 36 | 0.222222219 0.111111105 0.749999982 37 | 0.555555552 0.111111105 0.749999982 38 | 0.888888886 0.111111105 0.749999982 39 | 0.222222219 0.444444438 0.749999982 40 | 0.555555552 0.444444438 0.749999982 41 | 0.888888886 0.444444438 0.749999982 42 | 0.222222219 0.777777771 0.749999982 43 | 0.555555552 0.777777771 0.749999982 44 | 0.888888886 0.777777771 0.749999982 45 | -------------------------------------------------------------------------------- /example/data/C-MgO_hosts/POSCAR_1x5_orthorhombic_11.0A_separation: -------------------------------------------------------------------------------- 1 | c1+mg1 o1 2 | 1.000000000 3 | 4.267773167 0.000000000 0.000000000 4 | -0.000000000 12.319999933 0.000000000 5 | 0.000000000 0.000000000 14.398580001 6 | C 7 | 40 8 | Direct 9 | 0.000000000 0.000000000 0.000000000 10 | 0.000000000 0.200000000 0.000000000 11 | 0.000000000 0.400000000 0.000000000 12 | 0.000000000 0.600000000 0.000000000 13 | 0.000000000 0.800000000 0.000000000 14 | 0.500000000 0.100000000 0.000000000 15 | 0.500000000 0.300000000 0.000000000 16 | 0.500000000 0.500000000 0.000000000 17 | 0.500000000 0.700000000 0.000000000 18 | 0.500000000 0.900000000 0.000000000 19 | 0.000000000 0.000000000 0.766956196 20 | 0.000000000 0.200000000 0.766956196 21 | 0.000000000 0.400000000 0.766956196 22 | 0.000000000 0.600000000 0.766956196 23 | 0.000000000 0.800000000 0.766956196 24 | 0.500000000 0.100000000 0.766956196 25 | 0.500000000 0.300000000 0.766956196 26 | 0.500000000 0.500000000 0.766956196 27 | 0.500000000 0.700000000 0.766956196 28 | 0.500000000 0.900000000 0.766956196 29 | 0.333333342 1.000000000 0.000000000 30 | 0.333333342 0.200000000 0.000000000 31 | 0.333333342 0.400000000 0.000000000 32 | 0.333333342 0.600000000 0.000000000 33 | 0.333333342 0.800000000 0.000000000 34 | 0.833333342 0.100000000 0.000000000 35 | 0.833333342 0.300000000 0.000000000 36 | 0.833333342 0.500000000 0.000000000 37 | 0.833333342 0.700000000 0.000000000 38 | 0.833333342 0.900000000 0.000000000 39 | 0.166666657 0.100000000 0.766956196 40 | 0.166666657 0.300000000 0.766956196 41 | 0.166666657 0.500000000 0.766956196 42 | 0.166666657 0.700000000 0.766956196 43 | 0.166666657 0.900000000 0.766956196 44 | 0.666666657 0.000000000 0.766956196 45 | 0.666666657 0.200000000 0.766956196 46 | 0.666666657 0.400000000 0.766956196 47 | 0.666666657 0.600000000 0.766956196 48 | 0.666666657 0.800000000 0.766956196 -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yaml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: Something is not working 3 | title: "[BUG]" 4 | labels: [bug] 5 | body: 6 | - type: textarea 7 | id: description 8 | attributes: 9 | label: Description 10 | placeholder: | 11 | A clear and concise description of what the bug is and what the expected behaviour is. 12 | validations: 13 | required: true 14 | - type: textarea 15 | id: reproduction 16 | attributes: 17 | label: Reproduction steps 18 | description: "How do you trigger this bug? If possible, please provide a minimal reproducible example." 19 | placeholder: | 20 | Does the library compile? Is there an issue with a unit test or example? Or is the bug encountered when calling the library? If possible, provide a step-by-step guide: 21 | 1. 22 | 2. 23 | 3. 24 | validations: 25 | required: true 26 | - type: input 27 | id: version 28 | attributes: 29 | label: Version number 30 | description: "What was the latest version (or branch) of RAFFLE is the bug reproducible in?" 31 | placeholder: 1.0.0 32 | validations: 33 | required: true 34 | - type: input 35 | id: compiler 36 | attributes: 37 | label: Fortran compiler 38 | description: "What Fortran compiler (and version) was used?" 39 | placeholder: gfortran version 14.0 40 | validations: 41 | required: true 42 | - type: input 43 | id: platform 44 | attributes: 45 | label: Platform and Architecture 46 | description: "What architecture and operating system was the bug encountered on?" 47 | placeholder: macOS/ARM 10.14 48 | validations: 49 | required: true 50 | - type: checkboxes 51 | id: build 52 | attributes: 53 | label: Build method 54 | description: "What build methods was this issue encountered with?" 55 | options: 56 | - label: fpm 57 | - label: cmake 58 | - label: pip 59 | - type: textarea 60 | id: additional 61 | attributes: 62 | label: Additional information 63 | placeholder: Any further relevant context, i.e. screenshots, links to other issues, version number of build method. 64 | validations: 65 | required: false -------------------------------------------------------------------------------- /tools/database.py: -------------------------------------------------------------------------------- 1 | # %% 2 | #Imports MPRester 3 | # from mp_api.client import MPRester 4 | from ase import Atoms 5 | from ase.io import write, read 6 | from pymatgen.io.ase import AseAtomsAdaptor 7 | from mp_api.client import MPRester 8 | 9 | 10 | # %% 11 | # Personal api key for accessing materials project api 12 | # This is unique to each user 13 | # api_key = "" 14 | 15 | # %% 16 | #Gets the ID of materials we want. Ba is all structures with only Ba. Ba-O is all structures with only Ba and O, not only BaO. 17 | 18 | mpr = MPRester() # MPRester(api_key) 19 | materials = [] 20 | 21 | materials.append(mpr.materials.summary.search(chemsys="C", 22 | fields=["material_id","structure", "energy_per_atom", "nsites"])) 23 | materials.append(mpr.materials.summary.search(chemsys="Mg", 24 | fields=["material_id","structure", "energy_per_atom", "nsites"])) 25 | materials.append(mpr.materials.summary.search(chemsys="O", 26 | fields=["material_id","structure", "energy_per_atom", "nsites"])) 27 | materials.append(mpr.materials.summary.search(chemsys="C-Mg", 28 | fields=["material_id","structure", "energy_per_atom", "nsites"])) 29 | materials.append(mpr.materials.summary.search(chemsys="C-O", 30 | fields=["material_id","structure", "energy_per_atom", "nsites"])) 31 | materials.append(mpr.materials.summary.search(chemsys="Mg-O", 32 | fields=["material_id","structure", "energy_per_atom", "nsites"])) 33 | 34 | 35 | # %% 36 | structures = [] 37 | energies = [] 38 | nsites = [] 39 | for material_set in materials: 40 | for material in material_set: 41 | material_id = material.material_id 42 | structures.append(mpr.get_structure_by_material_id(material_id)) 43 | energies.append(material.energy_per_atom) 44 | nsites.append(material.nsites) 45 | 46 | # %% 47 | all_atoms = [] 48 | for structure, energy, nsite in zip(structures, energies, nsites): 49 | atom = AseAtomsAdaptor.get_atoms(structure) 50 | atom.info['free_energy'] = energy * nsite 51 | atom.info['energy'] = energy * nsite 52 | all_atoms.append(atom) 53 | write("database.xyz", all_atoms, format='extxyz') 54 | 55 | # %% 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /tools/visualise_evaluator.py: -------------------------------------------------------------------------------- 1 | from mpl_toolkits.mplot3d import Axes3D 2 | from mpl_toolkits.mplot3d import proj3d 3 | import numpy as np 4 | 5 | import matplotlib.pyplot as plt 6 | 7 | # Read the data from the file 8 | data = [] 9 | atoms = [] 10 | with open('viability.dat', 'r') as file: 11 | for line in file: 12 | values = line.strip().split() 13 | if len(values) == 3: 14 | atoms.append([float(values[0]), float(values[1]), float(values[2])]) 15 | 16 | if len(values) == 4: 17 | data.append([float(values[0]), float(values[1]), float(values[2]), float(values[3])]) 18 | 19 | # Drop all rows with row[3] less than 0.2 20 | # data = [row for row in data if row[3] > 0.4] # for 4-body only 21 | max_val = max([row[3] for row in data]) 22 | avg_val = sum([row[3] for row in data])/len(data) 23 | print(f"Max value: {max_val}") 24 | print(f"Avg value: {avg_val}") 25 | 26 | # Extract the coordinates and values 27 | x = [row[0] for row in data] 28 | y = [row[1] for row in data] 29 | z = [row[2] for row in data] 30 | # alpha = [row[3] for row in data] 31 | alpha = [(row[3]*100)*2 for row in data] 32 | alpha = [val/max(alpha) for val in alpha] 33 | # size = [(row[3]*10)**3 for row in data] # for 2-body only 34 | # size = [(row[3]*100)*2 for row in data] # for 2-body and 3-body 35 | # size = [row[3] for row in data] # for 4-body only 36 | # size = [(row[3]*2000) for row in data] # for all 37 | size = [(row[3]*1000) for row in data] # for all 38 | 39 | # Extract the atom coordinates 40 | atoms_x = [row[0] for row in atoms] 41 | atoms_y = [row[1] for row in atoms] 42 | atoms_z = [row[2] for row in atoms] 43 | 44 | # Plot the data on a 3D graph 45 | fig = plt.figure() 46 | ax = fig.add_subplot(111, projection='3d') 47 | 48 | x_scale=max(x)-min(x) 49 | y_scale=max(y)-min(y) 50 | z_scale=max(z)-min(z) 51 | 52 | scale=np.diag([x_scale, y_scale, z_scale, 1.0]) 53 | scale=scale*(1.0/scale.max()) 54 | scale[3,3]=1.0 55 | 56 | def short_proj(): 57 | return np.dot(Axes3D.get_proj(ax), scale) 58 | 59 | ax.get_proj=short_proj 60 | ax.mouse_init() 61 | 62 | 63 | ax.scatter(atoms_x, atoms_y, atoms_z, c='red', alpha=1.0, s=200) 64 | 65 | # ax.scatter(x, y, z, alpha=alpha, c='black', s=size) 66 | ax.scatter(x, y, z, c=alpha, cmap='viridis', s=size) 67 | ax.set_xlabel('X') 68 | ax.set_ylabel('Y') 69 | ax.set_zlabel('Z') 70 | plt.show() 71 | -------------------------------------------------------------------------------- /example/data/C-MgO_hosts/POSCAR_orthorhombic_11.1A_separation_Mg_seeded: -------------------------------------------------------------------------------- 1 | c1+mg1 o1 2 | 1.000000000 3 | 4.267773167 0.000000000 0.000000000 4 | -0.000000000 12.319999933 0.000000000 5 | 0.000000000 0.000000000 14.398580001 6 | C Mg 7 | 40 2 8 | Direct 9 | 0.000000000 0.000000000 0.000000000 10 | 0.000000000 0.200000000 0.000000000 11 | 0.000000000 0.400000000 0.000000000 12 | 0.000000000 0.600000000 0.000000000 13 | 0.000000000 0.800000000 0.000000000 14 | 0.500000000 0.100000000 0.000000000 15 | 0.500000000 0.300000000 0.000000000 16 | 0.500000000 0.500000000 0.000000000 17 | 0.500000000 0.700000000 0.000000000 18 | 0.500000000 0.900000000 0.000000000 19 | 0.000000000 0.000000000 0.766956196 20 | 0.000000000 0.200000000 0.766956196 21 | 0.000000000 0.400000000 0.766956196 22 | 0.000000000 0.600000000 0.766956196 23 | 0.000000000 0.800000000 0.766956196 24 | 0.500000000 0.100000000 0.766956196 25 | 0.500000000 0.300000000 0.766956196 26 | 0.500000000 0.500000000 0.766956196 27 | 0.500000000 0.700000000 0.766956196 28 | 0.500000000 0.900000000 0.766956196 29 | 0.333333342 1.000000000 0.000000000 30 | 0.333333342 0.200000000 0.000000000 31 | 0.333333342 0.400000000 0.000000000 32 | 0.333333342 0.600000000 0.000000000 33 | 0.333333342 0.800000000 0.000000000 34 | 0.833333342 0.100000000 0.000000000 35 | 0.833333342 0.300000000 0.000000000 36 | 0.833333342 0.500000000 0.000000000 37 | 0.833333342 0.700000000 0.000000000 38 | 0.833333342 0.900000000 0.000000000 39 | 0.166666657 0.100000000 0.766956196 40 | 0.166666657 0.300000000 0.766956196 41 | 0.166666657 0.500000000 0.766956196 42 | 0.166666657 0.700000000 0.766956196 43 | 0.166666657 0.900000000 0.766956196 44 | 0.666666657 0.000000000 0.766956196 45 | 0.666666657 0.200000000 0.766956196 46 | 0.666666657 0.400000000 0.766956196 47 | 0.666666657 0.600000000 0.766956196 48 | 0.666666657 0.800000000 0.766956196 49 | 0.500000000 0.500000000 0.384000000 50 | 0.500000000 0.250000000 0.192000000 -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "f90wrap>=0.2.14,<=0.2.16", 4 | "numpy>=1.26.4,<=2.2", 5 | "meson~=1.6.0", 6 | "cython~=3.0.11", 7 | "scikit-build-core", 8 | ] 9 | build-backend = "scikit_build_core.build" 10 | 11 | [tool.scikit-build] 12 | cmake.version = "CMakeLists.txt" 13 | ninja.version = ">=1.10" 14 | cmake.build-type = "Release" 15 | cmake.source-dir = "." 16 | cmake.args = [ 17 | "-DBUILD_PYTHON=On", 18 | "-DBUILD_EXECUTABLE=Off", 19 | "-DREMAKE_F90WRAP=Off", 20 | ] 21 | sdist.cmake = true 22 | wheel.cmake = true 23 | build-dir="build/{wheel_tag}" 24 | wheel.expand-macos-universal-tags = true 25 | ninja.make-fallback = true 26 | sdist.reproducible = true 27 | # dev purposes only 28 | build.verbose = false 29 | 30 | [project] 31 | name = "raffle" 32 | dynamic = ["version"] 33 | dependencies = [ 34 | "ase>=3.23.0", 35 | "numpy>=1.26.4,<=2.2", 36 | "f90wrap>=0.2.14,<=0.2.16", 37 | ] 38 | requires-python = ">=3.11,<3.14" 39 | authors = [ 40 | { name = "Ned Thaddeus Taylor", email = "n.t.taylor@exeter.ac.uk" }, 41 | { name = "Joe Pitfield", email = "joepitfield@gmail.com" }, 42 | { name = "Steven Paul Hepplestone", email = "s.p.hepplestone@exeter.ac.uk" }, 43 | ] 44 | description = "A material interface structure prediction package" 45 | readme = "README.md" 46 | license = { text = 'GNU General Public License v3.0 or later'} 47 | classifiers = [ 48 | "Development Status :: 5 - Production/Stable", 49 | "Intended Audience :: Science/Research", 50 | "Programming Language :: Python :: 3.11", 51 | "Programming Language :: Python :: 3.12", 52 | "Programming Language :: Python :: 3.13", 53 | "Programming Language :: Fortran", 54 | "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", 55 | "Operating System :: OS Independent", 56 | ] 57 | 58 | [project.urls] 59 | Homepage = "https://github.com/ExeQuantCode/raffle" 60 | Documentation = "https://raffle-fortran.readthedocs.io/" 61 | Repository = "https://github.com/ExeQuantCode/raffle" 62 | Issues = "https://github.com/ExeQuantCode/raffle/issues" 63 | 64 | [project.optional-dependencies] 65 | tests = [ 66 | "pytest", 67 | "pytest-cov", 68 | "parameterized", 69 | "unittest", 70 | ] 71 | 72 | [tool.scikit-build.metadata.version] 73 | provider = "scikit_build_core.metadata.regex" 74 | input = "fpm.toml" 75 | regex = '(?i)^version *= \"(?P.+?)\"' 76 | -------------------------------------------------------------------------------- /example/python_pkg/Si-Ge_learn/abrupt_shifts.py: -------------------------------------------------------------------------------- 1 | # %% 2 | import os 3 | from pathlib import Path 4 | from ase.io import read, write 5 | from ase.visualize import view 6 | from ase.optimize import FIRE 7 | from ase.calculators.singlepoint import SinglePointCalculator 8 | from mace.calculators import mace_mp 9 | from artemis.generator import artemis_generator 10 | 11 | script_dir = Path(__file__).resolve().parent 12 | 13 | # %% 14 | abrupt = read(script_dir / 'SiGe_abrupt_interface_rescaled.vasp') 15 | abrupt.set_pbc(True) 16 | 17 | # %% 18 | generator = artemis_generator() 19 | 20 | # %% 21 | loc, axis = generator.get_interface_location(abrupt) 22 | 23 | # %% 24 | generator.set_shift_method( 25 | num_shifts = 20 26 | ) 27 | # %% 28 | structures = generator.regenerate(abrupt, verbose=1) 29 | 30 | # %% 31 | # make directory for the structures 32 | output_dir = script_dir / "SiGe_shifted_structures" 33 | output_dir.mkdir(parents=True, exist_ok=True) 34 | for i, structure in enumerate(structures): 35 | write(output_dir / f'SiGe_shifted_{i}.vasp', structure, format='vasp', sort=True, direct=True) 36 | 37 | exit() 38 | # %% 39 | 40 | # check if mace file exists 41 | if not os.path.exists(script_dir / ".." / "mace-mpa-0-medium.model"): 42 | print("MACE-MPA-0 model file not found. Please download the model from the MACE website.") 43 | print("https://github.com/ACEsuit/mace-foundations/releases/tag/mace_mpa_0") 44 | exit(1) 45 | 46 | # set up the calculator 47 | calc_params = { 'model': script_dir / ".." / "mace-mpa-0-medium.model" } 48 | calc = mace_mp(**calc_params) 49 | 50 | # %% 51 | structures = [ abrupt.copy() ] 52 | structures.extend(generator.get_structures(calculator = calc)) 53 | 54 | for structure in structures: 55 | structure.calc = calc 56 | structure.calc = SinglePointCalculator( 57 | structure, 58 | energy=structure.get_potential_energy(), 59 | forces=structure.get_forces() 60 | ) 61 | 62 | 63 | write('SiGe_shifted_unrlxd.traj', structures) 64 | 65 | view(structures) 66 | 67 | # %% 68 | 69 | for structure in structures: 70 | structure.calc = calc 71 | optimizer = FIRE(structure) 72 | optimizer.run(fmax=0.05, steps=200) 73 | structure.calc = SinglePointCalculator( 74 | structure, 75 | energy=structure.get_potential_energy(), 76 | forces=structure.get_forces() 77 | ) 78 | 79 | write('SiGe_shifted_rlxd.traj', structures) 80 | -------------------------------------------------------------------------------- /tools/check_accuracy_C-Li.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | 4 | ## import ASE (Atomic Simulation Environment) modules 5 | from ase import Atoms 6 | from ase.io import read, write 7 | 8 | 9 | ## load calculator 10 | calculator = "MACE" 11 | match calculator: 12 | case "CHGNet": 13 | from chgnet.model.dynamics import CHGNetCalculator 14 | print("Initialising CHGNet calculator") 15 | calc = CHGNetCalculator() 16 | label = "CHGNet" 17 | case "MACE": 18 | from mace.calculators import mace_mp 19 | print("Initialising MACE calculator") 20 | calc_params = { 'model': "../example/python_pkg/Si-Ge_learn/DRAFFLE/mace-mpa-0-medium.model" } 21 | calc = mace_mp(**calc_params) 22 | # calc = mace_mp(model="medium", dispersion=False, default_dtype="float32", device='cpu') 23 | label = "MACE" 24 | 25 | from ase.build import bulk 26 | Li = bulk("Li") 27 | Li.calc = calc 28 | print("Energy of Li:", Li.get_potential_energy() / len(Li)) 29 | 30 | ## Read the database 31 | print("Reading database") 32 | database = read("../../../../DBig_database/Li-Carbon.xyz", index=":") 33 | # database = read("../example/data/carbon.xyz", index=":") 34 | 35 | C_host = database[0] 36 | C_host.calc = calc 37 | print("Energy of C_host:", C_host.get_potential_energy()) 38 | 39 | ## Calculate the energies 40 | energies_dft = [] 41 | energies_mlp = [] 42 | for i, atoms in enumerate(database): 43 | if atoms.calc is None: 44 | database.remove(atoms) 45 | continue 46 | energies_dft.append(atoms.get_potential_energy()/len(atoms)) 47 | atoms.calc = calc 48 | energies_mlp.append(atoms.get_potential_energy()/len(atoms)) 49 | # if energies_mlp[-1] - energies_dft[-1] > 3e-1 and energies_mlp[-1] < -7.9: 50 | # print(f"Energy difference for structure {i} is {energies_mlp[-1] - energies_dft[-1]}, energy_mace: {energies_mlp[-1]}") 51 | # view(atoms) 52 | 53 | 54 | import matplotlib.pyplot as plt 55 | 56 | ## Write energies to a file 57 | with open("Li-C_energies_comparison.txt", "w") as f: 58 | f.write("# DFT_Energy_per_atom "+label+"_Energy_per_atom\n") 59 | for dft_energy, mace_energy in zip(energies_dft, energies_mlp): 60 | f.write(f"{dft_energy} {mace_energy}\n") 61 | 62 | ## Plot the energies 63 | plt.figure(figsize=(10, 6)) 64 | plt.scatter(energies_dft, energies_mlp, c='blue', marker='o', label=label+' vs DFT') 65 | plt.show() -------------------------------------------------------------------------------- /example/python_pkg/README.md: -------------------------------------------------------------------------------- 1 | # Python Package Example 2 | 3 | This directory contains example Python files demonstrating how to use the raffle package. 4 | 5 | ## Directory Structure 6 | 7 | ``` 8 | python_pkg/ 9 | ├── # Example with dataset containing global minimum from which to learn RAFFLE descriptors 10 | └── run.py # Script to test placement methods 11 | └── # Example with no prior database, i.e. RAFFLE starts with no prior knowledge 12 | ├── DRAFFLE # Directory containing example RAFFLE learning script 13 | ├── learn.py # Script to run RSS generating and learning 14 | └── pca.ipynb # Notebook to plot principal component analysis of RAFFLE results 15 | └── DRSS # Directory containing example random structure search script using AGOX 16 | ├── rss.py # Script to run RSS 17 | └── pca.ipynb # Notebook to plot principal component analysis of RSS results 18 | ``` 19 | 20 | ## File Descriptions 21 | 22 | - `run.py`: Example script highlighting placement method capabilities 23 | - `learn.py`: Example script highlighting learning capabilties of RAFFLE 24 | - `pca.ipynb`: Notebook to generate principal component analysis of generated structures 25 | 26 | ## Execution Order 27 | 28 | To run a RAFFLE example and analyse the results, the following order must be performed. 29 | 1. Move to the desired `SYSTEM_learn/DRAFFLE` directory and create a directory to work in: 30 | ```bash 31 | cd SYSTEM_learn/DRAFFLE 32 | mkdir DOutput 33 | cd DOutput 34 | ``` 35 | 36 | 2. Run the `learn.py` script: 37 | ```bash 38 | python ../learn.py 39 | ``` 40 | 41 | 3. Go to parent directory and open the notebook `pca.ipynb`, run all the cells. 42 | 43 | NOTE: for the `C_learn/DRSS/` example, the `pca.ipynb` notebook expects that the `C_learn/DRAFFLE/` example script and notebook have been fully run first. 44 | This is because it attempts to use the PCA of the RAFFLE results to transform its data. 45 | Doing so enables the two techniques to be properly compared. 46 | 47 | The `[un]rlxd_structures_seed0.traj` files are provided (as are the `energies_[un]rlxd+seed0.txt`) as the key outputs from the `learn.py` runs. 48 | For the `rss.py` scripts, the `[un]rlxd_structures_seed0.traj` files are provided. 49 | Whilst other output files are generated during the RAFFLE runs, these are optional files with mostly redundant data. 50 | 51 | ## Prerequisites 52 | 53 | - Python 3.11 or higher 54 | - raffle package installed (`pip install .`) 55 | - `ase` for handling atomic structure data 56 | - `CHGNet`, `MACE`, `VASP`, or some other `ase`-compatible calculator 57 | -------------------------------------------------------------------------------- /test/test_tools_infile.f90: -------------------------------------------------------------------------------- 1 | program test_tools_infile 2 | use raffle__constants, only: real32 3 | use raffle__tools_infile 4 | implicit none 5 | 6 | 7 | integer :: ival = 0 8 | logical :: ltmp1 9 | character(256) :: stmp1 10 | character(256) :: line 11 | 12 | logical :: success = .true. 13 | 14 | 15 | line = "APPLES = string" 16 | call assign_val(line, stmp1, ival, keyword="APPLES") 17 | if( trim(stmp1) .ne. "string" .or. ival .ne. 1 )then 18 | write(0,*) "assign_val failed for string" 19 | success = .false. 20 | end if 21 | 22 | line = "ORANGES = 1" 23 | call assign_val(line, ltmp1, ival, keyword="ORANGES") 24 | if( .not. ltmp1 .or. ival .ne. 2 )then 25 | write(0,*) "assign_val failed for logical" 26 | success = .false. 27 | end if 28 | line = "ORANGES = 0" 29 | call assign_val(line, ltmp1, ival, keyword="ORANGES") 30 | if( ltmp1 .or. ival .ne. 3 )then 31 | write(0,*) "assign_val failed for logical" 32 | success = .false. 33 | end if 34 | line = "ORANGES = T" 35 | call assign_val(line, ltmp1, ival, keyword="ORANGES") 36 | if( .not. ltmp1 .or. ival .ne. 4 )then 37 | write(0,*) "assign_val failed for logical" 38 | success = .false. 39 | end if 40 | line = "ORANGES = F" 41 | call assign_val(line, ltmp1, ival, keyword="ORANGES") 42 | if( ltmp1 .or. ival .ne. 5 )then 43 | write(0,*) "assign_val failed for logical" 44 | success = .false. 45 | end if 46 | line = "ORANGES = t" 47 | call assign_val(line, ltmp1, ival, keyword="ORANGES") 48 | if( .not. ltmp1 .or. ival .ne. 6 )then 49 | write(0,*) "assign_val failed for logical" 50 | success = .false. 51 | end if 52 | line = "ORANGES = f" 53 | call assign_val(line, ltmp1, ival, keyword="ORANGES") 54 | if( ltmp1 .or. ival .ne. 7 )then 55 | write(0,*) "assign_val failed for logical" 56 | success = .false. 57 | end if 58 | 59 | line = "BANANAS = 1.0 # comment" 60 | ! ival = line number here 61 | call rm_comments(line, ival) 62 | if( trim(line) .ne. "BANANAS = 1.0")then 63 | write(0,*) "rm_comments failed" 64 | write(0,'("\",A,"\")') trim(line) 65 | success = .false. 66 | end if 67 | 68 | 69 | !----------------------------------------------------------------------------- 70 | ! check for any failed tests 71 | !----------------------------------------------------------------------------- 72 | write(*,*) "----------------------------------------" 73 | if(success)then 74 | write(*,*) 'test_tools_infile passed all tests' 75 | else 76 | write(0,*) 'test_tools_infile failed one or more tests' 77 | stop 1 78 | end if 79 | 80 | 81 | 82 | end program test_tools_infile 83 | -------------------------------------------------------------------------------- /.github/workflows/python.yml: -------------------------------------------------------------------------------- 1 | name: run-python-build 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | - development 8 | types: 9 | - opened 10 | - synchronize 11 | paths: 12 | - ".github/workflows/python.yml" 13 | - "CMakeLists.txt" 14 | - "pyproject.toml" 15 | - "src/*.py" 16 | - "**.f90" 17 | - "**.F90" 18 | workflow_dispatch: 19 | 20 | permissions: 21 | contents: read 22 | pages: write 23 | id-token: write 24 | 25 | concurrency: 26 | group: python 27 | cancel-in-progress: false 28 | 29 | jobs: 30 | build-and-test-python: 31 | environment: 32 | name: github-pages 33 | name: Build and test in debug mode 34 | runs-on: ${{ matrix.os }} 35 | strategy: 36 | fail-fast: false 37 | matrix: 38 | os: [ubuntu-latest, macos-latest] 39 | python-version: [ "3.11", "3.12", "3.13" ] 40 | toolchain: 41 | - {fortran-compiler: gcc, fc-version: 14} 42 | build_type: [Serial, Release] 43 | 44 | steps: 45 | - name: checkout repo 46 | uses: actions/checkout@v4 47 | 48 | - name: actions-setup-python ${{ matrix.python-version }} 49 | uses: actions/setup-python@v5 50 | with: 51 | python-version: ${{ matrix.python-version }} 52 | 53 | - name: actions-setup-cmake 54 | uses: jwlawson/actions-setup-cmake@v2.0.1 55 | with: 56 | cmake-version: '3.24.x' 57 | 58 | - uses: fortran-lang/setup-fortran@v1 59 | id: setup-fortran 60 | with: 61 | compiler: ${{ matrix.toolchain.fortran-compiler }} 62 | version: ${{ matrix.toolchain.fc-version }} 63 | 64 | - name: Install python dependencies 65 | run: | 66 | python --version 67 | python -m pip install pip-tools 68 | python -m pip install pytest 69 | python -m pip install parameterized 70 | python -m piptools compile -o requirements.txt pyproject.toml --all-build-deps 71 | python -m pip install -r requirements.txt 72 | 73 | - name: Install OpenMP runtime (Linux only) 74 | if: runner.os == 'Linux' 75 | run: sudo apt-get update && sudo apt-get install -y libgomp1 76 | 77 | - name: Build and install Python package with CMAKE_BUILD_TYPE=${{ matrix.build_type }} 78 | env: 79 | CMAKE_BUILD_TYPE: ${{ matrix.build_type }} 80 | run: | 81 | cmake --version 82 | echo "Building with CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" 83 | python -m pip install ".[ase]" --config-settings="cmake.define.CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" 84 | 85 | - name: Run tests 86 | run: | 87 | ${{ env.FC }} --version 88 | python -m pytest 89 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | 3 | # -- Project information 4 | import datetime 5 | import os 6 | import sys 7 | 8 | from unittest.mock import Mock 9 | 10 | MOCK_MODULES = ["raffle._raffle"] # List any other modules if needed 11 | sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES) 12 | 13 | # sys.path.insert(0, os.path.abspath(os.path.join('..', '..', 'src', 'raffle'))) # Sets the base path to find your modules 14 | sys.path.insert(0, os.path.abspath(os.path.join('..', '..', 'src'))) # Sets the base path to find your modules 15 | 16 | project = 'RAFFLE' 17 | copyright = f'{datetime.date.today().year}, RAFFLE-developers' 18 | # release = '1.0' 19 | # version = '1.0.0' 20 | 21 | # -- General configuration 22 | master_doc = 'index' 23 | 24 | # Identify the branch of the documentation 25 | on_rtd = os.environ.get('READTHEDOCS') == 'True' 26 | if on_rtd: 27 | git_branch = os.environ.get("READTHEDOCS_GIT_IDENTIFIER", "main") 28 | else: 29 | git_branch = "main" # or get from git directly with subprocess 30 | 31 | extensions = [ 32 | 'sphinx.ext.duration', 33 | 'sphinx.ext.doctest', 34 | 'sphinx.ext.autodoc', 35 | 'sphinx.ext.autosummary', 36 | 'sphinx.ext.intersphinx', 37 | 'sphinxcontrib.bibtex', 38 | 'sphinx.ext.napoleon', 39 | 'sphinx.ext.viewcode', 40 | 'sphinx_rtd_theme', 41 | 'sphinx.ext.extlinks', 42 | ] 43 | 44 | extlinks = { 45 | 'git': ('https://github.com/ExeQuantCode/RAFFLE/blob/' + git_branch + '/%s', 'git: %s') 46 | } 47 | 48 | intersphinx_mapping = { 49 | 'python': ('https://docs.python.org/3/', None), 50 | 'sphinx': ('https://www.sphinx-doc.org/en/master/', None), 51 | } 52 | intersphinx_disabled_domains = ['std'] 53 | 54 | templates_path = ['_templates'] 55 | 56 | exclude_patterns = ['_build', '.DS_Store', 'build'] 57 | 58 | 59 | # -- Options for HTML output 60 | 61 | html_theme = 'sphinx_rtd_theme' 62 | 63 | # -- Options for EPUB output 64 | epub_show_urls = 'footnote' 65 | 66 | html_logo = "RAFFLE_logo_no_background.png" 67 | # html_favicon = 'favicon.ico' 68 | html_theme_options = { 69 | 'logo_only': False, 70 | 'prev_next_buttons_location': 'bottom', 71 | 'style_external_links': False, 72 | 'vcs_pageview_mode': '', 73 | # 'style_nav_header_background': 'white', 74 | 'flyout_display': 'hidden', 75 | 'version_selector': True, 76 | 'language_selector': True, 77 | # Toc options 78 | 'collapse_navigation': True, 79 | 'sticky_navigation': True, 80 | 'navigation_depth': 4, 81 | 'includehidden': True, 82 | 'titles_only': False, 83 | } 84 | 85 | 86 | html_context = { 87 | "display_github": True, 88 | "github_repo": "RAFFLE", 89 | "github_user": "ExeQuantCode", 90 | "github_version": "main", 91 | "conf_py_path": "/docs/source/", 92 | } 93 | 94 | autoclass_content="both" 95 | 96 | bibtex_bibfiles = ['references.bib'] 97 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | ====== 2 | RAFFLE 3 | ====== 4 | 5 | RAFFLE (pseudoRandom Approach For Finding Local Energetic minima) is a Python and Fortran package for structure prediction applied to interfaces. 6 | RAFFLE can be utilised as a Python package, a Fortran library, or a standalone Fortran executable. 7 | The Python package provides a high-level interface to the Fortran library, which contains the core functionality. 8 | 9 | The Python package interfaces seemlessly with `ASE (Atomic Simulation Environment) `_, allowing for easy reading, writing, and manipulation of atomic structures. 10 | Although the package comes with a built-in atomic structure reader and writer, it is recommended to use ASE due to its greater functionality and wide-reaching support. 11 | 12 | The code is provided freely available under the `GNU General Public License v3.0 `_. 13 | 14 | An example 15 | 16 | .. code-block:: python 17 | 18 | # A simple example of how to use RAFFLE to generate 10 structures of diamond and write them to a single file 19 | from ase import Atoms 20 | from ase.io import write 21 | from ase.calculators.singlepoint import SinglePointCalculator 22 | from raffle.generator import raffle_generator 23 | from mace.calculators import mace_mp 24 | 25 | generator = raffle_generator() 26 | generator.distributions.set_history_len(10) 27 | calc = mace_mp(model="medium", dispersion=False, default_dtype="float32", device='cpu') 28 | 29 | host = Atoms('C', positions=[[0, 0, 0]], cell=[10, 10, 10]) 30 | host.calc = calc 31 | generator.set_host(host) 32 | 33 | generator.distributions.set_element_energies( { 'C': 0.0 } ) 34 | generator.distributions.create(host) 35 | 36 | num_structures_old = 0 37 | for i in range(10): 38 | structures = generator.generate( 39 | num_structures = 2, 40 | stoichiometry = { 'C': 7 } 41 | ) 42 | for structure in structures: 43 | optimiser = FIRE(structure) 44 | optimiser.run(fmax=0.05) 45 | 46 | generator.distributions.update(structures) 47 | num_structures_old += len(structures) 48 | if generator.distributions.is_converged(): 49 | break 50 | 51 | structures = generator.get_structures(calc) 52 | for structure in structures: 53 | structure.calc = SinglePointCalculator( 54 | structure, 55 | energy=structure.get_potential_energy(), 56 | forces=structure.get_forces() 57 | ) 58 | 59 | write('structures.traj', structures) 60 | 61 | .. toctree:: 62 | :maxdepth: 3 63 | :caption: Contents: 64 | 65 | about 66 | install 67 | tutorials/index 68 | faq 69 | Python API 70 | 71 | .. Indices and tables 72 | .. ================== 73 | 74 | .. * :ref:`genindex` 75 | .. * :ref:`modindex` 76 | .. * :ref:`search` 77 | -------------------------------------------------------------------------------- /example/python_pkg/benchmarks/min_placement.py: -------------------------------------------------------------------------------- 1 | import os 2 | nthreads = 1 3 | os.environ["OMP_NUM_THREADS"] = str(nthreads) 4 | os.environ["OPENBLAS_NUM_THREADS"] = str(nthreads) 5 | os.environ["MKL_NUM_THREADS"] = str(nthreads) 6 | 7 | import pytest 8 | import time 9 | import numpy as np 10 | from ase import Atoms 11 | from chgnet.model import CHGNetCalculator 12 | from raffle.generator import raffle_generator 13 | 14 | 15 | @pytest.mark.parametrize("kBT", [0.4]) 16 | @pytest.mark.parametrize("width", [ 17 | [0.025, np.pi/200.0, np.pi/200.0] 18 | ]) 19 | @pytest.mark.parametrize("grid_spacing", [0.5, 0.25, 0.1, 0.075, 0.05]) 20 | @pytest.mark.benchmark( 21 | group="min_placement", 22 | min_rounds=5, 23 | timer=time.time, 24 | disable_gc=True, 25 | warmup=False 26 | ) 27 | def test_min_placement(benchmark, grid_spacing, kBT, width): 28 | 29 | calc = CHGNetCalculator() 30 | host = Atoms('C', positions=[(0, 0, 0)], cell=[3.567, 3.567, 3.567], pbc=True, calculator=calc) 31 | 32 | # Initialize generator 33 | generator = raffle_generator() 34 | 35 | # set energy scale 36 | generator.distributions.set_kBT(kBT) 37 | 38 | # set the distribution function widths (2-body, 3-body, 4-body) 39 | generator.distributions.set_width(width) 40 | 41 | energies = {element: 0.0 for element in ['C']} 42 | generator.distributions.set_element_energies(energies) 43 | 44 | generator.set_grid(grid_spacing=grid_spacing) 45 | generator.set_host(host) 46 | 47 | initial_database = [Atoms('C', positions=[(0, 0, 0)], cell=[8, 8, 8], pbc=True, calculator=calc)] 48 | 49 | generator.distributions.create(initial_database) 50 | 51 | benchmark.extra_info = { 52 | "kBT": kBT, 53 | "width": width, 54 | "grid_spacing": grid_spacing 55 | } 56 | 57 | 58 | # Measure time for distributions.create() 59 | result = benchmark(generator.generate, 60 | num_structures = 1, 61 | stoichiometry = {'C': 1}, 62 | seed = 0, 63 | method_ratio = { 64 | 'void': 0.0, 65 | 'rand': 0.0, 66 | 'walk': 0.0, 67 | 'grow': 0.0, 68 | 'min': 1.0 69 | 70 | }, 71 | verbose = 0 72 | ) 73 | 74 | return result 75 | 76 | if __name__ == '__main__': 77 | grid_spacings = [0.5, 0.25, 0.1, 0.075, 0.05] 78 | results = [] 79 | 80 | for grid_spacing in grid_spacings: 81 | for _ in range(5): # Run the benchmark 5 times for each grid size 82 | result = test_min_placement(lambda x: x, grid_spacing, 0.4, [0.025, np.pi/200.0, np.pi/200.0]) 83 | results.append({ 84 | 'grid_spacing': grid_spacing, 85 | 'time': result 86 | }) 87 | 88 | # Print results 89 | print("\nBenchmark Results:") 90 | print("-" * 40) 91 | print(f"{'Grid Size':<10} {'Time (s)':<10}") 92 | print("-" * 40) 93 | for result in results: 94 | print(f"{result['grid_spacing']:<10} {result['time']:<10.4f}") 95 | -------------------------------------------------------------------------------- /src/fortran/lib/mod_io_utils.F90: -------------------------------------------------------------------------------- 1 | module raffle__io_utils 2 | !! Module for handling errors and io calls in the program. 3 | !! 4 | !! This module provides the expected procedure for stopping a program. 5 | !! If in testing mode, the stop can be suppressed. 6 | implicit none 7 | logical :: test_error_handling = .false. 8 | 9 | logical :: suppress_warnings = .false. 10 | character(len=*), parameter :: raffle__version__ = "1.1.1" 11 | 12 | private 13 | 14 | public :: raffle__version__ 15 | public :: test_error_handling, suppress_warnings 16 | public :: stop_program, print_warning 17 | public :: print_version, print_build_info 18 | 19 | 20 | contains 21 | 22 | !############################################################################### 23 | subroutine stop_program(message, exit_code, block_stop) 24 | !! Stop the program and print an error message. 25 | implicit none 26 | character(len=*), intent(in) :: message 27 | integer, intent(in), optional :: exit_code 28 | logical, intent(in), optional :: block_stop 29 | 30 | integer :: exit_code_ 31 | logical :: block_stop_ 32 | 33 | if(present(exit_code)) then 34 | exit_code_ = exit_code 35 | else 36 | exit_code_ = 1 37 | end if 38 | if(present(block_stop)) then 39 | block_stop_ = block_stop 40 | else 41 | block_stop_ = .false. 42 | end if 43 | 44 | write(0,*) 'ERROR: ', trim(message) 45 | if(.not.block_stop_)then 46 | if(.not.test_error_handling) then 47 | stop exit_code_ 48 | end if 49 | end if 50 | end subroutine stop_program 51 | !############################################################################### 52 | 53 | 54 | !############################################################################### 55 | subroutine print_warning(message) 56 | !! Print a warning message 57 | implicit none 58 | character(len=*), intent(in) :: message 59 | 60 | if(.not.suppress_warnings) then 61 | write(0,*) 'WARNING: ', trim(message) 62 | end if 63 | end subroutine print_warning 64 | !############################################################################### 65 | 66 | 67 | !############################################################################### 68 | subroutine print_version() 69 | !! Print the version number of the program. 70 | implicit none 71 | 72 | write(*,'("version: ",A)') raffle__version__ 73 | end subroutine print_version 74 | !############################################################################### 75 | 76 | 77 | !############################################################################### 78 | subroutine print_build_info() 79 | !! Print the build information of the program. 80 | implicit none 81 | 82 | write(*,'("RAFFLE: pseudoRandom Approach For Finding Local Energy minima")') 83 | call print_version() 84 | write(*,'(" (build ",A,1X,A,")")') __DATE__, __TIME__ 85 | 86 | end subroutine print_build_info 87 | !############################################################################### 88 | 89 | end module raffle__io_utils 90 | -------------------------------------------------------------------------------- /src/fortran/lib/mod_misc_maths.f90: -------------------------------------------------------------------------------- 1 | module raffle__misc_maths 2 | !! Module for miscellaneous mathematical functions. 3 | use raffle__io_utils, only: stop_program 4 | use raffle__constants, only: real32 5 | implicit none 6 | 7 | 8 | private 9 | 10 | public :: lnsum, triangular_number, set_difference 11 | 12 | 13 | 14 | contains 15 | 16 | !############################################################################### 17 | function lnsum(n) 18 | !! Return the sum of the logs of the integers from 1 to n. 19 | implicit none 20 | 21 | ! Arguments 22 | integer :: n 23 | !! The upper limit of the range. 24 | real(real32) :: lnsum 25 | !! The sum of the logs of the integers from 1 to n. 26 | 27 | ! Local variables 28 | integer :: i 29 | !! Loop index. 30 | 31 | lnsum = 0._real32 32 | do i = 1, n 33 | lnsum = lnsum + log( real(i, real32) ) 34 | end do 35 | 36 | return 37 | end function lnsum 38 | !############################################################################### 39 | 40 | 41 | !############################################################################### 42 | pure function triangular_number(n) result(output) 43 | !! Return the nth triangular number. 44 | implicit none 45 | 46 | ! Arguments 47 | integer, intent(in) :: n 48 | !! The index of the triangular number to return. 49 | 50 | integer :: output 51 | !! The nth triangular number. 52 | 53 | output = n * ( n + 1 ) / 2 54 | end function triangular_number 55 | !############################################################################### 56 | 57 | 58 | !############################################################################### 59 | function set_difference(a, b, set_min_zero) 60 | !! Return the set difference of two arrays. 61 | implicit none 62 | 63 | ! Arguments 64 | real(real32), dimension(:), intent(in) :: a 65 | !! The first array. 66 | real(real32), dimension(:), intent(in) :: b 67 | !! The second array. 68 | logical, optional :: set_min_zero 69 | !! Boolean to set the maximum value of the output array to zero. 70 | real(real32), dimension(size(a)) :: set_difference 71 | !! The set difference of the two arrays. 72 | 73 | ! Local variables 74 | integer :: i 75 | !! Loop indices. 76 | logical :: set_min_zero_ 77 | !! Boolean to set all values below zero to zero. 78 | 79 | 80 | if(present(set_min_zero)) then 81 | set_min_zero_ = set_min_zero 82 | else 83 | set_min_zero_ = .false. 84 | end if 85 | 86 | if(size(a,1) .ne. size(b,1)) then 87 | call stop_program('Arrays must be the same size.') 88 | return 89 | end if 90 | 91 | if(set_min_zero_)then 92 | do i = 1, size(a,1) 93 | set_difference(i) = max(0.0_real32, a(i) - b(i)) 94 | end do 95 | else 96 | set_difference = a - b 97 | end if 98 | 99 | end function set_difference 100 | !############################################################################### 101 | 102 | end module raffle__misc_maths 103 | -------------------------------------------------------------------------------- /tools/check_accuracy_C.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | 4 | ## import ASE (Atomic Simulation Environment) modules 5 | from ase import Atoms 6 | from ase.io import read, write 7 | 8 | 9 | ## load calculator 10 | from chgnet.model.dynamics import CHGNetCalculator 11 | print("Initialising CHGNet calculator") 12 | chgnet = CHGNetCalculator() 13 | from mace.calculators import mace_mp 14 | print("Initialising MACE calculator") 15 | calc_params = { 'model': "../example/python_pkg/mace-mpa-0-medium.model" } 16 | mace = mace_mp(**calc_params) 17 | # calc = mace_mp(model="medium", dispersion=False, default_dtype="float32", device='cpu') 18 | 19 | ## Read the database 20 | print("Reading database") 21 | database = read("../example/data/carbon.xyz", index=":") 22 | 23 | # get index of lowest energy structure 24 | lowest_energy_index = np.argmin([ 25 | atoms.get_potential_energy() if atoms.calc is not None else float('inf') 26 | for atoms in database 27 | ]) 28 | C_energy_dft = database[lowest_energy_index].get_potential_energy() / len(database[lowest_energy_index]) 29 | C_ground_state = database[lowest_energy_index].copy() 30 | C_ground_state.calc = chgnet 31 | C_energy_chgnet = C_ground_state.get_potential_energy() / len(C_ground_state) 32 | C_ground_state.calc = mace 33 | C_energy_mace = C_ground_state.get_potential_energy() / len(C_ground_state) 34 | 35 | 36 | ## Calculate the energies 37 | energies_dft = [] 38 | energies_mace = [] 39 | energies_chgnet = [] 40 | formation_energies_dft = [] 41 | formation_energies_mace = [] 42 | formation_energies_chgnet = [] 43 | for i, atoms in enumerate(database): 44 | if atoms.calc is None: 45 | database.remove(atoms) 46 | continue 47 | formation_energy_dft = atoms.get_potential_energy() / len(atoms) - C_energy_dft 48 | formation_energies_dft.append(formation_energy_dft) 49 | energies_dft.append(atoms.get_potential_energy()/len(atoms)) 50 | atoms.calc = chgnet 51 | formation_energy_chgnet = atoms.get_potential_energy() / len(atoms) - C_energy_chgnet 52 | formation_energies_chgnet.append(formation_energy_chgnet) 53 | energies_chgnet.append(atoms.get_potential_energy()/len(atoms)) 54 | atoms.calc = mace 55 | formation_energy_mace = atoms.get_potential_energy() / len(atoms) - C_energy_mace 56 | formation_energies_mace.append(formation_energy_mace) 57 | energies_mace.append(atoms.get_potential_energy()/len(atoms)) 58 | 59 | 60 | import matplotlib.pyplot as plt 61 | 62 | ## Write energies to a file 63 | with open("C_energies_comparison.txt", "w") as f: 64 | f.write("# DFT_Energy_per_atom MACE-MPA-0_Energy_per_atom CHGNet_Energy_per_atom\n") 65 | for dft_energy, mace_energy, chgnet_energy in zip(energies_dft, energies_mace, energies_chgnet): 66 | f.write(f"{dft_energy} {mace_energy} {chgnet_energy}\n") 67 | 68 | with open("C_formations_comparison.txt", "w") as f: 69 | f.write("# DFT_Formation_energy_per_atom MACE-MPA-0_Formation_energy_per_atom CHGNet_Formation_energy_per_atom\n") 70 | for dft_energy, mace_energy, chgnet_energy in zip(formation_energies_dft, formation_energies_mace, formation_energies_chgnet): 71 | f.write(f"{dft_energy} {mace_energy} {chgnet_energy}\n") 72 | 73 | ## Plot the energies 74 | plt.figure(figsize=(10, 6)) 75 | plt.scatter(energies_dft, energies_mace, c='blue', marker='o', label='MLIP vs DFT') 76 | plt.show() -------------------------------------------------------------------------------- /example/python_pkg/benchmarks/placement_methods.py: -------------------------------------------------------------------------------- 1 | import os 2 | nthreads = 1 3 | os.environ["OMP_NUM_THREADS"] = str(nthreads) 4 | os.environ["OPENBLAS_NUM_THREADS"] = str(nthreads) 5 | os.environ["MKL_NUM_THREADS"] = str(nthreads) 6 | 7 | import pytest 8 | import time 9 | import numpy as np 10 | from ase import Atoms 11 | from chgnet.model import CHGNetCalculator 12 | from raffle.generator import raffle_generator 13 | 14 | 15 | @pytest.mark.parametrize("kBT", [0.4]) 16 | @pytest.mark.parametrize("width", [ 17 | [0.025, np.pi/200.0, np.pi/200.0] 18 | ]) 19 | @pytest.mark.parametrize("grid_spacing", [0.5, 0.25, 0.1, 0.075, 0.05]) 20 | @pytest.mark.parametrize("method_ratio", [ 21 | {'void': 0.0, 'rand': 0.0, 'walk': 0.0, 'grow': 0.0, 'min': 1.0}, 22 | {'void': 0.0, 'rand': 0.0, 'walk': 0.0, 'grow': 1.0, 'min': 0.0}, 23 | {'void': 0.0, 'rand': 0.0, 'walk': 1.0, 'grow': 0.0, 'min': 0.0}, 24 | {'void': 0.0, 'rand': 1.0, 'walk': 0.0, 'grow': 0.0, 'min': 0.0}, 25 | {'void': 1.0, 'rand': 0.0, 'walk': 0.0, 'grow': 0.0, 'min': 0.0} 26 | ]) 27 | @pytest.mark.benchmark( 28 | group="placement_methods", 29 | min_rounds=5, 30 | timer=time.time, 31 | disable_gc=True, 32 | warmup=False 33 | ) 34 | def test_placement_methods(benchmark, grid_spacing, kBT, width, method_ratio): 35 | 36 | calc = CHGNetCalculator() 37 | host = Atoms('C', positions=[(0, 0, 0)], cell=[3.567, 3.567, 3.567], pbc=True, calculator=calc) 38 | 39 | # Initialize generator 40 | generator = raffle_generator() 41 | 42 | # set energy scale 43 | generator.distributions.set_kBT(kBT) 44 | 45 | # set the distribution function widths (2-body, 3-body, 4-body) 46 | generator.distributions.set_width(width) 47 | 48 | energies = {element: 0.0 for element in ['C']} 49 | generator.distributions.set_element_energies(energies) 50 | 51 | generator.set_grid(grid_spacing=grid_spacing) 52 | generator.set_host(host) 53 | 54 | initial_database = [Atoms('C', positions=[(0, 0, 0)], cell=[8, 8, 8], pbc=True, calculator=calc)] 55 | 56 | generator.distributions.create(initial_database) 57 | 58 | benchmark.extra_info = { 59 | "kBT": kBT, 60 | "width": width, 61 | "grid_spacing": grid_spacing, 62 | "method_ratio": method_ratio 63 | } 64 | 65 | # Measure time for distributions.create() 66 | result = benchmark(generator.generate, 67 | num_structures = 1, 68 | stoichiometry = {'C': 1}, 69 | seed = 0, 70 | method_ratio = method_ratio, 71 | verbose = 0 72 | ) 73 | 74 | return result 75 | 76 | if __name__ == '__main__': 77 | grid_spacings = [0.5, 0.25, 0.1, 0.075, 0.05] 78 | results = [] 79 | 80 | for grid_spacing in grid_spacings: 81 | for _ in range(5): # Run the benchmark 5 times for each grid size 82 | result = test_placement_methods(lambda x: x, grid_spacing, 0.4, [0.025, np.pi/200.0, np.pi/200.0]) 83 | results.append({ 84 | 'grid_spacing': grid_spacing, 85 | 'time': result 86 | }) 87 | 88 | # Print results 89 | print("\nBenchmark Results:") 90 | print("-" * 40) 91 | print(f"{'Grid Size':<10} {'Time (s)':<10}") 92 | print("-" * 40) 93 | for result in results: 94 | print(f"{result['grid_spacing']:<10} {result['time']:<10.4f}") 95 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct - RAFFLE 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to make participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to a positive environment for our 15 | community include: 16 | 17 | * Demonstrating empathy and kindness toward other people 18 | * Being respectful of differing opinions, viewpoints, and experiences 19 | * Giving and gracefully accepting constructive feedback 20 | * Accepting responsibility and apologising to those affected by our mistakes, 21 | and learning from the experience 22 | * Focusing on what is best not just for us as individuals, but for the 23 | overall community 24 | 25 | Examples of unacceptable behavior include: 26 | 27 | * The use of sexualised language or imagery, and sexual attention or 28 | advances 29 | * Trolling, insulting or derogatory comments, and personal or political attacks 30 | * Public or private harassment 31 | * Publishing others' private information, such as a physical or email 32 | address, without their explicit permission 33 | * Other conduct which could reasonably be considered inappropriate in a 34 | professional setting 35 | 36 | ## Our Responsibilities 37 | 38 | Project maintainers are responsible for clarifying and enforcing our standards of 39 | acceptable behavior and will take appropriate and fair corrective action in 40 | response to any instances of unacceptable behavior. 41 | 42 | Project maintainers have the right and responsibility to remove, edit, or reject 43 | comments, commits, code, wiki edits, issues, and other contributions that are 44 | not aligned to this Code of Conduct, or to ban 45 | temporarily or permanently any contributor for other behaviors that they deem 46 | inappropriate, threatening, offensive, or harmful. 47 | 48 | ## Scope 49 | 50 | This Code of Conduct applies within all community spaces, and also applies when 51 | an individual is officially representing the community in public spaces. 52 | Examples of representing our community include using an official e-mail address, 53 | posting via an official social media account, or acting as an appointed 54 | representative at an online or offline event. 55 | 56 | ## Enforcement 57 | 58 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 59 | reported to the community leaders responsible for enforcement at . 60 | All complaints will be reviewed and investigated promptly and fairly. 61 | 62 | All community leaders are obligated to respect the privacy and security of the 63 | reporter of any incident. 64 | 65 | ## Attribution 66 | 67 | This Code of Conduct is adapted from the [Contributor Covenant](https://contributor-covenant.org/), version 68 | [1.4](https://www.contributor-covenant.org/version/1/4/code-of-conduct/code_of_conduct.md) and 69 | [2.0](https://www.contributor-covenant.org/version/2/0/code_of_conduct/code_of_conduct.md), 70 | and was generated by [contributing-gen](https://github.com/bttger/contributing-gen). 71 | -------------------------------------------------------------------------------- /docs/source/tutorials/aluminium_tutorial.rst: -------------------------------------------------------------------------------- 1 | .. aluminium: 2 | 3 | ================== 4 | Aluminium tutorial 5 | ================== 6 | 7 | This tutorial will guide you through the process of performing RAFFLE-based structure search for the bulk phases of aluminium. 8 | 9 | The tutorial is designed to show how a RAFFLE generator given no prior knowledge can learn bonding and identify known phases. 10 | This is not an expected use-case of RAFFLE due to its application to a bulk system, but still demonstrates the expected workflow and capabilities. 11 | 12 | The example script can be found in the following directory: 13 | 14 | .. code-block:: bash 15 | 16 | raffle/example/python_pkg/Al_learn/DRAFFLE/learn.py 17 | 18 | We recommend reading through the file and running it to understand the process of learning and generating structures. 19 | However, we will provide a brief overview of the script here. 20 | 21 | First, we must import the required packages: 22 | 23 | .. code-block:: python 24 | 25 | from ase import Atoms 26 | from raffle.generator import raffle_generator 27 | from chgnet.model import CHGNetCalculator 28 | import numpy as np 29 | 30 | Next, we need to set up the RAFFLE generator and the calculator to calculate the energies of the structures. 31 | In this example, we use the CHGNet calculator: 32 | 33 | .. code-block:: python 34 | 35 | generator = raffle_generator() 36 | 37 | calc = CHGNetCalculator() 38 | 39 | Then, we need to create the host structure. 40 | Here, a set of host cells are generated to represent the multiple potential bulk phases of aluminium. 41 | These are then used to generate the structures. 42 | 43 | .. code-block:: python 44 | 45 | crystal_structures = ['orthorhombic', 'hcp'] 46 | hosts = [] 47 | for crystal_structure in crystal_structures: 48 | for a in np.linspace(3.1, 5.4, num=6): 49 | atom = build.bulk( 50 | name = 'Al', 51 | crystalstructure = crystal_structure, 52 | a = a, b = a, c = a, 53 | ) 54 | hosts.append(Atoms( 55 | 'Al', 56 | positions = [(0, 0, 0)], 57 | cell = atom.get_cell(), 58 | pbc = True, 59 | calculator = calc 60 | )) 61 | 62 | The script then sets parameters for the generator and provides an initial database. 63 | Note, this database is effectively empty, as it only contains a single structure, which is an isolated aluminium atom. 64 | 65 | .. code-block:: python 66 | 67 | initial_database = [Atoms('Al', positions=[(0, 0, 0)], cell=[8, 8, 8], pbc=True)] 68 | initial_database[0].calc = calc 69 | generator.distributions.create(initial_database) 70 | 71 | Finally, the script generates structures using the generator. 72 | The generator is given the host structures. 73 | Finally, the generator is run for each host structure, providing a unique stoichiometry each time and using a custom method ratio. 74 | 75 | .. code-block:: python 76 | 77 | for host in hosts: 78 | generator.set_host(host) 79 | generator.generate( 80 | num_structures = 5, 81 | stoichiometry = { 'Al': num_atoms }, 82 | method_ratio = {"void": 0.5, "rand": 0.001, "walk": 0.5, "grow": 0.0, "min": 1.0}, 83 | ) 84 | 85 | structures = generator.get_structures() 86 | write('structures.traj', structures) 87 | -------------------------------------------------------------------------------- /example/data/C-MgO_hosts/POSCAR_4x4_11.0A_separation: -------------------------------------------------------------------------------- 1 | c1 2 | 1.000000000 3 | 9.855999947 0.000000000 0.000000000 4 | -4.927999973 8.535546333 0.000000000 5 | 0.000000000 0.000000000 14.710999966 6 | C 7 | 64 8 | Direct 9 | 0.000000000 0.000000000 0.000000000 10 | 0.750000000 0.000000000 0.000000000 11 | 0.000000000 0.750000000 0.000000000 12 | 0.750000000 0.750000000 0.000000000 13 | 0.250000000 0.000000000 0.000000000 14 | 0.250000000 0.750000000 0.000000000 15 | 0.500000000 0.000000000 0.000000000 16 | 0.500000000 0.750000000 0.000000000 17 | 0.000000000 0.250000000 0.000000000 18 | 0.750000000 0.250000000 0.000000000 19 | 0.250000000 0.250000000 0.000000000 20 | 0.500000000 0.250000000 0.000000000 21 | 0.000000000 0.500000000 0.000000000 22 | 0.750000000 0.500000000 0.000000000 23 | 0.250000000 0.500000000 0.000000000 24 | 0.500000000 0.500000000 0.000000000 25 | 0.000000000 0.000000000 0.749999982 26 | 0.750000000 0.000000000 0.749999982 27 | 0.000000000 0.750000000 0.749999982 28 | 0.750000000 0.750000000 0.749999982 29 | 0.250000000 0.000000000 0.749999982 30 | 0.250000000 0.750000000 0.749999982 31 | 0.500000000 0.000000000 0.749999982 32 | 0.500000000 0.750000000 0.749999982 33 | 0.000000000 0.250000000 0.749999982 34 | 0.750000000 0.250000000 0.749999982 35 | 0.250000000 0.250000000 0.749999982 36 | 0.500000000 0.250000000 0.749999982 37 | 0.000000000 0.500000000 0.749999982 38 | 0.750000000 0.500000000 0.749999982 39 | 0.250000000 0.500000000 0.749999982 40 | 0.500000000 0.500000000 0.749999982 41 | 0.083333335 0.166666671 0.000000000 42 | 0.833333335 0.166666671 0.000000000 43 | 0.083333335 0.916666671 0.000000000 44 | 0.833333335 0.916666671 0.000000000 45 | 0.333333335 0.166666671 0.000000000 46 | 0.333333335 0.916666671 0.000000000 47 | 0.583333335 0.166666671 0.000000000 48 | 0.583333335 0.916666671 0.000000000 49 | 0.083333335 0.416666671 0.000000000 50 | 0.833333335 0.416666671 0.000000000 51 | 0.333333335 0.416666671 0.000000000 52 | 0.583333335 0.416666671 0.000000000 53 | 0.083333335 0.666666671 0.000000000 54 | 0.833333335 0.666666671 0.000000000 55 | 0.333333335 0.666666671 0.000000000 56 | 0.583333335 0.666666671 0.000000000 57 | 0.166666664 0.083333329 0.749999982 58 | 0.916666664 0.083333329 0.749999982 59 | 0.166666664 0.833333329 0.749999982 60 | 0.916666664 0.833333329 0.749999982 61 | 0.416666664 0.083333329 0.749999982 62 | 0.416666664 0.833333329 0.749999982 63 | 0.666666665 0.083333329 0.749999982 64 | 0.666666665 0.833333329 0.749999982 65 | 0.166666664 0.333333329 0.749999982 66 | 0.916666664 0.333333329 0.749999982 67 | 0.416666664 0.333333329 0.749999982 68 | 0.666666665 0.333333329 0.749999982 69 | 0.166666664 0.583333328 0.749999982 70 | 0.916666664 0.583333328 0.749999982 71 | 0.416666664 0.583333328 0.749999982 72 | 0.666666665 0.583333328 0.749999982 73 | -------------------------------------------------------------------------------- /example/data/C-MgO_hosts/POSCAR_4x4_14.7A_separation: -------------------------------------------------------------------------------- 1 | c1 2 | 1.000000000 3 | 9.855999947 0.000000000 0.000000000 4 | -4.927999973 8.535546333 0.000000000 5 | 0.000000000 0.000000000 18.388833288 6 | C 7 | 64 8 | Direct 9 | 0.000000000 0.000000000 0.000000000 10 | 0.750000000 0.000000000 0.000000000 11 | 0.000000000 0.750000000 0.000000000 12 | 0.750000000 0.750000000 0.000000000 13 | 0.250000000 0.000000000 0.000000000 14 | 0.250000000 0.750000000 0.000000000 15 | 0.500000000 0.000000000 0.000000000 16 | 0.500000000 0.750000000 0.000000000 17 | 0.000000000 0.250000000 0.000000000 18 | 0.750000000 0.250000000 0.000000000 19 | 0.250000000 0.250000000 0.000000000 20 | 0.500000000 0.250000000 0.000000000 21 | 0.000000000 0.500000000 0.000000000 22 | 0.750000000 0.500000000 0.000000000 23 | 0.250000000 0.500000000 0.000000000 24 | 0.500000000 0.500000000 0.000000000 25 | 0.000000000 0.000000000 0.800000892 26 | 0.750000000 0.000000000 0.800000892 27 | 0.000000000 0.750000000 0.800000892 28 | 0.750000000 0.750000000 0.800000892 29 | 0.250000000 0.000000000 0.800000892 30 | 0.250000000 0.750000000 0.800000892 31 | 0.500000000 0.000000000 0.800000892 32 | 0.500000000 0.750000000 0.800000892 33 | 0.000000000 0.250000000 0.800000892 34 | 0.750000000 0.250000000 0.800000892 35 | 0.250000000 0.250000000 0.800000892 36 | 0.500000000 0.250000000 0.800000892 37 | 0.000000000 0.500000000 0.800000892 38 | 0.750000000 0.500000000 0.800000892 39 | 0.250000000 0.500000000 0.800000892 40 | 0.500000000 0.500000000 0.800000892 41 | 0.083333335 0.166666671 0.000000000 42 | 0.833333335 0.166666671 0.000000000 43 | 0.083333335 0.916666671 0.000000000 44 | 0.833333335 0.916666671 0.000000000 45 | 0.333333335 0.166666671 0.000000000 46 | 0.333333335 0.916666671 0.000000000 47 | 0.583333335 0.166666671 0.000000000 48 | 0.583333335 0.916666671 0.000000000 49 | 0.083333335 0.416666671 0.000000000 50 | 0.833333335 0.416666671 0.000000000 51 | 0.333333335 0.416666671 0.000000000 52 | 0.583333335 0.416666671 0.000000000 53 | 0.083333335 0.666666671 0.000000000 54 | 0.833333335 0.666666671 0.000000000 55 | 0.333333335 0.666666671 0.000000000 56 | 0.583333335 0.666666671 0.000000000 57 | 0.166666664 0.083333329 0.800000892 58 | 0.916666664 0.083333329 0.800000892 59 | 0.166666664 0.833333329 0.800000892 60 | 0.916666664 0.833333329 0.800000892 61 | 0.416666664 0.083333329 0.800000892 62 | 0.416666664 0.833333329 0.800000892 63 | 0.666666665 0.083333329 0.800000892 64 | 0.666666665 0.833333329 0.800000892 65 | 0.166666664 0.333333329 0.800000892 66 | 0.916666664 0.333333329 0.800000892 67 | 0.416666664 0.333333329 0.800000892 68 | 0.666666665 0.333333329 0.800000892 69 | 0.166666664 0.583333328 0.800000892 70 | 0.916666664 0.583333328 0.800000892 71 | 0.416666664 0.583333328 0.800000892 72 | 0.666666665 0.583333328 0.800000892 73 | -------------------------------------------------------------------------------- /tools/check_accuracy_MoS2.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | from pathlib import Path 4 | 5 | script_dir = Path(__file__).resolve().parent 6 | 7 | ## import ASE (Atomic Simulation Environment) modules 8 | from ase import Atoms 9 | from ase.io import read, write 10 | 11 | 12 | ## load calculator 13 | from chgnet.model.dynamics import CHGNetCalculator 14 | print("Initialising CHGNet calculator") 15 | chgnet = CHGNetCalculator() 16 | from mace.calculators import mace_mp 17 | print("Initialising MACE calculator") 18 | calc_params = { 'model': "../example/python_pkg/mace-mpa-0-medium.model" } 19 | mace = mace_mp(**calc_params) 20 | # calc = mace_mp(model="medium", dispersion=False, default_dtype="float32", device='cpu') 21 | 22 | ## Read the database 23 | print("Reading database") 24 | database = read("../example/data/MoS2_vasp.xyz", index=":") 25 | 26 | # get index of lowest energy structure 27 | lowest_energy_index = np.argmin([ 28 | atoms.get_potential_energy() if atoms.calc is not None else float('inf') 29 | for atoms in database 30 | ]) 31 | MoS2_energy_dft = database[lowest_energy_index].get_potential_energy() / len(database[lowest_energy_index]) 32 | MoS2_ground_state = database[lowest_energy_index].copy() 33 | MoS2_ground_state.calc = chgnet 34 | MoS2_energy_chgnet = MoS2_ground_state.get_potential_energy() / len(MoS2_ground_state) 35 | MoS2_ground_state.calc = mace 36 | MoS2_energy_mace = MoS2_ground_state.get_potential_energy() / len(MoS2_ground_state) 37 | 38 | 39 | ## Calculate the energies 40 | energies_dft = [] 41 | energies_mace = [] 42 | energies_chgnet = [] 43 | formation_energies_dft = [] 44 | formation_energies_mace = [] 45 | formation_energies_chgnet = [] 46 | for i, atoms in enumerate(database): 47 | if atoms.calc is None: 48 | database.remove(atoms) 49 | continue 50 | formation_energy_dft = atoms.get_potential_energy() / len(atoms) - MoS2_energy_dft 51 | formation_energies_dft.append(formation_energy_dft) 52 | energies_dft.append(atoms.get_potential_energy()/len(atoms)) 53 | atoms.calc = chgnet 54 | formation_energy_chgnet = atoms.get_potential_energy() / len(atoms) - MoS2_energy_chgnet 55 | formation_energies_chgnet.append(formation_energy_chgnet) 56 | energies_chgnet.append(atoms.get_potential_energy()/len(atoms)) 57 | atoms.calc = mace 58 | formation_energy_mace = atoms.get_potential_energy() / len(atoms) - MoS2_energy_mace 59 | formation_energies_mace.append(formation_energy_mace) 60 | energies_mace.append(atoms.get_potential_energy()/len(atoms)) 61 | 62 | 63 | import matplotlib.pyplot as plt 64 | 65 | ## Write energies to a file 66 | with open("MoS2_energies_comparison.txt", "w") as f: 67 | f.write("# DFT_Energy_per_atom MACE-MPA-0_Energy_per_atom CHGNet_Energy_per_atom\n") 68 | for dft_energy, mace_energy, chgnet_energy in zip(energies_dft, energies_mace, energies_chgnet): 69 | f.write(f"{dft_energy} {mace_energy} {chgnet_energy}\n") 70 | 71 | with open("MoS2_formations_comparison.txt", "w") as f: 72 | f.write("# DFT_Formation_energy_per_atom MACE-MPA-0_Formation_energy_per_atom CHGNet_Formation_energy_per_atom\n") 73 | for dft_energy, mace_energy, chgnet_energy in zip(formation_energies_dft, formation_energies_mace, formation_energies_chgnet): 74 | f.write(f"{dft_energy} {mace_energy} {chgnet_energy}\n") 75 | 76 | ## Plot the energies 77 | plt.figure(figsize=(10, 6)) 78 | plt.scatter(energies_dft, energies_mace, c='blue', marker='o', label='MLIP vs DFT') 79 | plt.show() -------------------------------------------------------------------------------- /tools/check_accuracy_Al.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | 4 | ## import ASE (Atomic Simulation Environment) modules 5 | from ase import Atoms 6 | from ase.io import read, write 7 | 8 | 9 | ## load calculator 10 | from chgnet.model.dynamics import CHGNetCalculator 11 | print("Initialising CHGNet calculator") 12 | chgnet = CHGNetCalculator() 13 | from mace.calculators import mace_mp 14 | print("Initialising MACE calculator") 15 | calc_params = { 'model': "../example/python_pkg/mace-mpa-0-medium.model" } 16 | mace = mace_mp(**calc_params) 17 | # calc = mace_mp(model="medium", dispersion=False, default_dtype="float32", device='cpu') 18 | 19 | ## Read the database 20 | print("Reading database") 21 | database = read("../example/data/aluminium.xyz", index=":") 22 | 23 | # get index of lowest energy structure 24 | lowest_energy_index = np.argmin([ 25 | atoms.get_potential_energy() if atoms.calc is not None else float('inf') 26 | for atoms in database 27 | ]) 28 | Al_energy_dft = database[lowest_energy_index].get_potential_energy() / len(database[lowest_energy_index]) 29 | Al_ground_state = database[lowest_energy_index].copy() 30 | Al_ground_state.calc = chgnet 31 | Al_energy_chgnet = Al_ground_state.get_potential_energy() / len(Al_ground_state) 32 | Al_ground_state.calc = mace 33 | Al_energy_mace = Al_ground_state.get_potential_energy() / len(Al_ground_state) 34 | 35 | # Al_reference_energy_dft = -0.19810165 36 | # print("Al_reference_energy_mace: ", Al_reference_energy_mlp) 37 | # print("Al_reference_energy_dft: ", Al_reference_energy_dft) 38 | 39 | 40 | ## Calculate the energies 41 | energies_dft = [] 42 | energies_mace = [] 43 | energies_chgnet = [] 44 | formation_energies_dft = [] 45 | formation_energies_mace = [] 46 | formation_energies_chgnet = [] 47 | for i, atoms in enumerate(database): 48 | if atoms.calc is None: 49 | database.remove(atoms) 50 | continue 51 | formation_energy_dft = atoms.get_potential_energy() / len(atoms) - Al_energy_dft 52 | formation_energies_dft.append(formation_energy_dft) 53 | energies_dft.append(atoms.get_potential_energy()/len(atoms)) 54 | atoms.calc = chgnet 55 | formation_energy_chgnet = atoms.get_potential_energy() / len(atoms) - Al_energy_chgnet 56 | formation_energies_chgnet.append(formation_energy_chgnet) 57 | energies_chgnet.append(atoms.get_potential_energy()/len(atoms)) 58 | atoms.calc = mace 59 | formation_energy_mace = atoms.get_potential_energy() / len(atoms) - Al_energy_mace 60 | formation_energies_mace.append(formation_energy_mace) 61 | energies_mace.append(atoms.get_potential_energy()/len(atoms)) 62 | 63 | 64 | import matplotlib.pyplot as plt 65 | 66 | ## Write energies to a file 67 | with open("Al_energies_comparison.txt", "w") as f: 68 | f.write("# DFT_Energy_per_atom MACE-MPA-0_Energy_per_atom CHGNet_Energy_per_atom\n") 69 | for dft_energy, mace_energy, chgnet_energy in zip(energies_dft, energies_mace, energies_chgnet): 70 | f.write(f"{dft_energy} {mace_energy} {chgnet_energy}\n") 71 | 72 | with open("Al_formations_comparison.txt", "w") as f: 73 | f.write("# DFT_Formation_energy_per_atom MACE-MPA-0_Formation_energy_per_atom CHGNet_Formation_energy_per_atom\n") 74 | for dft_energy, mace_energy, chgnet_energy in zip(formation_energies_dft, formation_energies_mace, formation_energies_chgnet): 75 | f.write(f"{dft_energy} {mace_energy} {chgnet_energy}\n") 76 | 77 | ## Plot the energies 78 | plt.figure(figsize=(10, 6)) 79 | plt.scatter(energies_dft, energies_mace, c='blue', marker='o', label='MLIP vs DFT') 80 | plt.show() -------------------------------------------------------------------------------- /test/test_cache.f90: -------------------------------------------------------------------------------- 1 | program test_cache 2 | use raffle__io_utils 3 | use raffle__cache 4 | use raffle__constants, only: real32 5 | implicit none 6 | 7 | logical :: success = .true. 8 | 9 | call test_retrieve_unallocated(success) 10 | call test_store_retrieve_probability_density(success) 11 | 12 | !----------------------------------------------------------------------------- 13 | ! check for any failed tests 14 | !----------------------------------------------------------------------------- 15 | write(*,*) "----------------------------------------" 16 | if(success)then 17 | write(*,*) 'test_cache passed all tests' 18 | else 19 | write(0,*) 'test_cache failed one or more tests' 20 | stop 1 21 | end if 22 | 23 | contains 24 | 25 | subroutine test_store_retrieve_probability_density(success) 26 | implicit none 27 | logical, intent(inout) :: success 28 | real(real32), allocatable :: test_data(:,:), retrieved_data(:,:) 29 | integer :: i, j 30 | 31 | ! Create test data - a 3x3 matrix with values 32 | allocate(test_data(3,3)) 33 | do i = 1, 3 34 | do j = 1, 3 35 | test_data(i,j) = real(i*10 + j, real32) 36 | end do 37 | end do 38 | 39 | ! Store the test data in the cache 40 | call store_probability_density(test_data) 41 | 42 | ! Retrieve the data from the cache 43 | retrieved_data = retrieve_probability_density() 44 | 45 | ! Check dimensions match 46 | if (.not. all(shape(retrieved_data) == shape(test_data))) then 47 | write(0,*) 'test_store_retrieve_probability_density: array shapes do not match' 48 | success = .false. 49 | return 50 | end if 51 | 52 | ! Check all values match 53 | do i = 1, 3 54 | do j = 1, 3 55 | if (abs(retrieved_data(i,j) - test_data(i,j)) .gt. 1.e-6_real32) then 56 | write(0,*) & 57 | 'test_store_retrieve_probability_density: values do not match at', & 58 | i, j, retrieved_data(i,j), test_data(i,j) 59 | success = .false. 60 | return 61 | end if 62 | end do 63 | end do 64 | 65 | ! Clean up 66 | if (allocated(test_data)) deallocate(test_data) 67 | if (allocated(retrieved_data)) deallocate(retrieved_data) 68 | 69 | write(*,*) 'test_store_retrieve_probability_density: PASSED' 70 | end subroutine test_store_retrieve_probability_density 71 | 72 | subroutine test_retrieve_unallocated(success) 73 | implicit none 74 | logical, intent(inout) :: success 75 | real(real32), allocatable :: retrieved_data(:,:) 76 | 77 | ! Try to retrieve data when cache is not allocated 78 | retrieved_data = retrieve_probability_density() 79 | 80 | ! Verify returned array is a scalar with value 0 81 | if (size(retrieved_data) .ne. 1) then 82 | write(0,*) & 83 | 'test_retrieve_unallocated: returned array should be scalar but has size', & 84 | size(retrieved_data) 85 | success = .false. 86 | return 87 | end if 88 | 89 | if (abs(retrieved_data(1,1)) .gt. 1.e-6_real32) then 90 | write(0,*) & 91 | 'test_retrieve_unallocated: returned value should be 0 but is', & 92 | retrieved_data(1,1) 93 | success = .false. 94 | return 95 | end if 96 | 97 | ! Clean up 98 | if (allocated(retrieved_data)) deallocate(retrieved_data) 99 | 100 | write(*,*) 'test_retrieve_unallocated: PASSED' 101 | end subroutine test_retrieve_unallocated 102 | 103 | end program test_cache 104 | -------------------------------------------------------------------------------- /test/test_misc_maths.f90: -------------------------------------------------------------------------------- 1 | program test_misc_maths 2 | use raffle__io_utils, only: test_error_handling 3 | use raffle__misc_maths 4 | use raffle__constants, only: real32 5 | implicit none 6 | 7 | logical :: success = .true. 8 | 9 | test_error_handling = .true. 10 | 11 | 12 | call test_lnsum(success) 13 | call test_triangular_number(success) 14 | call test_set_difference(success) 15 | 16 | 17 | !----------------------------------------------------------------------------- 18 | ! check for any failed tests 19 | !----------------------------------------------------------------------------- 20 | write(*,*) "----------------------------------------" 21 | if(success)then 22 | write(*,*) 'test_misc_maths passed all tests' 23 | else 24 | write(0,*) 'test_misc_maths failed one or more tests' 25 | stop 1 26 | end if 27 | 28 | contains 29 | 30 | subroutine test_lnsum(success) 31 | implicit none 32 | logical, intent(inout) :: success 33 | integer :: n 34 | real(real32) :: result 35 | 36 | n = 5 37 | result = lnsum(n) 38 | call assert( & 39 | abs( & 40 | result - & 41 | ( & 42 | log(1.0_real32) + & 43 | log(2.0_real32) + & 44 | log(3.0_real32) + & 45 | log(4.0_real32) + & 46 | log(5.0_real32) & 47 | ) & 48 | ) .lt. 1.E-6_real32, & 49 | 'lnsum failed', & 50 | success & 51 | ) 52 | end subroutine test_lnsum 53 | 54 | subroutine test_triangular_number(success) 55 | implicit none 56 | logical, intent(inout) :: success 57 | integer :: n, result 58 | 59 | n = 5 60 | result = triangular_number(n) 61 | call assert( & 62 | result .eq. 15, & 63 | 'Triangular number failed', & 64 | success & 65 | ) 66 | end subroutine test_triangular_number 67 | 68 | subroutine test_set_difference(success) 69 | implicit none 70 | logical, intent(inout) :: success 71 | real(real32), dimension(3) :: a, b, result, expected 72 | real(real32), dimension(4) :: c 73 | 74 | a = [1.0_real32, 2.0_real32, 3.0_real32] 75 | b = [1.0_real32, 1.0_real32, 1.0_real32] 76 | expected = [0.0_real32, 1.0_real32, 2.0_real32] 77 | result = set_difference(a, b) 78 | 79 | call assert( & 80 | all( abs(result - expected) .lt. 1.E-6_real32 ), & 81 | 'Set difference failed', & 82 | success & 83 | ) 84 | 85 | b = [0.0_real32, 1.0_real32, 4.0_real32] 86 | expected = [1.0_real32, 1.0_real32, 0.0_real32] 87 | result = set_difference(a, b, set_min_zero=.true.) 88 | 89 | call assert( & 90 | all( abs(result - expected) .lt. 1.E-6_real32 ), & 91 | 'Set difference min zero failed', & 92 | success & 93 | ) 94 | 95 | c = [1.0_real32, 2.0_real32, 3.0_real32, 4.0_real32] 96 | write(*,*) "Testing set_difference error handling" 97 | result = set_difference(a, c) 98 | write(*,*) "Handled error: set difference of arrays of different lengths" 99 | 100 | 101 | end subroutine test_set_difference 102 | 103 | !############################################################################### 104 | 105 | subroutine assert(condition, message, success) 106 | implicit none 107 | logical, intent(in) :: condition 108 | character(len=*), intent(in) :: message 109 | logical, intent(inout) :: success 110 | if (.not. condition) then 111 | write(0,*) "Test failed: ", message 112 | success = .false. 113 | end if 114 | end subroutine assert 115 | 116 | end program test_misc_maths -------------------------------------------------------------------------------- /example/python_pkg/benchmarks/create_gdfs.py: -------------------------------------------------------------------------------- 1 | import os 2 | nthreads = 1 3 | os.environ["OMP_NUM_THREADS"] = str(nthreads) 4 | os.environ["OPENBLAS_NUM_THREADS"] = str(nthreads) 5 | os.environ["MKL_NUM_THREADS"] = str(nthreads) 6 | 7 | import glob 8 | from raffle.generator import raffle_generator 9 | import pytest 10 | from ase.io import read 11 | import time 12 | import numpy as np 13 | 14 | 15 | def get_xyz_files(): 16 | """Get all .xyz files from the ../../data directory""" 17 | current_dir = os.path.dirname(os.path.abspath(__file__)) 18 | data_dir = os.path.join(current_dir, '..', '..', '..', 'example', 'data') 19 | print("Data directory:", data_dir) 20 | return glob.glob(os.path.join(data_dir, '*.xyz')) 21 | 22 | 23 | @pytest.mark.parametrize("xyz_file", get_xyz_files()) 24 | @pytest.mark.parametrize("kBT", [0.2, 0.4, 0.6]) 25 | @pytest.mark.parametrize("width", [ 26 | [0.025, np.pi/200.0, np.pi/200.0], 27 | [0.05, np.pi/100.0, np.pi/100.0], 28 | [0.1, np.pi/50.0, np.pi/50.0] 29 | ]) 30 | @pytest.mark.benchmark( 31 | group="distributions", 32 | min_rounds=5, 33 | timer=time.time, 34 | disable_gc=True, 35 | warmup=False 36 | ) 37 | def test_distributions_create(benchmark, xyz_file, kBT, width): 38 | atoms = read(xyz_file, index=":") 39 | 40 | # Initialize generator 41 | generator = raffle_generator() 42 | 43 | # get list of elements in list of atoms 44 | elements = [] 45 | for atom in atoms: 46 | elements += atom.get_chemical_symbols() 47 | elements = list(set(elements)) 48 | energies = {element: 0.0 for element in elements} 49 | generator.distributions.set_element_energies(energies) 50 | 51 | avg_num_atoms = 0 52 | for atom in atoms: 53 | avg_num_atoms += len(atom) 54 | avg_num_atoms = round(avg_num_atoms / len(atoms)) 55 | 56 | benchmark.extra_info = { 57 | 'file': os.path.basename(xyz_file), 58 | 'num_structures': len(atoms), 59 | 'num_species': len(elements), 60 | "avg_num_atoms": avg_num_atoms, 61 | "kBT": kBT, 62 | "width": width 63 | } 64 | 65 | # set energy scale 66 | generator.distributions.set_kBT(kBT) 67 | 68 | # set the distribution function widths (2-body, 3-body, 4-body) 69 | generator.distributions.set_width(width) 70 | 71 | # Measure time for distributions.create() 72 | result = benchmark(generator.distributions.create, atoms) 73 | 74 | 75 | return { 76 | 'file': os.path.basename(xyz_file), 77 | 'time': result, 78 | 'num_structures': len(atoms), 79 | 'num_species': len(elements), 80 | "avg_num_atoms": avg_num_atoms 81 | } 82 | 83 | @pytest.fixture 84 | def make_customer_record(): 85 | def _make_customer_record(name): 86 | return {"name": name, "orders": []} 87 | 88 | return _make_customer_record 89 | 90 | if __name__ == '__main__': 91 | xyz_files = get_xyz_files() 92 | results = [] 93 | 94 | result = test_distributions_create(lambda x: x) 95 | # for xyz_file in xyz_files: 96 | # # for _ in range(5): # Run the benchmark 5 times for each file 97 | # result = test_distributions_create(lambda x: x, xyz_file) 98 | # results.append(result) 99 | 100 | # Print results 101 | print("\nBenchmark Results:") 102 | print("-" * 60) 103 | print(f"{'File':<20} {'Time (s)':<10} {'Num Structures':<10} {'Num Species':<10} {'Avg Num Atoms':<10}") 104 | print("-" * 60) 105 | for result in results: 106 | print(f"{result['file']:<20} {result['time']:<10.4f} {result['num_structures']:<10} {result['num_species']:<10} {result['avg_num_atoms']:<10}") -------------------------------------------------------------------------------- /.github/workflows/fpm.yml: -------------------------------------------------------------------------------- 1 | name: run-fpm-build 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | - development 8 | types: 9 | - opened 10 | - synchronize 11 | paths: 12 | - ".github/workflows/fpm.yml" 13 | - "fpm.toml" 14 | - "**.f90" 15 | - "**.F90" 16 | workflow_dispatch: 17 | 18 | permissions: 19 | contents: read 20 | pages: write 21 | id-token: write 22 | 23 | concurrency: 24 | group: fpm 25 | cancel-in-progress: false 26 | 27 | jobs: 28 | build-and-test-fpm-debug: 29 | environment: 30 | name: github-pages 31 | name: Build and test in debug mode 32 | runs-on: ubuntu-latest 33 | strategy: 34 | fail-fast: false 35 | matrix: 36 | os: [ubuntu-latest, macos-latest] 37 | toolchain: 38 | - {compiler: gcc, version: 13} 39 | - {fortran-compiler: gcc, fc-version: 14} 40 | # - {compiler: intel, version: '2024.1'} 41 | # - {compiler: intel-classic, version: '2021.10'} 42 | # exclude: 43 | # - os: macos-latest 44 | # toolchain: {compiler: intel, version: '2024.1'} 45 | # - os: macos-latest 46 | # toolchain: {compiler: intel-classic, version: '2021.10'} 47 | steps: 48 | - name: checkout repo 49 | uses: actions/checkout@v4 50 | 51 | - uses: fortran-lang/setup-fortran@v1 52 | id: setup-fortran 53 | with: 54 | compiler: ${{ matrix.toolchain.compiler }} 55 | version: ${{ matrix.toolchain.version }} 56 | 57 | - uses: fortran-lang/setup-fpm@v5 58 | id: setup-fpm 59 | with: 60 | fpm-version: "v0.10.0" 61 | 62 | - name: Install OpenMP runtime (Linux only) 63 | if: runner.os == 'Linux' 64 | run: sudo apt-get update && sudo apt-get install -y libgomp1 65 | 66 | - name: Compile 67 | run: | 68 | ${{ env.FC }} --version 69 | fpm build --profile debug --compiler ${{ env.FC }} 70 | 71 | - name: Test 72 | run: | 73 | ${{ env.FC }} --version 74 | fpm test --profile debug --compiler ${{ env.FC }} 75 | 76 | build-and-test-fpm-release: 77 | name: Build and test in release mode 78 | environment: 79 | name: github-pages 80 | runs-on: ubuntu-latest 81 | strategy: 82 | fail-fast: false 83 | matrix: 84 | os: [ubuntu-latest, macos-latest] 85 | toolchain: 86 | - {compiler: gcc, version: 13} 87 | # - {compiler: intel, version: '2024.1'} 88 | # - {compiler: intel-classic, version: '2021.10'} 89 | # exclude: 90 | # - os: macos-latest 91 | # toolchain: {compiler: intel, version: '2024.1'} 92 | # - os: macos-latest 93 | # toolchain: {compiler: intel-classic, version: '2021.10'} 94 | 95 | steps: 96 | - name: checkout repo 97 | uses: actions/checkout@v4 98 | 99 | - uses: fortran-lang/setup-fortran@v1 100 | id: setup-fortran 101 | with: 102 | compiler: ${{ matrix.toolchain.compiler }} 103 | version: ${{ matrix.toolchain.version }} 104 | 105 | - uses: fortran-lang/setup-fpm@v5 106 | id: setup-fpm 107 | with: 108 | fpm-version: "v0.10.0" 109 | 110 | - name: Install OpenMP runtime (Linux only) 111 | if: runner.os == 'Linux' 112 | run: sudo apt-get update && sudo apt-get install -y libgomp1 113 | 114 | - name: Compile 115 | run: | 116 | ${{ env.FC }} --version 117 | fpm build --profile release --compiler ${{ env.FC }} 118 | 119 | - name: Test 120 | run: | 121 | ${{ env.FC }} --version 122 | fpm test --profile release --compiler ${{ env.FC }} 123 | -------------------------------------------------------------------------------- /docs/source/tutorials/quick_guide.rst: -------------------------------------------------------------------------------- 1 | .. quick_guide: 2 | 3 | =========== 4 | Quick guide 5 | =========== 6 | 7 | 8 | The quick guide is designed to give a brief overview of the steps required to run a RAFFLE calculation. 9 | It is assumed that the user has already installed RAFFLE and has a basic understanding of the command line. 10 | For a more detailed explanation of the parameters and options available, please see the :doc:`Main tutorial page ` for individual tutorials detailing each step. 11 | 12 | 13 | RAFFLE is a random structure search package designed primarily for interfaces. 14 | The tutorials will use bulk systems to demonstrate its functionality, but it is recommended to use packages such as `AIRSS `_ for bulk random structure search. 15 | 16 | 17 | Single iteration 18 | ---------------- 19 | 20 | Here is a script to run a single iteration of the RAFFLE generator for structure search. 21 | 22 | .. code-block:: python 23 | 24 | # Single iteration of RAFFLE structure search 25 | from ase.io import read, write 26 | from raffle.generator import raffle_generator 27 | 28 | generator = raffle_generator() 29 | 30 | host = read("host.xyz") 31 | generator.set_host(host) 32 | generator.set_grid(grid_spacing=0.1) 33 | generator.set_bounds([[0, 0, 0.5], [1, 1, 0.75]]) 34 | generator.distributions.set_element_energies( 35 | { 'C': -9.063733 } 36 | ) 37 | 38 | database = read("database.xyz", index=":") 39 | generator.distributions.create(database) 40 | 41 | structures = generator.generate( 42 | num_structures = 1, 43 | stoichiometry = { 'C': 2 }, 44 | ) 45 | 46 | write("output.xyz", structures) 47 | 48 | This script will generate a single structure with a stoichiometry of two carbon atoms. 49 | The host structure is read from a file, and the grid spacing and bounds are set. 50 | The element energies are set to the energy of carbon, and the database is read from a file. 51 | The generator is then run, and the structures are written to an output file. 52 | 53 | 54 | Iterative structure search 55 | -------------------------- 56 | 57 | Here is an example of how to run an iterative structure search with RAFFLE and check for convergence. 58 | 59 | .. code-block:: python 60 | 61 | # Iterative RAFFLE structure search 62 | from ase.io import read, write 63 | from ase.optimize import FIRE 64 | from raffle.generator import raffle_generator 65 | from mace.calculators import mace_mp 66 | 67 | generator = raffle_generator() 68 | generator.distributions.set_history_len(10) 69 | calc = mace_mp(model="medium", dispersion=False, default_dtype="float32", device='cpu') 70 | 71 | host = read("host.xyz") 72 | generator.set_host(host) 73 | generator.set_grid(grid_spacing=0.1) 74 | generator.set_bounds([[0, 0, 0.5], [1, 1, 0.75]]) 75 | generator.distributions.set_element_energies( 76 | { 'C': -9.063733 } 77 | ) 78 | 79 | database = read("database.xyz", index=":") 80 | generator.distributions.create(database) 81 | 82 | num_structures_old = 0 83 | rlxd_structures = [] 84 | for i in range(10): 85 | structures = generator.generate( 86 | num_structures = 2, 87 | stoichiometry = { 'C': 2 }, 88 | calc = calc 89 | ) 90 | for structure in structures: 91 | optimiser = FIRE(structure) 92 | optimiser.run(fmax=0.05) 93 | 94 | generator.distributions.update(structures) 95 | rlxd_structures.extend(structures) 96 | if generator.distributions.is_converged(): 97 | break 98 | 99 | write("output.xyz", structures) 100 | -------------------------------------------------------------------------------- /example/python_pkg/diamond/POSCAR_host_3x3: -------------------------------------------------------------------------------- 1 | C8 2 | 1.000000000 3 | 14.242980436 0.000000000 0.000000000 4 | 0.000000000 14.242980436 0.000000000 5 | 0.000000000 0.000000000 7.121490218 6 | C 7 | 72 8 | Direct 9 | 0.000000000 0.000000000 0.000000000 10 | 0.333333333 0.000000000 0.000000000 11 | 0.666666667 0.000000000 0.000000000 12 | 0.000000000 0.333333333 0.000000000 13 | 0.333333333 0.333333333 0.000000000 14 | 0.666666667 0.333333333 0.000000000 15 | 0.000000000 0.666666667 0.000000000 16 | 0.333333333 0.666666667 0.000000000 17 | 0.666666667 0.666666667 0.000000000 18 | 0.166666667 0.166666667 0.000000000 19 | 0.500000000 0.166666667 0.000000000 20 | 0.833333333 0.166666667 0.000000000 21 | 0.166666667 0.500000000 0.000000000 22 | 0.500000000 0.500000000 0.000000000 23 | 0.833333333 0.500000000 0.000000000 24 | 0.166666667 0.833333333 0.000000000 25 | 0.500000000 0.833333333 0.000000000 26 | 0.833333333 0.833333333 0.000000000 27 | 0.166666667 0.000000000 0.250000000 28 | 0.500000000 0.000000000 0.250000000 29 | 0.833333333 0.000000000 0.250000000 30 | 0.166666667 0.333333333 0.250000000 31 | 0.500000000 0.333333333 0.250000000 32 | 0.833333333 0.333333333 0.250000000 33 | 0.166666667 0.666666667 0.250000000 34 | 0.500000000 0.666666667 0.250000000 35 | 0.833333333 0.666666667 0.250000000 36 | 0.000000000 0.166666667 0.250000000 37 | 0.333333333 0.166666667 0.250000000 38 | 0.666666667 0.166666667 0.250000000 39 | 0.000000000 0.500000000 0.250000000 40 | 0.333333333 0.500000000 0.250000000 41 | 0.666666667 0.500000000 0.250000000 42 | 0.000000000 0.833333333 0.250000000 43 | 0.333333333 0.833333333 0.250000000 44 | 0.666666667 0.833333333 0.250000000 45 | 0.083333333 0.083333333 0.125000000 46 | 0.416666667 0.083333333 0.125000000 47 | 0.750000000 0.083333333 0.125000000 48 | 0.083333333 0.416666667 0.125000000 49 | 0.416666667 0.416666667 0.125000000 50 | 0.750000000 0.416666667 0.125000000 51 | 0.083333333 0.750000000 0.125000000 52 | 0.416666667 0.750000000 0.125000000 53 | 0.750000000 0.750000000 0.125000000 54 | 0.250000000 0.250000000 0.125000000 55 | 0.583333333 0.250000000 0.125000000 56 | 0.916666667 0.250000000 0.125000000 57 | 0.250000000 0.583333333 0.125000000 58 | 0.583333333 0.583333333 0.125000000 59 | 0.916666667 0.583333333 0.125000000 60 | 0.250000000 0.916666667 0.125000000 61 | 0.583333333 0.916666667 0.125000000 62 | 0.916666667 0.916666667 0.125000000 63 | 0.250000000 0.083333333 0.375000000 64 | 0.583333333 0.083333333 0.375000000 65 | 0.916666667 0.083333333 0.375000000 66 | 0.250000000 0.416666667 0.375000000 67 | 0.583333333 0.416666667 0.375000000 68 | 0.916666667 0.416666667 0.375000000 69 | 0.250000000 0.750000000 0.375000000 70 | 0.583333333 0.750000000 0.375000000 71 | 0.916666667 0.750000000 0.375000000 72 | 0.083333333 0.250000000 0.375000000 73 | 0.416666667 0.250000000 0.375000000 74 | 0.750000000 0.250000000 0.375000000 75 | 0.083333333 0.583333333 0.375000000 76 | 0.416666667 0.583333333 0.375000000 77 | 0.750000000 0.583333333 0.375000000 78 | 0.083333333 0.916666667 0.375000000 79 | 0.416666667 0.916666667 0.375000000 80 | 0.750000000 0.916666667 0.375000000 81 | -------------------------------------------------------------------------------- /.github/workflows/coverage.yml: -------------------------------------------------------------------------------- 1 | name: run-code-coverage 2 | 3 | on: 4 | push: 5 | branches: 6 | - "main" 7 | paths: 8 | - ".github/workflows/coverage.yml" 9 | - "CMakeLists.txt" 10 | - "**.f90" 11 | - "**.F90" 12 | - "**.cmake" 13 | pull_request: 14 | branches: 15 | - "main" 16 | types: 17 | - opened 18 | - synchronize 19 | paths: 20 | - ".github/workflows/coverage.yml" 21 | - "CMakeLists.txt" 22 | - "**.f90" 23 | - "**.F90" 24 | - "**.cmake" 25 | workflow_dispatch: 26 | 27 | permissions: 28 | contents: read 29 | pages: write 30 | id-token: write 31 | 32 | concurrency: 33 | group: pages 34 | cancel-in-progress: false 35 | 36 | jobs: 37 | run-code-coverage: 38 | # permissions: 39 | # contents: write 40 | environment: 41 | name: github-pages 42 | url: ${{ steps.deployment.outputs.page_url }} 43 | runs-on: ubuntu-latest 44 | strategy: 45 | fail-fast: false 46 | matrix: 47 | compiler: [gcc] 48 | version: [13] 49 | steps: 50 | - name: checkout repo 51 | uses: actions/checkout@v4 52 | 53 | - name: actions-setup-cmake 54 | uses: jwlawson/actions-setup-cmake@v2 55 | with: 56 | cmake-version: '3.24.x' 57 | 58 | - uses: fortran-lang/setup-fortran@v1 59 | id: setup-fortran 60 | with: 61 | compiler: ${{ matrix.compiler }} 62 | version: ${{ matrix.version }} 63 | 64 | - name: Install gcovr 65 | run: | 66 | pip --version 67 | pip install gcovr 68 | 69 | - name: Build project 70 | run: | 71 | sudo apt-get update 72 | sudo apt-get install -y cmake make 73 | cmake --version 74 | mkdir -p build 75 | cd build 76 | cmake -DCMAKE_BUILD_TYPE=Coverage -DBUILD_PYTHON=Off -DBUILD_EXECUTABLE=Off .. 77 | make 78 | 79 | - name: Run coverage tests 80 | run: | 81 | cd build 82 | env CTEST_OUTPUT_ON_FAILURE=1 make coverage 83 | 84 | - name: Get coverage percentage 85 | run: | 86 | pip install bs4 87 | echo "COVERAGE_PERCENTAGE="$(python ./tools/coverage_badge.py) >> $GITHUB_ENV 88 | 89 | - name: Create coverage badge 90 | uses: schneegans/dynamic-badges-action@v1.7.0 91 | with: 92 | auth: ${{ secrets.GIST_SECRET }} 93 | gistID: 48f14ebb5636b54d3813e4b4494903eb 94 | filename: raffle_coverage_${{ github.head_ref || github.ref_name }}.json # Use branch-specific file 95 | label: Coverage 96 | message: ${{ env.COVERAGE_PERCENTAGE }}% 97 | valColorRange: ${{ env.COVERAGE_PERCENTAGE }} 98 | maxColorRange: 100 99 | minColorRange: 0 100 | 101 | - name: upload artifact 102 | uses: actions/upload-pages-artifact@v3 103 | with: 104 | path: './build/coverage/' 105 | 106 | deploy: 107 | environment: 108 | name: github-pages 109 | url: ${{ steps.deployment.outputs.page_url }} 110 | runs-on: ubuntu-latest 111 | needs: run-code-coverage 112 | if: ${{ github.ref == 'refs/heads/main' }} 113 | steps: 114 | - name: deploy to Github Pages (main branch) 115 | id: deployment 116 | uses: actions/deploy-pages@v4 117 | 118 | # - name: deploy to Github Pages (development branch) 119 | # if: ${{ github.ref != 'refs/heads/main' }} 120 | # uses: peaceiris/actions-gh-pages@v4 121 | # with: 122 | # publish_dir: ./build/coverage/ 123 | # github_token: ${{ secrets.GITHUB_TOKEN }} 124 | # destination_dir: development-branch/ -------------------------------------------------------------------------------- /docs/source/tutorials/host_tutorial.rst: -------------------------------------------------------------------------------- 1 | .. host: 2 | 3 | ====================== 4 | Setting host structure 5 | ====================== 6 | 7 | This tutorial will detail how to set the host structure for RAFFLE and the optional bounding box. 8 | 9 | The host structure is the base structure that will be added to in order to generate the structures. 10 | The bounding box is an optional parameter that can be used to limit the space in which atoms can be placed. 11 | 12 | 13 | It is recommended to set the host after changing parameters such as the Gaussian parameters and cutoffs (see :doc:`Parameters tutorial `). 14 | However, this is not strictly necessary, as the host can be set at any time. 15 | It is recommended that the host be provided with a calculator, as this will enable calculation of the host structure prior to atom placement. 16 | 17 | 18 | Follow the parameter tutorial to see how to initialise the generator. 19 | 20 | .. code-block:: python 21 | 22 | # Initialise RAFFLE generator 23 | from raffle.generator import raffle_generator 24 | 25 | generator = raffle_generator() 26 | 27 | We shall also initialise the calculator. 28 | 29 | .. code-block:: python 30 | 31 | # Set the calculator 32 | from mace.calculators import mace_mp 33 | calc = mace_mp(model="medium", dispersion=False, default_dtype="float32", device='cpu') 34 | 35 | 36 | Defining the host structure 37 | --------------------------- 38 | 39 | Now we shall initialise an atoms object and set it as the host structure. 40 | 41 | .. code-block:: python 42 | 43 | # Set the host structure 44 | host = Atoms(...) 45 | host.calc = calc 46 | generator.set_host(host) 47 | 48 | 49 | Preparing the host structure 50 | ---------------------------- 51 | 52 | If a vacuum region has not been set within the host structure (i.e. a region with no atoms between two constituent substructures), the `prepare_host` method can be used to introduce such a region. 53 | The `prepare_host` method will remove atoms from the host structure within a specified distance from the interface location and returns a dictionary of the removed stoichiometry. 54 | The interface location is the location of the interface in the host structure and can be identified using `ARTEMIS `_. 55 | 56 | Below is an example of how to use both ARTEMIS and RAFFLE to prepare the host structure. 57 | 58 | .. code-block:: python 59 | 60 | # Import the required modules 61 | from artemis.generator import artemis_generator 62 | artemis_generator = artemis_generator() 63 | 64 | # Return the interface location using ARTEMIS 65 | location, axis = artemis_generator.get_interface_location( host, return_fractional = True ) 66 | print("Interface found at", location, "along", axis) 67 | 68 | # Prepare the host structure 69 | missing_stoich = generator.prepare_host( 70 | interface_location = location, 71 | depth = 2.0, 72 | location_as_fractional = True 73 | ) 74 | print("missing_stoich", missing_stoich) 75 | 76 | # Visualise the prepared host structure 77 | from ase.visualize import view 78 | host_modified = generator.get_host() 79 | view(host_modified) 80 | 81 | 82 | Defining the bounding box 83 | -------------------------- 84 | 85 | An optional bounding box can restrict atom placement to a specified region. 86 | The limits are expressed in fractional coordinates relative to the lattice vectors :math:`(\vec{a}, \vec{b}, \vec{c})`. 87 | 88 | .. code-block:: python 89 | 90 | # Set the fractional limits of atom position placement 91 | a_min = 0.0; b_max = 0.0; c_min = 0.3 92 | a_max = 1.0; b_max = 1.0; c_max = 0.8 93 | generator.set_bounds( [ 94 | [a_min, b_min, c_min], 95 | [a_max, b_max, c_max] 96 | ] ) 97 | -------------------------------------------------------------------------------- /tools/database.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "#Imports MPRester\n", 10 | "# from mp_api.client import MPRester\n", 11 | "from ase import Atoms\n", 12 | "from ase.io import write, read\n", 13 | "from pymatgen.io.ase import AseAtomsAdaptor\n", 14 | "from pymatgen.ext.matproj import MPRester" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": null, 20 | "metadata": {}, 21 | "outputs": [], 22 | "source": [ 23 | "# Personal api key for accessing materials project api\n", 24 | "# This is unique to each user\n", 25 | "# api_key = \"\"" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": null, 31 | "metadata": {}, 32 | "outputs": [], 33 | "source": [ 34 | "# Get the ID of materials from the materials project\n", 35 | "mpr = MPRester() # MPRester(api_key)\n", 36 | "materials = []\n", 37 | "\n", 38 | "materials.append(mpr.materials.summary.search(chemsys=\"C\", \n", 39 | " fields=[\"material_id\",\"structure\", \"energy_per_atom\", \"nsites\"]))\n", 40 | "materials.append(mpr.materials.summary.search(chemsys=\"Mg\", \n", 41 | " fields=[\"material_id\",\"structure\", \"energy_per_atom\", \"nsites\"]))\n", 42 | "materials.append(mpr.materials.summary.search(chemsys=\"O\", \n", 43 | " fields=[\"material_id\",\"structure\", \"energy_per_atom\", \"nsites\"]))\n", 44 | "materials.append(mpr.materials.summary.search(chemsys=\"C-Mg\", \n", 45 | " fields=[\"material_id\",\"structure\", \"energy_per_atom\", \"nsites\"]))\n", 46 | "materials.append(mpr.materials.summary.search(chemsys=\"C-O\", \n", 47 | " fields=[\"material_id\",\"structure\", \"energy_per_atom\", \"nsites\"]))\n", 48 | "materials.append(mpr.materials.summary.search(chemsys=\"Mg-O\", \n", 49 | " fields=[\"material_id\",\"structure\", \"energy_per_atom\", \"nsites\"]))" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": null, 55 | "metadata": {}, 56 | "outputs": [], 57 | "source": [ 58 | "# Get the structures, energies, and number of sites for each material from the materials project\n", 59 | "structures = []\n", 60 | "energies = []\n", 61 | "nsites = []\n", 62 | "for material_set in materials:\n", 63 | " for material in material_set:\n", 64 | " material_id = material.material_id\n", 65 | " structures.append(mpr.get_structure_by_material_id(material_id))\n", 66 | " energies.append(material.energy_per_atom)\n", 67 | " nsites.append(material.nsites)" 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": null, 73 | "metadata": {}, 74 | "outputs": [], 75 | "source": [ 76 | "# Convert the structures to atoms and write them to a single extended xyz file\n", 77 | "all_atoms = []\n", 78 | "for structure, energy, nsite in zip(structures, energies, nsites):\n", 79 | " atom = AseAtomsAdaptor.get_atoms(structure)\n", 80 | " atom.info['free_energy'] = energy * nsite\n", 81 | " atom.info['energy'] = energy * nsite\n", 82 | " all_atoms.append(atom)\n", 83 | "write(\"database.xyz\", all_atoms, format='extxyz')" 84 | ] 85 | } 86 | ], 87 | "metadata": { 88 | "kernelspec": { 89 | "display_name": "py3.11", 90 | "language": "python", 91 | "name": "python3" 92 | }, 93 | "language_info": { 94 | "codemirror_mode": { 95 | "name": "ipython", 96 | "version": 3 97 | }, 98 | "file_extension": ".py", 99 | "mimetype": "text/x-python", 100 | "name": "python", 101 | "nbconvert_exporter": "python", 102 | "pygments_lexer": "ipython3", 103 | "version": "3.11.8" 104 | } 105 | }, 106 | "nbformat": 4, 107 | "nbformat_minor": 2 108 | } 109 | -------------------------------------------------------------------------------- /example/python_pkg/Si-Ge_learn/Ge_slab.vasp: -------------------------------------------------------------------------------- 1 | Ge 2 | 1.000000000 3 | 11.300000000 0.000000000 0.000000000 4 | 0.000000000 11.300000000 0.000000000 5 | 0.000000000 0.000000000 25.299999996 6 | Ge 7 | 80 8 | Direct 9 | 0.750000000 0.000000000 0.000000000 10 | 0.750000000 0.000000000 0.223320158 11 | 0.750000000 0.000000000 0.446640316 12 | 0.875000000 0.125000000 0.055830039 13 | 0.875000000 0.125000000 0.279150198 14 | 0.875000000 0.125000000 0.502470356 15 | 0.000000000 0.250000000 0.000000000 16 | 0.000000000 0.250000000 0.223320158 17 | 0.000000000 0.250000000 0.446640316 18 | 0.125000000 0.375000000 0.055830039 19 | 0.125000000 0.375000000 0.279150198 20 | 0.125000000 0.375000000 0.502470356 21 | 0.000000000 0.000000000 0.111660079 22 | 0.000000000 0.000000000 0.334980237 23 | 0.125000000 0.125000000 0.167490118 24 | 0.125000000 0.125000000 0.390810277 25 | 0.750000000 0.250000000 0.111660079 26 | 0.750000000 0.250000000 0.334980237 27 | 0.875000000 0.375000000 0.167490118 28 | 0.875000000 0.375000000 0.390810277 29 | 0.750000000 0.500000000 0.000000000 30 | 0.750000000 0.500000000 0.223320158 31 | 0.750000000 0.500000000 0.446640316 32 | 0.875000000 0.625000000 0.055830039 33 | 0.875000000 0.625000000 0.279150198 34 | 0.875000000 0.625000000 0.502470356 35 | 0.000000000 0.750000000 0.000000000 36 | 0.000000000 0.750000000 0.223320158 37 | 0.000000000 0.750000000 0.446640316 38 | 0.125000000 0.875000000 0.055830039 39 | 0.125000000 0.875000000 0.279150198 40 | 0.125000000 0.875000000 0.502470356 41 | 0.000000000 0.500000000 0.111660079 42 | 0.000000000 0.500000000 0.334980237 43 | 0.125000000 0.625000000 0.167490118 44 | 0.125000000 0.625000000 0.390810277 45 | 0.750000000 0.750000000 0.111660079 46 | 0.750000000 0.750000000 0.334980237 47 | 0.875000000 0.875000000 0.167490118 48 | 0.875000000 0.875000000 0.390810277 49 | 0.250000000 0.000000000 0.000000000 50 | 0.250000000 0.000000000 0.223320158 51 | 0.250000000 0.000000000 0.446640316 52 | 0.375000000 0.125000000 0.055830039 53 | 0.375000000 0.125000000 0.279150198 54 | 0.375000000 0.125000000 0.502470356 55 | 0.500000000 0.250000000 0.000000000 56 | 0.500000000 0.250000000 0.223320158 57 | 0.500000000 0.250000000 0.446640316 58 | 0.625000000 0.375000000 0.055830039 59 | 0.625000000 0.375000000 0.279150198 60 | 0.625000000 0.375000000 0.502470356 61 | 0.500000000 0.000000000 0.111660079 62 | 0.500000000 0.000000000 0.334980237 63 | 0.625000000 0.125000000 0.167490118 64 | 0.625000000 0.125000000 0.390810277 65 | 0.250000000 0.250000000 0.111660079 66 | 0.250000000 0.250000000 0.334980237 67 | 0.375000000 0.375000000 0.167490118 68 | 0.375000000 0.375000000 0.390810277 69 | 0.250000000 0.500000000 0.000000000 70 | 0.250000000 0.500000000 0.223320158 71 | 0.250000000 0.500000000 0.446640316 72 | 0.375000000 0.625000000 0.055830039 73 | 0.375000000 0.625000000 0.279150198 74 | 0.375000000 0.625000000 0.502470356 75 | 0.500000000 0.750000000 0.000000000 76 | 0.500000000 0.750000000 0.223320158 77 | 0.500000000 0.750000000 0.446640316 78 | 0.625000000 0.875000000 0.055830039 79 | 0.625000000 0.875000000 0.279150198 80 | 0.625000000 0.875000000 0.502470356 81 | 0.500000000 0.500000000 0.111660079 82 | 0.500000000 0.500000000 0.334980237 83 | 0.625000000 0.625000000 0.167490118 84 | 0.625000000 0.625000000 0.390810277 85 | 0.250000000 0.750000000 0.111660079 86 | 0.250000000 0.750000000 0.334980237 87 | 0.375000000 0.875000000 0.167490118 88 | 0.375000000 0.875000000 0.390810277 89 | -------------------------------------------------------------------------------- /example/python_pkg/Si-Ge_learn/Si_slab.vasp: -------------------------------------------------------------------------------- 1 | Si 2 | 1.000000000 3 | 10.860000000 0.000000000 0.000000000 4 | 0.000000000 10.860000000 0.000000000 5 | 0.000000000 0.000000000 24.859999996 6 | Si 7 | 80 8 | Direct 9 | 0.000000000 0.000000000 0.000000000 10 | 0.000000000 0.000000000 0.218423170 11 | 0.000000000 0.000000000 0.436846339 12 | 0.125000000 0.125000000 0.054605792 13 | 0.125000000 0.125000000 0.273028962 14 | 0.125000000 0.125000000 0.491452132 15 | 0.250000000 0.250000000 0.000000000 16 | 0.250000000 0.250000000 0.218423170 17 | 0.250000000 0.250000000 0.436846339 18 | 0.375000000 0.375000000 0.054605792 19 | 0.375000000 0.375000000 0.273028962 20 | 0.375000000 0.375000000 0.491452132 21 | 0.250000000 0.000000000 0.109211585 22 | 0.250000000 0.000000000 0.327634755 23 | 0.375000000 0.125000000 0.163817377 24 | 0.375000000 0.125000000 0.382240547 25 | 0.000000000 0.250000000 0.109211585 26 | 0.000000000 0.250000000 0.327634755 27 | 0.125000000 0.375000000 0.163817377 28 | 0.125000000 0.375000000 0.382240547 29 | 0.000000000 0.500000000 0.000000000 30 | 0.000000000 0.500000000 0.218423170 31 | 0.000000000 0.500000000 0.436846339 32 | 0.125000000 0.625000000 0.054605792 33 | 0.125000000 0.625000000 0.273028962 34 | 0.125000000 0.625000000 0.491452132 35 | 0.250000000 0.750000000 0.000000000 36 | 0.250000000 0.750000000 0.218423170 37 | 0.250000000 0.750000000 0.436846339 38 | 0.375000000 0.875000000 0.054605792 39 | 0.375000000 0.875000000 0.273028962 40 | 0.375000000 0.875000000 0.491452132 41 | 0.250000000 0.500000000 0.109211585 42 | 0.250000000 0.500000000 0.327634755 43 | 0.375000000 0.625000000 0.163817377 44 | 0.375000000 0.625000000 0.382240547 45 | 0.000000000 0.750000000 0.109211585 46 | 0.000000000 0.750000000 0.327634755 47 | 0.125000000 0.875000000 0.163817377 48 | 0.125000000 0.875000000 0.382240547 49 | 0.500000000 0.000000000 0.000000000 50 | 0.500000000 0.000000000 0.218423170 51 | 0.500000000 0.000000000 0.436846339 52 | 0.625000000 0.125000000 0.054605792 53 | 0.625000000 0.125000000 0.273028962 54 | 0.625000000 0.125000000 0.491452132 55 | 0.750000000 0.250000000 0.000000000 56 | 0.750000000 0.250000000 0.218423170 57 | 0.750000000 0.250000000 0.436846339 58 | 0.875000000 0.375000000 0.054605792 59 | 0.875000000 0.375000000 0.273028962 60 | 0.875000000 0.375000000 0.491452132 61 | 0.750000000 0.000000000 0.109211585 62 | 0.750000000 0.000000000 0.327634755 63 | 0.875000000 0.125000000 0.163817377 64 | 0.875000000 0.125000000 0.382240547 65 | 0.500000000 0.250000000 0.109211585 66 | 0.500000000 0.250000000 0.327634755 67 | 0.625000000 0.375000000 0.163817377 68 | 0.625000000 0.375000000 0.382240547 69 | 0.500000000 0.500000000 0.000000000 70 | 0.500000000 0.500000000 0.218423170 71 | 0.500000000 0.500000000 0.436846339 72 | 0.625000000 0.625000000 0.054605792 73 | 0.625000000 0.625000000 0.273028962 74 | 0.625000000 0.625000000 0.491452132 75 | 0.750000000 0.750000000 0.000000000 76 | 0.750000000 0.750000000 0.218423170 77 | 0.750000000 0.750000000 0.436846339 78 | 0.875000000 0.875000000 0.054605792 79 | 0.875000000 0.875000000 0.273028962 80 | 0.875000000 0.875000000 0.491452132 81 | 0.750000000 0.500000000 0.109211585 82 | 0.750000000 0.500000000 0.327634755 83 | 0.875000000 0.625000000 0.163817377 84 | 0.875000000 0.625000000 0.382240547 85 | 0.500000000 0.750000000 0.109211585 86 | 0.500000000 0.750000000 0.327634755 87 | 0.625000000 0.875000000 0.163817377 88 | 0.625000000 0.875000000 0.382240547 89 | -------------------------------------------------------------------------------- /docs/source/tutorials/generating_tutorial.rst: -------------------------------------------------------------------------------- 1 | .. generating_tutorial: 2 | 3 | 4 | ===================== 5 | Generating structures 6 | ===================== 7 | 8 | 9 | This tutorial will detail the `generate` procedure for generating structures using the RAFFLE generator. 10 | 11 | The `generator` procedure is the process of adding atoms to the host structure to generate new structures. 12 | 13 | .. note:: 14 | The host structure must be set before generating structures. See :doc:`Host tutorial ` for more information. 15 | 16 | 17 | Input arguments 18 | --------------- 19 | 20 | The generating procedure has several arguments that can be set to control the generation of structures. 21 | 22 | The arguments are as follows: 23 | 24 | - ``num_structures``: The number of structures to generate. 25 | - ``stoichiometry``: A dictionary of the stoichiometry of atoms to add. 26 | - ``method_ratio``: A dictionary of the ratio of each method to use. 27 | - ``settings_out_file``: The file to write the settings to. 28 | - ``calc``: The calculator to attach to the generated structures. 29 | - ``seed``: The seed for the random number generator. 30 | - ``verbose``: The verbosity level of the generator. 31 | - ``return_exit_code``: Whether to return the exit code of the generator. 32 | 33 | 34 | The accepted keys for the ``method_ratio`` dictionary are: 35 | 36 | - ``min`` (or ``minimum`` or ``global``): The minimum method. 37 | - ``walk``: The walk method. 38 | - ``grow`` or (``growth``): The grow method. 39 | - ``void``: The void method. 40 | - ``rand`` or (``random``): The random method. 41 | 42 | 43 | Example 44 | ------- 45 | 46 | The following example demonstrates how to generate structures using the RAFFLE generator. 47 | 48 | .. code-block:: python 49 | 50 | from raffle.generator import raffle_generator 51 | from mace.calculators import mace_mp 52 | 53 | ... # Define an ASE Atoms object for the host structure 54 | 55 | # Set the host structure 56 | generator = raffle_generator() 57 | generator.set_host(host) 58 | 59 | # Set the generating arguments 60 | generator.generate( 61 | num_structures = 10, 62 | stoichiometry = {'Al': 1, 'O': 2}, 63 | method_ratio = { 64 | 'min': 5.0, 65 | 'walk': 3.0, 66 | 'grow': 2.0 67 | 'void': 1.0 68 | 'rand': 0.1 69 | }, 70 | settings_out_file = 'settings.json', 71 | calc = mace_mp(), 72 | seed = 42, 73 | verbose = 1, 74 | return_exit_code = False 75 | ) 76 | 77 | 78 | 79 | The above example generates 10 structures with a stoichiometry of 1 Al and 2 O atoms. 80 | The five methods are used with the specified ratios, with the values being renormalised to sum to 1 after the input. 81 | 82 | The settings are written to the file ``settings.json`` for future reference to improve reproducibility. 83 | By default, if no file is specified, the settings are not written to a file. 84 | 85 | The calculator is attached to the generated structures to calculate the energies of the structures. 86 | The seed is set to 42 to ensure reproducibility of the random number generator. 87 | 88 | The verbosity level is set to 2 to provide detailed information about the generation process. 89 | Default verbosity is 0, which provides no output. 90 | 91 | 92 | Retrieving generated structures 93 | ------------------------------- 94 | 95 | The generated structures are returned as a list of ASE Atoms objects. 96 | 97 | .. code-block:: python 98 | 99 | structures = generator.generate() 100 | 101 | The ``structures`` variable contains the list of generated structures for that iteration 102 | 103 | Optionally, if the ``return_exit_code`` argument is set to ``True``, the exit code of the generator can be retrieved using the following command: 104 | 105 | .. code-block:: python 106 | 107 | structures, status = generator.generate(return_exit_code=True) 108 | 109 | The ``status`` variable contains the status of the generation process, which can be used to check for errors. 110 | A successful generation will return a status of 0, while an error will return a non-zero status. 111 | 112 | Optionally, all structures generated thus far using the generator can be retrieved using the following command: 113 | 114 | .. code-block:: python 115 | 116 | all_structures = generator.get_structures() 117 | -------------------------------------------------------------------------------- /example/python_pkg/C_learn/DRSS/rss.py: -------------------------------------------------------------------------------- 1 | # https://agox.gitlab.io/agox/command_line_tools/command_line.html 2 | 3 | import matplotlib 4 | 5 | matplotlib.use("Agg") 6 | 7 | 8 | import numpy as np 9 | from ase import Atoms 10 | from ase.io import write 11 | 12 | from agox import AGOX 13 | from agox.databases import Database 14 | from agox.environments import Environment 15 | from agox.evaluators import LocalOptimizationEvaluator 16 | from agox.generators import RandomGenerator 17 | from agox.postprocessors import MinimumDistPostProcess 18 | 19 | 20 | database_index = 0 21 | iteration_directory = "iteration" 22 | 23 | ############################################################################## 24 | # Calculator 25 | ############################################################################## 26 | 27 | # from mace.calculators import mace_mp 28 | from chgnet.model import CHGNetCalculator 29 | from ase.build import bulk 30 | import os 31 | 32 | # calc = mace_mp() 33 | calc = CHGNetCalculator() 34 | 35 | ############################################################################## 36 | # System & general settings: 37 | ############################################################################## 38 | 39 | 40 | diamond = bulk("C", "diamond", a=3.567) # Lattice constant for diamond cubic carbon 41 | diamond.write("diamond.traj") 42 | post1 = MinimumDistPostProcess(order=1.5, c1=0.75) 43 | post2 = MinimumDistPostProcess(order=2.5, c1=0.75) 44 | 45 | # Make an empty template with a cubic cell of size 6x6x6 with periodic boundary conditions 46 | # in all directions 47 | a = 3.567 48 | iteration = 0 49 | template = Atoms("", cell=np.eye(3) * a, pbc=True) 50 | 51 | 52 | # Confinement cell matches the template cell in all dimensions and is placed at 53 | # the origin of the template cell. 54 | confinement_cell = template.cell.copy() 55 | confinement_corner = np.array([0, 0, 0]) 56 | 57 | environment = Environment( 58 | template=template, 59 | symbols="C8", 60 | confinement_cell=confinement_cell, 61 | confinement_corner=confinement_corner, 62 | box_constraint_pbc=[True, True, True], # Confinement is periodic in all directions. 63 | ) 64 | 65 | # Database 66 | db_directory = iteration_directory+"{}".format(iteration)+"/" 67 | if not os.path.exists(db_directory): 68 | os.makedirs(db_directory) 69 | db_path = db_directory+"db{}.db".format(database_index) # From input argument! 70 | 71 | for seed in range(20): 72 | database = Database(filename=db_path, order=3, initialize=True) 73 | 74 | ############################################################################## 75 | # Search Settings: 76 | ############################################################################## 77 | 78 | random_generator = RandomGenerator(**environment.get_confinement(), environment=environment, order=1) 79 | 80 | # Wont relax fully with steps:5 - more realistic setting would be 100+. 81 | evaluator = LocalOptimizationEvaluator( 82 | calc, 83 | gets={"get_key": "candidates"}, 84 | optimizer_run_kwargs={"fmax": 0.05, "steps": 100}, 85 | store_trajectory=True, 86 | order=2, 87 | constraints=environment.get_constraints(), 88 | ) 89 | 90 | ############################################################################## 91 | # Let get the show running! 92 | ############################################################################## 93 | 94 | agox = AGOX(random_generator, database, evaluator, seed=seed) 95 | 96 | agox.run(N_iterations=1000) 97 | 98 | structure_data = database.get_all_structures_data() 99 | # check iteration number has changed 100 | iteration_check = -1 101 | unrlxd_structures = [] 102 | rlxd_structures = [] 103 | for idx, structure in enumerate(structure_data): 104 | if structure["iteration"] != iteration_check: 105 | iteration_check = structure["iteration"] 106 | unrlxd_structures.append(database.db_to_atoms(structure)) 107 | if idx != 0: 108 | rlxd_structures.append(database.db_to_atoms(structure_data[idx-1])) 109 | if len(rlxd_structures) != len(unrlxd_structures): 110 | rlxd_structures.append(database.db_to_atoms(structure_data[-1])) 111 | 112 | print("Unrelaxed structures", len(unrlxd_structures)) 113 | print("Relaxed structures", len(rlxd_structures)) 114 | write(f"unrlxd_structures_seed{seed}.traj", unrlxd_structures) 115 | write(f"rlxd_structures_seed{seed}.traj", rlxd_structures) 116 | 117 | # database.restore_to_memory() 118 | # structures = database.get_all_candidates() # this is an Atoms object with some more stuff 119 | -------------------------------------------------------------------------------- /tools/check_accuracy_ScS2-Li.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | from pathlib import Path 4 | 5 | script_dir = Path(__file__).resolve().parent 6 | 7 | ## import ASE (Atomic Simulation Environment) modules 8 | from ase import Atoms 9 | from ase.optimize import BFGS 10 | from ase.filters import FrechetCellFilter 11 | from ase.constraints import FixAtoms 12 | from ase.io import read, write 13 | from ase.calculators.singlepoint import SinglePointCalculator 14 | 15 | 16 | ## load calculator 17 | from chgnet.model.dynamics import CHGNetCalculator 18 | print("Initialising CHGNet calculator") 19 | chgnet = CHGNetCalculator() 20 | from mace.calculators import mace_mp 21 | print("Initialising MACE calculator") 22 | calc_params = { 'model': "../example/python_pkg/mace-mpa-0-medium.model" } 23 | mace = mace_mp(**calc_params) 24 | # calc = mace_mp(model="medium", dispersion=False, default_dtype="float32", device='cpu') 25 | 26 | 27 | ## Read the database 28 | print("Reading database") 29 | database = read("../example/data/ScS2-Li.xyz", index=":") 30 | lowest_energy_index = -1 31 | lowest_energy = float('inf') 32 | # Get the lowest energy structure with just the stoichiometry ScS2 33 | for atoms in database: 34 | if atoms.calc is None: 35 | continue 36 | if atoms.get_chemical_formula(empirical=True) == "ScS2" or "S2Sc": 37 | n_Sc = atoms.get_atomic_numbers().tolist().count(21) 38 | energy = atoms.get_potential_energy() / n_Sc 39 | if energy < lowest_energy: 40 | lowest_energy = energy 41 | lowest_energy_index = database.index(atoms) 42 | print(f"Found ScS2 structure with energy {energy} at index {lowest_energy_index}") 43 | 44 | if atoms.get_chemical_formula(empirical=True) == "Li": 45 | print(f"Found Li structure at index {database.index(atoms)}") 46 | 47 | n_Sc = database[lowest_energy_index].get_atomic_numbers().tolist().count(21) 48 | Li = read( script_dir / "../example/python_pkg/ScS2-Li_learn/Li.xyz", index=0 ) 49 | Li_energy_dft = Li.get_potential_energy() / len(Li) # Li_AE_GW POT 50 | ScS2_energy_dft = database[lowest_energy_index].get_potential_energy() / n_Sc 51 | ScS2_ground_state = database[lowest_energy_index].copy() 52 | 53 | Li_chgnet = Li.copy() 54 | Li_chgnet.calc = chgnet 55 | Li_chgnet.set_constraint(FixAtoms(mask=[True for atom in Li_chgnet])) 56 | ecf = FrechetCellFilter(Li_chgnet) 57 | # structurally optimized Li structure 58 | opt = BFGS(ecf) 59 | opt.run(fmax=0.02) 60 | Li.calc = chgnet 61 | Li_energy_chgnet = Li_chgnet.get_potential_energy() / len(Li_chgnet) 62 | 63 | Li_mace = Li.copy() 64 | Li_mace.calc = mace 65 | Li_mace.set_constraint(FixAtoms(mask=[True for atom in Li_mace])) 66 | ecf = FrechetCellFilter(Li_mace) 67 | # structurally optimized Li structure 68 | opt = BFGS(ecf) 69 | opt.run(fmax=0.02) 70 | Li_energy_mace = Li_mace.get_potential_energy() / len(Li_mace) 71 | ScS2_ground_state.calc = chgnet 72 | ScS2_energy_chgnet = ScS2_ground_state.get_potential_energy() / n_Sc 73 | ScS2_ground_state.calc = mace 74 | ScS2_energy_mace = ScS2_ground_state.get_potential_energy() / n_Sc 75 | 76 | ## Calculate the energies 77 | formation_energies_dft = [] 78 | formation_energies_mace = [] 79 | formation_energies_chgnet = [] 80 | for i, atoms in enumerate(database): 81 | if atoms.calc is None: 82 | database.remove(atoms) 83 | continue 84 | if not atoms.get_chemical_formula(empirical=True) == "LiS2Sc": 85 | continue 86 | # get number of Li atoms in the structure 87 | n_Li = atoms.get_atomic_numbers().tolist().count(3) 88 | # get number of Sc atoms in the structure 89 | n_Sc = atoms.get_atomic_numbers().tolist().count(21) 90 | formation_energy_dft = ( atoms.get_potential_energy() - n_Li * Li_energy_dft - n_Sc * ScS2_energy_dft ) / n_Sc / n_Li 91 | formation_energies_dft.append(formation_energy_dft) 92 | atoms.calc = chgnet 93 | formation_energy_chgnet = ( atoms.get_potential_energy() - n_Li * Li_energy_chgnet - n_Sc * ScS2_energy_chgnet ) / n_Sc / n_Li 94 | formation_energies_chgnet.append(formation_energy_chgnet) 95 | atoms.calc = mace 96 | formation_energy_mace = ( atoms.get_potential_energy() - n_Li * Li_energy_mace - n_Sc * ScS2_energy_mace ) / n_Sc / n_Li 97 | formation_energies_mace.append(formation_energy_mace) 98 | 99 | 100 | ## Write energies to a file 101 | with open("ScS2-Li_formations_comparison.txt", "w") as f: 102 | f.write("# DFT_Formation_energy_per_atom MACE-MPA-0_Formation_energy_per_atom CHGNet_Formation_energy_per_atom\n") 103 | for dft_energy, mace_energy, chgnet_energy in zip(formation_energies_dft, formation_energies_mace, formation_energies_chgnet): 104 | f.write(f"{dft_energy} {mace_energy} {chgnet_energy}\n") 105 | --------------------------------------------------------------------------------