From dbb9f6e200914deae19455f782c4edeea094da32 Mon Sep 17 00:00:00 2001 From: Mgcini Keith Phuthi Date: Tue, 17 Dec 2024 13:42:09 -0800 Subject: [PATCH] added vasp asimmodule --- asimtools/asimmodules/lammps/lammps.py | 6 +- asimtools/asimmodules/vasp/__init__.py | 0 asimtools/asimmodules/vasp/vasp.py | 98 +++++++++++++++++++ asimtools/job.py | 2 - .../external/VASP/vasp_mpset_sim_input.yaml | 9 ++ 5 files changed, 110 insertions(+), 5 deletions(-) create mode 100644 asimtools/asimmodules/vasp/__init__.py create mode 100755 asimtools/asimmodules/vasp/vasp.py create mode 100644 examples/external/VASP/vasp_mpset_sim_input.yaml diff --git a/asimtools/asimmodules/lammps/lammps.py b/asimtools/asimmodules/lammps/lammps.py index 21f4584..50d7f20 100755 --- a/asimtools/asimmodules/lammps/lammps.py +++ b/asimtools/asimmodules/lammps/lammps.py @@ -125,14 +125,14 @@ def lammps( command, check=False, capture_output=True, text=True, ) - with open('lmp_stdout.txt', 'w', encoding='utf-8') as f: + with open('lmp_stdout.txt', 'a+', encoding='utf-8') as f: f.write(completed_process.stdout) if completed_process.returncode != 0: err_txt = f'Failed to run {lmp_inp_file}\n' - err_txt += 'See lmp.stderr.txt for details.' + err_txt += 'See lmp_stderr.txt for details.' logging.error(err_txt) - with open('lmp_stderr.txt', 'w', encoding='utf-8') as f: + with open('lmp_stderr.txt', 'a+', encoding='utf-8') as f: f.write(completed_process.stderr) completed_process.check_returncode() return {} diff --git a/asimtools/asimmodules/vasp/__init__.py b/asimtools/asimmodules/vasp/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/asimtools/asimmodules/vasp/vasp.py b/asimtools/asimmodules/vasp/vasp.py new file mode 100755 index 0000000..919ff58 --- /dev/null +++ b/asimtools/asimmodules/vasp/vasp.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python +''' +Runs VASP based on input files and optionally MP settings. +Heavily uses pymatgen for IO and MP settings. +VASP must be installed + +Author: mkphuthi@github.com +''' +from typing import Dict, Optional, Sequence +import os +import sys +from pathlib import Path +from numpy.random import randint +import subprocess +import logging +from ase.io import read +from pymatgen.io.ase import AseAtomsAdaptor +from pymatgen.io.vasp import Poscar +from pymatgen.io.vasp.sets import ( + MPRelaxSet, MPStaticSet, MPNonSCFSet, MPScanRelaxSet +) +from asimtools.utils import ( + get_atoms, +) + +def vasp( + image: Optional[Dict], + vaspinput_args: Optional[Dict] = None, + command: str = 'vasp_std', + mpset: Optional[str] = None, + write_image_output: bool = False, +) -> Dict: + """Run VASP with given input files and specified image + + :param image: Initial image for VASP calculation. Image specification, + see :func:`asimtools.utils.get_atoms` + :type image: Dict + :param vaspinput_args: Dictionary of VASP input arguments. + See :class:`pymatgen.io.vasp.inputs.VaspInput` + :type vaspinput_args: Dict + :param command: Command with which to run VASP, defaults to 'vasp_std' + :type command: str, optional + :param mpset: Material Project VASP set to use, defaults to None + :type mpset: str, optional + :param write_image_output: Whether to write output image in standard + asimtools format to file, defaults to False + :type write_image_output: bool, optional + """ + + if vaspinput_args: + if image is not None: + atoms = get_atoms(**image) + struct = AseAtomsAdapter.get_structure(atoms) + vaspinput = VaspInput( + poscar=Poscar(struct), + **vaspinput_args + ) + else: + atoms = get_atoms(**image) + struct = AseAtomsAdaptor.get_structure(atoms) + if mpset == 'MPRelaxSet': + vasp_input = MPRelaxSet(struct) + elif mpset == 'MPStaticSet': + vasp_input = MPStaticSet(struct) + elif mpset == 'MPNonSCFSet': + vasp_input = MPNonSCFSet(struct) + elif mpset == 'MPScanRelaxSet': + vasp_input = MPScanRelaxSet(struct) + else: + raise ValueError(f'Unknown MPSet: {mpset}') + + vasp_input.write_input("./") + + command = command.split(' ') + completed_process = subprocess.run( + command, check=False, capture_output=True, text=True, + ) + + with open('vasp_stdout.txt', 'a+', encoding='utf-8') as f: + f.write(completed_process.stdout) + + if completed_process.returncode != 0: + err_txt = f'Failed to run VASP\n' + err_txt += 'See vasp_stderr.txt for details.' + logging.error(err_txt) + with open('vasp_stderr.txt', 'a+', encoding='utf-8') as f: + f.write(completed_process.stderr) + completed_process.check_returncode() + return {} + + if write_image_output: + atoms_output = read('OUTCAR') + atoms_output.write( + 'image_output.xyz', + format='extxyz', + ) + + return {} diff --git a/asimtools/job.py b/asimtools/job.py index d9c4401..8bf258e 100644 --- a/asimtools/job.py +++ b/asimtools/job.py @@ -406,7 +406,6 @@ def gen_input_files( images = self.sim_input.get('args', {}).get('images', False) if images and write_image: if images.get('images', False) or images.get('image_file', False): - print(write_image, os.getcwd(), images) images = get_images(**images) input_images_file = 'images_input.xyz' # Relative to workdir ase.io.write( @@ -948,7 +947,6 @@ def submit(self, dependency: Union[List,None] = None, debug: bool = False) -> Li descend=True ) if not cur_step_complete: - print(f'XXXX Step {step+i} not complete, submitting') slurm_flags = curjob.env['slurm']['flags'] if isinstance(slurm_flags, list): job_name = curjob.sim_input.get('job_name',False) diff --git a/examples/external/VASP/vasp_mpset_sim_input.yaml b/examples/external/VASP/vasp_mpset_sim_input.yaml new file mode 100644 index 0000000..2dd3880 --- /dev/null +++ b/examples/external/VASP/vasp_mpset_sim_input.yaml @@ -0,0 +1,9 @@ +asimmodule: vasp.vasp +workdir: vasp_mpset_results +env_id: inline +args: + image: + name: Na + builder: bulk + mpset: MPStaticSet + command: vasp_std