Conversation
It works, but it cannot be configured yet.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #60 +/- ##
==========================================
- Coverage 88.54% 85.90% -2.65%
==========================================
Files 8 9 +1
Lines 812 837 +25
==========================================
Hits 719 719
- Misses 93 118 +25 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
As a reference the ASE team worked on this some time back https://gitlab.com/ase/ase/-/merge_requests/2657 |
|
Yeah, I snooped around in there, but as you expected it's much simpler with the parser and newer ASE infrastructure. |
|
I also found the calculator implemented by FLEUR. Seems like this can be a good template for a "modern" ase calculator too. |
|
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
There was a problem hiding this comment.
Pull request overview
This PR introduces an ASE FileIOCalculator implementation for running SPHInX DFT calculations via sphinx_parser, aiming to support ASE’s calculate() flow for energies and forces (Issue #34).
Changes:
- Added a new
SphinxDftASE calculator that writes aninput.sxfile from anase.Atoms. - Added result parsing from a SPHInX stdout log via
SphinxLogParser, exposingenergyandforcesthroughself.results.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
sphinx_parser/calculator.py
Outdated
| def read_results(self): | ||
| parser = SphinxLogParser.load_from_path(Path(self.directory) / "log.sx") | ||
| self.results["energy"] = parser.get_energy_free()[-1][-1] | ||
| self.results["forces"] = parser.get_forces()[-1] |
sphinx_parser/calculator.py
Outdated
| struct_group = get_structure_group(atoms)[0] | ||
| main_group = sphinx.main( | ||
| scfDiag=sphinx.main.scfDiag(maxSteps=10, blockCCG={}), | ||
| evalForces=sphinx.main.evalForces("forces.txt"), | ||
| ) | ||
| pawPot_group = get_paw_from_structure(atoms) | ||
| basis_group = sphinx.basis( | ||
| eCut=25, kPoint=sphinx.basis.kPoint(coords=3 * [0.5]) | ||
| ) | ||
| paw_group = sphinx.PAWHamiltonian(xc=1, spinPolarized=False, ekt=0.2) | ||
| initial_guess_group = sphinx.initialGuess( | ||
| waves=sphinx.initialGuess.waves(lcao=sphinx.initialGuess.waves.lcao()), | ||
| rho=sphinx.initialGuess.rho(atomicOrbitals=True), | ||
| ) |
sphinx_parser/calculator.py
Outdated
| pawPot_group = get_paw_from_structure(atoms) | ||
| basis_group = sphinx.basis( |
There was a problem hiding this comment.
I don't think it's a good idea to hard code this here. @samwaseda does the rest of sphinxparser make reference to the potential location?
There was a problem hiding this comment.
Good question. I cannot remember how it works here anymore...
sphinx_parser/calculator.py
Outdated
| class SphinxDft(FileIOCalculator): | ||
| implemented_properties = ["energy", "forces"] | ||
|
|
||
| def __init__(self, *args, **kwargs): | ||
| super().__init__(*args, **kwargs, profile=StandardProfile(command="sphinx")) | ||
| self.fileio_rules = FileIORules(stdout_name="log.sx") | ||
|
|
||
| def write_input(self, atoms, properties=None, system_changes=None): | ||
| super().write_input(atoms, properties, system_changes) | ||
|
|
||
| struct_group = get_structure_group(atoms)[0] | ||
| main_group = sphinx.main( | ||
| scfDiag=sphinx.main.scfDiag(maxSteps=10, blockCCG={}), | ||
| evalForces=sphinx.main.evalForces("forces.txt"), | ||
| ) | ||
| pawPot_group = get_paw_from_structure(atoms) | ||
| basis_group = sphinx.basis( | ||
| eCut=25, kPoint=sphinx.basis.kPoint(coords=3 * [0.5]) | ||
| ) | ||
| paw_group = sphinx.PAWHamiltonian(xc=1, spinPolarized=False, ekt=0.2) | ||
| initial_guess_group = sphinx.initialGuess( | ||
| waves=sphinx.initialGuess.waves(lcao=sphinx.initialGuess.waves.lcao()), | ||
| rho=sphinx.initialGuess.rho(atomicOrbitals=True), | ||
| ) | ||
|
|
||
| input_sx = sphinx( | ||
| pawPot=pawPot_group, | ||
| structure=struct_group, | ||
| main=main_group, | ||
| basis=basis_group, | ||
| PAWHamiltonian=paw_group, | ||
| initialGuess=initial_guess_group, | ||
| ) | ||
|
|
||
| cwd = self.directory | ||
| with open(Path(cwd) / "input.sx", "w") as f: | ||
| f.write(to_sphinx(input_sx)) | ||
|
|
||
| def read_results(self): | ||
| parser = SphinxLogParser.load_from_path(Path(self.directory) / "log.sx") | ||
| self.results["energy"] = parser.get_energy_free()[-1][-1] | ||
| self.results["forces"] = parser.get_forces()[-1] |
sphinx_parser/calculator.py
Outdated
| parser = SphinxLogParser.load_from_path(Path(self.directory) / "log.sx") | ||
| self.results["energy"] = parser.get_energy_free()[-1][-1] |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Marvin Poul <ponder@creshal.de>
It works, but it cannot be configured yet.
See #34