From 7f161df0da390a74d06d77457833f851b33efb77 Mon Sep 17 00:00:00 2001 From: Yuichi Motoyama Date: Fri, 6 Dec 2024 14:25:29 +0900 Subject: [PATCH] restore aenetPyLammps --- .../latgas_abinitio_interface/aenet.py | 9 ++- .../aenet_pylammps.py | 11 ++-- .../latgas_abinitio_interface/params.py | 1 + tests/test_aenet.py | 18 +++++- tests/test_aenetpylammps.py | 57 +++++++++++++++++++ tests/test_openmx.py | 22 +++++-- tests/test_qe.py | 26 ++++++--- tests/test_vasp.py | 11 +++- 8 files changed, 133 insertions(+), 22 deletions(-) create mode 100644 tests/test_aenetpylammps.py diff --git a/abics/applications/latgas_abinitio_interface/aenet.py b/abics/applications/latgas_abinitio_interface/aenet.py index 7c102cf2..ed995829 100644 --- a/abics/applications/latgas_abinitio_interface/aenet.py +++ b/abics/applications/latgas_abinitio_interface/aenet.py @@ -26,12 +26,15 @@ from .params import ALParams, DFTParams from .util import structure_to_XSF, structure_from_XSF + class AenetSolver(SolverBase): """ This class defines the aenet solver. """ - def __init__(self, path_to_solver: os.PathLike, ignore_species=None, run_scheme="subprocess"): + def __init__( + self, path_to_solver: os.PathLike, ignore_species=None, run_scheme="subprocess" + ): """ Initialize the solver. @@ -49,7 +52,7 @@ def name(self): return "aenet" class Input(object): - def __init__(self, ignore_species : str | None, run_scheme="subprocess"): + def __init__(self, ignore_species: str | None, run_scheme="subprocess"): self.base_info = None self.pos_info = None self.ignore_species = ignore_species @@ -138,6 +141,8 @@ def cl_args(self, nprocs, nthreads, output_dir): os.path.join(output_dir, "predict.in"), os.path.join(output_dir, "structure.xsf"), ] + else: + raise RuntimeError("Invalid run_scheme: {}".format(self.run_scheme)) class Output(object): def get_results(self, output_dir): diff --git a/abics/applications/latgas_abinitio_interface/aenet_pylammps.py b/abics/applications/latgas_abinitio_interface/aenet_pylammps.py index 85b4141f..1eb3e5b8 100644 --- a/abics/applications/latgas_abinitio_interface/aenet_pylammps.py +++ b/abics/applications/latgas_abinitio_interface/aenet_pylammps.py @@ -63,8 +63,9 @@ def __init__(self, ignore_species): cmdargs=["-log", "none", "-screen", "none", "-nocite"], comm=MPI.COMM_SELF ) self.rank = MPI.COMM_WORLD.Get_rank() - + # debug cmdargs=["-log", "test{}.log".format(MPI.COMM_WORLD.Get_rank()), "-screen", "none", "-nocite"], comm=MPI.COMM_SELF + def name(self): return "aenetPyLammps" @@ -82,7 +83,7 @@ def calculate_energy(self, fi, output_dir): by = np.linalg.norm(np.cross(unit_vec(latt[0]), latt[1])) cx = np.dot(latt[2], unit_vec(latt[0])) cy = (np.dot(latt[1], latt[2]) - bx * cx) / by - cz = np.sqrt(np.linalg.norm(latt[2]) ** 2.0 - cx ** 2.0 - cy ** 2.0) + cz = np.sqrt(np.linalg.norm(latt[2]) ** 2.0 - cx**2.0 - cy**2.0) # lmp = lammps(cmdargs=["-log", "none","-nocite"]) self.calc.command("atom_style atomic") @@ -92,9 +93,11 @@ def calculate_energy(self, fi, output_dir): self.calc.command(f"region box prism 0 {ax} 0 {by} 0 {cz} {bx} {cx} {cy}") self.calc.command(f"create_box {nspec} box") types = list(map(lambda x: spec_dict[x.name], st.species)) - new_coords = np.dot(st.frac_coords, np.array([[ax,0,0], [bx,by,0], [cx,cy,cz]])) + new_coords = np.dot( + st.frac_coords, np.array([[ax, 0, 0], [bx, by, 0], [cx, cy, cz]]) + ) self.calc.create_atoms(natoms, None, types, new_coords.ravel()) - + for i in range(1, nspec + 1): self.calc.command(f"mass {i} 1") self.calc.commands_list(self.input.pair_pot) diff --git a/abics/applications/latgas_abinitio_interface/params.py b/abics/applications/latgas_abinitio_interface/params.py index 90165aa0..7bbd106c 100644 --- a/abics/applications/latgas_abinitio_interface/params.py +++ b/abics/applications/latgas_abinitio_interface/params.py @@ -174,6 +174,7 @@ def from_toml(cls, f): d = toml.load(f) return cls.from_dict(d["mlref"]["solver"]) + class TrainerParams: def __init__(self): self.base_input_dir = [] diff --git a/tests/test_aenet.py b/tests/test_aenet.py index 8f1c56ea..5fa1f718 100644 --- a/tests/test_aenet.py +++ b/tests/test_aenet.py @@ -22,6 +22,8 @@ from pymatgen.core import Structure +from abics.applications.latgas_abinitio_interface.base_solver import create_solver +from abics.applications.latgas_abinitio_interface.params import DFTParams from abics.applications.latgas_abinitio_interface.aenet import AenetSolver @@ -35,11 +37,17 @@ def setUpClass(cls): os.makedirs(workdir) def setUp(self): - self.solver = AenetSolver(".") + params = DFTParams.from_dict( + {"type": "aenet", "path": ".", "run_scheme": "subprocess"} + ) + self.solver = create_solver(params.solver, params) self.rootdir = os.path.dirname(__file__) self.datadir = os.path.join(self.rootdir, "data", "aenet") self.workdir = os.path.join(self.rootdir, "res", "aenet") + def test_create_solver(self): + self.assertIsInstance(self.solver, AenetSolver) + def test_get_results(self): res = self.solver.output.get_results(self.datadir) res.structure.to("POSCAR", os.path.join(self.workdir, "pos.vasp")) @@ -68,4 +76,10 @@ def test_cl_algs(self): nthreads = 4 workdir = "work" res = self.solver.input.cl_args(nprocs, nthreads, workdir) - self.assertEqual(res, [os.path.join(workdir, "predict.in"), os.path.join(workdir, "structure.xsf")]) + self.assertEqual( + res, + [ + os.path.join(workdir, "predict.in"), + os.path.join(workdir, "structure.xsf"), + ], + ) diff --git a/tests/test_aenetpylammps.py b/tests/test_aenetpylammps.py new file mode 100644 index 00000000..d53cb5c8 --- /dev/null +++ b/tests/test_aenetpylammps.py @@ -0,0 +1,57 @@ +# ab-Initio Configuration Sampling tool kit (abICS) +# Copyright (C) 2019- The University of Tokyo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. + +import os +import shutil +import unittest + +import numpy as np + +from pymatgen.core import Structure + +from abics.applications.latgas_abinitio_interface.base_solver import create_solver +from abics.applications.latgas_abinitio_interface.params import DFTParams +from abics.applications.latgas_abinitio_interface.aenet_pylammps import ( + AenetPyLammpsSolver, +) + + +class TestAenetPyLammps(unittest.TestCase): + @classmethod + def setUpClass(cls): + rootdir = os.path.dirname(__file__) + workdir = os.path.join(rootdir, "res", "aenet") + if os.path.exists(workdir): + shutil.rmtree(workdir) + os.makedirs(workdir) + + def setUp(self): + params = DFTParams.from_dict({"type": "aenetPyLammps", "path": "."}) + + self.imported = False + try: + self.solver = create_solver(params.solver, params) + self.imported = True + except ImportError: + self.imported = False + + self.rootdir = os.path.dirname(__file__) + self.datadir = os.path.join(self.rootdir, "data", "aenet") + self.workdir = os.path.join(self.rootdir, "res", "aenet") + + def test_create_solver(self): + if self.imported: + self.assertIsInstance(self.solver, AenetPyLammpsSolver) diff --git a/tests/test_openmx.py b/tests/test_openmx.py index 3f3e9f46..9a7fd40d 100644 --- a/tests/test_openmx.py +++ b/tests/test_openmx.py @@ -22,7 +22,12 @@ from pymatgen.core import Structure -from abics.applications.latgas_abinitio_interface.openmx import OpenMXInputFile, OpenMXSolver +from abics.applications.latgas_abinitio_interface.base_solver import create_solver +from abics.applications.latgas_abinitio_interface.params import DFTParams +from abics.applications.latgas_abinitio_interface.openmx import ( + OpenMXInputFile, + OpenMXSolver, +) class TestOpenMX(unittest.TestCase): @@ -38,7 +43,17 @@ def setUp(self): self.rootdir = os.path.dirname(__file__) self.datadir = os.path.join(self.rootdir, "data", "openmx") self.workdir = os.path.join(self.rootdir, "res", "openmx") - self.solver = OpenMXSolver(os.path.join(self.datadir, "bin", "openmx.dummy")) + params = DFTParams.from_dict( + { + "type": "openmx", + "path": os.path.join(self.datadir, "bin", "openmx.dummy"), + "run_scheme": "subprocess", + } + ) + self.solver = create_solver(params.solver, params) + + def test_create_solver(self): + self.assertIsInstance(self.solver, OpenMXSolver) def test_get_results(self): self.solver.input.from_directory(os.path.join(self.datadir, "baseinput")) @@ -51,7 +66,7 @@ def test_get_results(self): def test_input(self): self.solver.input.from_directory(os.path.join(self.datadir, "baseinput")) - A = 4.0*np.eye(3) + A = 4.0 * np.eye(3) r = np.array([[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]]) st = Structure( A, @@ -70,7 +85,6 @@ def test_input(self): self.assertEqual(res, ref) - def test_cl_algs(self): self.solver.input.from_directory(os.path.join(self.datadir, "baseinput")) nprocs = 2 diff --git a/tests/test_qe.py b/tests/test_qe.py index 397b55bd..d3c0e9bb 100644 --- a/tests/test_qe.py +++ b/tests/test_qe.py @@ -22,6 +22,8 @@ from pymatgen.core import Structure +from abics.applications.latgas_abinitio_interface.base_solver import create_solver +from abics.applications.latgas_abinitio_interface.params import DFTParams from abics.applications.latgas_abinitio_interface.qe import QESolver from qe_tools.parsers import PwInputFile @@ -37,11 +39,15 @@ def setUpClass(cls): os.makedirs(workdir) def setUp(self): - self.solver = QESolver(".") + params = DFTParams.from_dict({"type": "qe", "path": "."}) + self.solver = create_solver(params.solver, params) self.rootdir = os.path.dirname(__file__) self.datadir = os.path.join(self.rootdir, "data", "qe") self.workdir = os.path.join(self.rootdir, "res", "qe") + def test_create_solver(self): + self.assertIsInstance(self.solver, QESolver) + def test_get_results(self): res = self.solver.output.get_results(self.datadir) res.structure.to("POSCAR", os.path.join(self.workdir, "pos.vasp")) @@ -52,7 +58,7 @@ def test_get_results(self): def test_input(self): self.solver.input.from_directory(os.path.join(self.datadir, "baseinput")) - A = 4.0*np.eye(3) + A = 4.0 * np.eye(3) r = np.array([[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]]) st = Structure( A, @@ -72,10 +78,17 @@ def test_input(self): self.assertEqual(res.namelists, ref.namelists) - self.assertTrue(np.allclose(res.cell_parameters["cell"], ref.cell_parameters["cell"])) - self.assertTrue(np.allclose(res.atomic_positions["positions"], ref.atomic_positions["positions"])) - self.assertEqual(res.atomic_positions["fixed_coords"], ref.atomic_positions["fixed_coords"]) - + self.assertTrue( + np.allclose(res.cell_parameters["cell"], ref.cell_parameters["cell"]) + ) + self.assertTrue( + np.allclose( + res.atomic_positions["positions"], ref.atomic_positions["positions"] + ) + ) + self.assertEqual( + res.atomic_positions["fixed_coords"], ref.atomic_positions["fixed_coords"] + ) def test_cl_algs(self): nprocs = 2 @@ -83,4 +96,3 @@ def test_cl_algs(self): workdir = "work" res = self.solver.input.cl_args(nprocs, nthreads, workdir) self.assertEqual(res, ["-in", os.path.join(workdir, "scf.in")]) - diff --git a/tests/test_vasp.py b/tests/test_vasp.py index f617f7ac..5c356d35 100644 --- a/tests/test_vasp.py +++ b/tests/test_vasp.py @@ -23,6 +23,8 @@ from pymatgen.core import Structure from pymatgen.io.vasp.inputs import VaspInput +from abics.applications.latgas_abinitio_interface.base_solver import create_solver +from abics.applications.latgas_abinitio_interface.params import DFTParams from abics.applications.latgas_abinitio_interface.vasp import VASPSolver @@ -36,11 +38,15 @@ def setUpClass(cls): os.makedirs(workdir) def setUp(self): - self.solver = VASPSolver(".") + params = DFTParams.from_dict({"type": "vasp", "path": "."}) + self.solver = create_solver(params.solver, params) self.rootdir = os.path.dirname(__file__) self.datadir = os.path.join(self.rootdir, "data", "vasp") self.workdir = os.path.join(self.rootdir, "res", "vasp") + def test_create_solver(self): + self.assertIsInstance(self.solver, VASPSolver) + def test_get_results(self): os.utime(os.path.join(self.datadir, "output", "OSZICAR")) res = self.solver.output.get_results(os.path.join(self.datadir, "output")) @@ -69,7 +75,7 @@ def test_input(self): self.assertEqual(res["INCAR"], ref["INCAR"]) self.assertTrue(res["POSCAR"].structure.matches(ref["POSCAR"].structure)) - for k,v in ref["POSCAR"].structure.site_properties.items(): + for k, v in ref["POSCAR"].structure.site_properties.items(): self.assertTrue(np.allclose(res["POSCAR"].structure.site_properties[k], v)) def test_cl_algs(self): @@ -78,4 +84,3 @@ def test_cl_algs(self): workdir = "work" res = self.solver.input.cl_args(nprocs, nthreads, workdir) self.assertEqual(res, [workdir]) -