Repository: deepmodeling/dpgen2 (language: python)

Issue:
Implement the op RunVasp
Implement the op RunVasp. This OP run a VASP DFT task prepared by PrepVasp, and outputs the labeled configuration (coordinate, simulation cell, dft energy, force and virial) in the `deepmd/npy` data format provided by [`dpdata`](https://github.com/deepmodeling/dpdata/).

We have to implement the execute method of the class. What the op does is explained in the [docstr of the class](https://github.com/wanghan-iapcm/dpgen2/blob/ef08f44f7a39c81fe469885ffaa4cd8be9d4d0a3/dpgen2/op/run_vasp.py#L12-L20) and the interface of the execute method is provided in [the docstr of the method](https://github.com/wanghan-iapcm/dpgen2/blob/ef08f44f7a39c81fe469885ffaa4cd8be9d4d0a3/dpgen2/op/run_vasp.py#L42-L63).

One can also take the [implementation of RunDPTrain](https://github.com/wanghan-iapcm/dpgen2/blob/master/dpgen2/op/run_dp_train.py) as an example for the RunVasp


Discussion / hints:

Fix patch:
diff --git a/dpgen2/constants.py b/dpgen2/constants.py
index 3792687e..90b03f32 100644
--- a/dpgen2/constants.py
+++ b/dpgen2/constants.py
@@ -15,4 +15,5 @@
 vasp_conf_name = 'POSCAR'
 vasp_input_name = 'INCAR'
 vasp_pot_name = 'POTCAR'
+vasp_kp_name = 'KPOINTS'
 
diff --git a/dpgen2/exploration/selector/conf_selector_frame.py b/dpgen2/exploration/selector/conf_selector_frame.py
index de95e456..56280400 100644
--- a/dpgen2/exploration/selector/conf_selector_frame.py
+++ b/dpgen2/exploration/selector/conf_selector_frame.py
@@ -56,7 +56,7 @@ def select (
         Returns
         -------
         confs : List[Path]
-                The selected confgurations, stored in a folder that can be parsed as dpdata.MultiSystems. The `list` only has one item.
+                The selected confgurations, stored in a folder in deepmd/npy format, can be parsed as dpdata.MultiSystems. The `list` only has one item.
         report : ExplorationReport
                 The exploration report recoding the status of the exploration. 
 
diff --git a/dpgen2/fp/vasp.py b/dpgen2/fp/vasp.py
index 83a77edc..66906722 100644
--- a/dpgen2/fp/vasp.py
+++ b/dpgen2/fp/vasp.py
@@ -1,26 +1,120 @@
-from typing import Dict
+import numpy as np
+import dpdata
+from pathlib import Path
+from typing import (
+    Tuple, 
+    List, 
+    Set, 
+    Dict,
+    Union,
+)
 
 class VaspInputs():
     def __init__(
             self,
-            incar_template : str,
-            potcars : Dict[str, str],
+            kspacing : Union[float, List[float]],
+            kgamma : bool = True,
+            incar_template_name : str = None,
+            potcar_names : Dict[str, str] = None,
     ):
-        self._incar_template = incar_template
-        self._potcars = potcars
+        """
+        Parameters
+        ----------
+        kspacing : Union[float, List[float]]
+                The kspacing. If it is a number, then three directions use the same
+                ksapcing, otherwise it is a list of three numbers, specifying the
+                kspacing used in the x, y and z dimension.
+        kgamma : bool
+                K-mesh includes the gamma point
+        incar_template_name: str
+                A template INCAR file. 
+        potcar_names : Dict[str,str]
+                The potcar files for the elements. For example
+                { 
+                   "H" : "/path/to/POTCAR_H",
+                   "O" : "/path/to/POTCAR_O",
+                }
+        """
+        self.kspacing = kspacing
+        self.kgamma = kgamma
+        self.incar_from_file(incar_template_name)
+        self.potcars_from_file(potcar_names)
 
     @property
-    def incar_temp(self):
+    def incar_template(self):
         return self._incar_template
 
     @property
     def potcars(self):
         return self._potcars
 
+    def incar_from_file(
+            self,
+            fname : str,
+    ):
+        self._incar_template = Path(fname).read_text()
+
+    def potcars_from_file(
+            self,
+            dict_fnames : Dict[str,str],
+    ):
+        self._potcars = {}
+        for kk,vv in dict_fnames.items():
+            self._potcars[kk] = Path(vv).read_text()            
+
     def make_potcar(
             self, 
-            poscar : str,
+            atom_names,
+    ) -> str:        
+        potcar_contents = []
+        for nn in atom_names:
+            potcar_contents.append(self._potcars[nn])
+        return "".join(potcar_contents)            
+
+    def make_kpoints(
+            self,
+            box : np.array,
     ) -> str:
-        raise NotImplementedError
+        return make_kspacing_kpoints(box, self.kspacing, self.kgamma)
+
+
+def make_kspacing_kpoints(box, kspacing, kgamma) :
+    if type(kspacing) is not list:
+        kspacing = [kspacing, kspacing, kspacing]
+    box = np.array(box)
+    rbox = _reciprocal_box(box)
+    kpoints = [max(1,(np.ceil(2 * np.pi * np.linalg.norm(ii) / ks).astype(int))) for ii,ks in zip(rbox,kspacing)]
+    ret = _make_vasp_kpoints(kpoints, kgamma)
+    return ret
+
 
+def _make_vasp_kp_gamma(kpoints):
+    ret = ""
+    ret += "Automatic mesh\n"
+    ret += "0\n"
+    ret += "Gamma\n"
+    ret += "%d %d %d\n" % (kpoints[0], kpoints[1], kpoints[2])
+    ret += "0  0  0\n"
+    return ret
+
+def _make_vasp_kp_mp(kpoints):
+    ret = ""
+    ret += "K-Points\n"
+    ret += "0\n"
+    ret += "Monkhorst Pack\n"
+    ret += "%d %d %d\n" % (kpoints[0], kpoints[1], kpoints[2])
+    ret += "0  0  0\n"
+    return ret
+
+def _make_vasp_kpoints (kpoints, kgamma = False) :
+    if kgamma :
+        ret = _make_vasp_kp_gamma(kpoints)
+    else :
+        ret = _make_vasp_kp_mp(kpoints)
+    return ret
     
+def _reciprocal_box(box) :
+    rbox = np.linalg.inv(box)
+    rbox = rbox.T
+    return rbox
+
diff --git a/dpgen2/op/prep_vasp.py b/dpgen2/op/prep_vasp.py
index 8233fbd1..41443ec8 100644
--- a/dpgen2/op/prep_vasp.py
+++ b/dpgen2/op/prep_vasp.py
@@ -1,3 +1,4 @@
+import dpdata
 from dflow.python import (
     OP,
     OPIO,
@@ -5,9 +6,23 @@
     Artifact
 )
 import os, json
-from typing import Tuple, List, Set, Dict
+from typing import (
+    Tuple, 
+    List, 
+    Set, 
+    Dict,
+    Union,
+)
 from pathlib import Path
 from dpgen2.fp.vasp import VaspInputs
+from dpgen2.utils.chdir import set_directory
+from dpgen2.constants import (
+    vasp_task_pattern,
+    vasp_conf_name,
+    vasp_input_name,
+    vasp_pot_name,
+    vasp_kp_name,
+)
 
 class PrepVasp(OP):
     r"""Prepares the working directories for VASP tasks.
@@ -34,6 +49,7 @@ def get_output_sign(cls):
             "task_paths" : Artifact(List[Path]),
         })
 
+
     @OP.exec_sign_check
     def execute(
             self,
@@ -47,7 +63,7 @@ def execute(
             Input dict with components:
 
             - `inputs` : (`VaspInputs`) Definitions for the VASP inputs
-            - `confs` : (`Artifact(List[Path])`) Configuration files for the VASP tasks. 
+            - `confs` : (`Artifact(List[Path])`) Configurations for the VASP tasks. Stored in folders as deepmd/npy format. Can be parsed as dpdata.MultiSystems. 
         
         Returns
         -------
@@ -57,4 +73,49 @@ def execute(
             - `task_names`: (`List[str]`) The name of tasks. Will be used as the identities of the tasks. The names of different tasks are different.
             - `task_paths`: (`Artifact(List[Path])`) The parepared working paths of the tasks. Contains all input files needed to start the VASP. The order fo the Paths should be consistent with `op["task_names"]`
         """
-        raise NotImplementedError
+
+        inputs = ip['inputs']
+        confs = ip['confs']
+
+        task_names = []
+        task_paths = []
+        counter=0
+        # loop over list of MultiSystems
+        for mm in confs:
+            ms = dpdata.MultiSystems()
+            ms.from_deepmd_npy(mm, labeled=False)
+            # loop over Systems in MultiSystems
+            for ii in range(len(ms)):
+                ss = ms[ii]
+                # loop over frames
+                for ff in range(ss.get_nframes()):
+                    nn, pp = self._exec_one_frame(counter, inputs, ss[ff])
+                    task_names.append(nn)
+                    task_paths.append(pp)
+                    counter += 1
+        return OPIO({
+            'task_names' : task_names,
+            'task_paths' : task_paths,
+        })
+
+
+    def _exec_one_frame(
+            self,
+            idx,
+            vasp_inputs : VaspInputs,
+            conf_frame : dpdata.System,
+    ) -> str:
+        task_name = vasp_task_pattern % idx
+        task_path = Path(task_name)
+        with set_directory(task_path):
+            conf_frame.to('vasp/poscar', vasp_conf_name)
+            Path(vasp_input_name).write_text(
+                vasp_inputs.incar_template
+            )
+            Path(vasp_pot_name).write_text(
+                vasp_inputs.make_potcar(conf_frame['atom_names'])
+            )
+            Path(vasp_kp_name).write_text(
+                vasp_inputs.make_kpoints(conf_frame['cells'][0])
+            )
+        return task_name, task_path


Test patch:
diff --git a/tests/fake_data_set.py b/tests/fake_data_set.py
index bc5f78bc..b2af53d8 100644
--- a/tests/fake_data_set.py
+++ b/tests/fake_data_set.py
@@ -10,7 +10,8 @@ def fake_system(
     ss.data['atom_names'] = [atom_name]
     ss.data['atom_numbs'] = [natoms]
     ss.data['atom_types'] = [0 for ii in range(natoms)]
-    ss.data['cells'] = np.zeros([nframes, 3, 3])
+    #ss.data['cells'] = np.zeros([nframes, 3, 3])
+    ss.data['cells'] = np.tile(np.eye(3), [nframes, 1, 1])
     ss.data['coords'] = np.zeros([nframes, natoms, 3])
     ss.data['forces'] = np.zeros([nframes, natoms, 3])
     ss.data['energies'] = np.zeros([nframes])
diff --git a/tests/fp/context.py b/tests/fp/context.py
new file mode 100644
index 00000000..40c90ef5
--- /dev/null
+++ b/tests/fp/context.py
@@ -0,0 +1,3 @@
+import sys,os
+sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')))
+import dpgen2
diff --git a/tests/fp/data.vasp.kp.gf/INCAR b/tests/fp/data.vasp.kp.gf/INCAR
new file mode 100644
index 00000000..fd7f1859
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/INCAR
@@ -0,0 +1,23 @@
+PREC=A
+ENCUT=600
+ISYM=0
+ALGO=fast
+EDIFF=1.000000e-06
+LREAL=A
+NPAR=1
+KPAR=1
+
+NELMIN=4
+ISIF=2
+ISMEAR=1
+SIGMA=1.000000
+IBRION=-1
+
+NSW=0
+
+LWAVE=F
+LCHARG=F
+PSTRESS=0
+
+KSPACING=0.160000
+KGAMMA=.FALSE.
diff --git a/tests/fp/data.vasp.kp.gf/POSCAR b/tests/fp/data.vasp.kp.gf/POSCAR
new file mode 100644
index 00000000..322fe1aa
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/POSCAR
@@ -0,0 +1,9 @@
+POSCAR file written by OVITO
+1
+6.6326952 0.0 0.0
+0.1301009 6.5259342 0.0
+0.0170968 -0.0156295 6.4869027
+Al 
+1
+Cartesian
+0 0 0 
diff --git a/tests/fp/data.vasp.kp.gf/make_kp_test.py b/tests/fp/data.vasp.kp.gf/make_kp_test.py
new file mode 100644
index 00000000..4deddecd
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/make_kp_test.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python3
+
+import numpy as np
+import dpdata
+import ase,os
+
+
+def make_one(out_dir) :
+    # [0.5, 1)
+    [aa,bb,cc] = np.random.random(3) * 0.5 + 0.5
+    # [1, 179)
+    [alpha,beta,gamma] = np.random.random(3) * (178 / 180) + 1
+    # make cell
+    cell = ase.geometry.cellpar_to_cell([aa,bb,cc,alpha,beta,gamma])
+    sys = dpdata.System('POSCAR')
+    sys['cells'][0] = cell
+    os.makedirs(out_dir, exist_ok=True)
+    sys.to_vasp_poscar(os.path.join(out_dir, 'POSCAR'))
+    
+
+ntest = 30
+for ii in range(ntest) :
+     out_dir = 'test.%03d' % ii
+     make_one(out_dir)
diff --git a/tests/fp/data.vasp.kp.gf/test.000/POSCAR b/tests/fp/data.vasp.kp.gf/test.000/POSCAR
new file mode 100644
index 00000000..86f8649c
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.000/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+5.4127259713610210e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+7.8618816929019986e-01 2.4081028936890111e-02 0.0000000000000000e+00 
+6.7715811612933341e-01 8.3424435233163518e-03 1.5808741859753134e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.000/kp.ref b/tests/fp/data.vasp.kp.gf/test.000/kp.ref
new file mode 100644
index 00000000..ba3cf0c8
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.000/kp.ref
@@ -0,0 +1,1 @@
+ 3012 1844 2485
diff --git a/tests/fp/data.vasp.kp.gf/test.001/POSCAR b/tests/fp/data.vasp.kp.gf/test.001/POSCAR
new file mode 100644
index 00000000..90926fcb
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.001/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+5.6880700105188797e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+9.3755473569041059e-01 2.7862428092373298e-02 0.0000000000000000e+00 
+7.5094919110404246e-01 1.3658846496970233e-02 1.3537583670211236e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.001/kp.ref b/tests/fp/data.vasp.kp.gf/test.001/kp.ref
new file mode 100644
index 00000000..4d36af79
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.001/kp.ref
@@ -0,0 +1,1 @@
+ 2759 2003 2901
diff --git a/tests/fp/data.vasp.kp.gf/test.002/POSCAR b/tests/fp/data.vasp.kp.gf/test.002/POSCAR
new file mode 100644
index 00000000..99f9e362
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.002/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+7.1318152793059453e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+9.0090250362408364e-01 2.2057413311066729e-02 0.0000000000000000e+00 
+5.9568260849887056e-01 1.8603698586820437e-04 1.4346759150138591e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.002/kp.ref b/tests/fp/data.vasp.kp.gf/test.002/kp.ref
new file mode 100644
index 00000000..4104162a
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.002/kp.ref
@@ -0,0 +1,1 @@
+ 3187 1781 2738
diff --git a/tests/fp/data.vasp.kp.gf/test.003/POSCAR b/tests/fp/data.vasp.kp.gf/test.003/POSCAR
new file mode 100644
index 00000000..5c0fb951
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.003/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+9.9290805389638193e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+8.7190986412990223e-01 1.6171729506936849e-02 0.0000000000000000e+00 
+9.3585048431850237e-01 7.6384960535879976e-03 2.3018089381209059e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.003/kp.ref b/tests/fp/data.vasp.kp.gf/test.003/kp.ref
new file mode 100644
index 00000000..644274b4
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.003/kp.ref
@@ -0,0 +1,1 @@
+ 2316 2559 1707
diff --git a/tests/fp/data.vasp.kp.gf/test.004/POSCAR b/tests/fp/data.vasp.kp.gf/test.004/POSCAR
new file mode 100644
index 00000000..92b4d92a
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.004/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+6.2510904478129614e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+8.7599597707006160e-01 2.2319600269443796e-02 0.0000000000000000e+00 
+8.2278296275134177e-01 3.8799483550304068e-03 1.8371270941025968e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.004/kp.ref b/tests/fp/data.vasp.kp.gf/test.004/kp.ref
new file mode 100644
index 00000000..52c2b88f
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.004/kp.ref
@@ -0,0 +1,1 @@
+ 3368 1799 2138
diff --git a/tests/fp/data.vasp.kp.gf/test.005/POSCAR b/tests/fp/data.vasp.kp.gf/test.005/POSCAR
new file mode 100644
index 00000000..1fe0a36d
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.005/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+9.9053877966779680e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+5.3940028709160581e-01 1.8670361241875811e-02 0.0000000000000000e+00 
+7.7381050613360713e-01 1.2800166920594798e-02 1.9826939886769979e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.005/kp.ref b/tests/fp/data.vasp.kp.gf/test.005/kp.ref
new file mode 100644
index 00000000..617b49ea
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.005/kp.ref
@@ -0,0 +1,1 @@
+ 1403 2504 1981
diff --git a/tests/fp/data.vasp.kp.gf/test.006/POSCAR b/tests/fp/data.vasp.kp.gf/test.006/POSCAR
new file mode 100644
index 00000000..e18d9a78
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.006/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+5.1962337600558017e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+7.7015283686821623e-01 2.3582102183916275e-02 0.0000000000000000e+00 
+8.8645171326257188e-01 1.3693290237640118e-02 9.0982527300307661e-03 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.006/kp.ref b/tests/fp/data.vasp.kp.gf/test.006/kp.ref
new file mode 100644
index 00000000..3a2185d0
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.006/kp.ref
@@ -0,0 +1,1 @@
+ 4406 3010 4317
diff --git a/tests/fp/data.vasp.kp.gf/test.007/POSCAR b/tests/fp/data.vasp.kp.gf/test.007/POSCAR
new file mode 100644
index 00000000..b6b298a4
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.007/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+9.0778928724851427e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+5.0174477170218057e-01 8.7638477359290260e-03 0.0000000000000000e+00 
+5.7691634780896750e-01 6.9486384276072335e-03 1.1319556047435765e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.007/kp.ref b/tests/fp/data.vasp.kp.gf/test.007/kp.ref
new file mode 100644
index 00000000..43e2cc8e
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.007/kp.ref
@@ -0,0 +1,1 @@
+ 2570 5258 3470
diff --git a/tests/fp/data.vasp.kp.gf/test.008/POSCAR b/tests/fp/data.vasp.kp.gf/test.008/POSCAR
new file mode 100644
index 00000000..491f71a0
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.008/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+7.9430397140351772e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+6.7703587724520653e-01 2.0197502612753639e-02 0.0000000000000000e+00 
+8.9944450316391611e-01 1.2190061829841534e-02 1.8455625620951665e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.008/kp.ref b/tests/fp/data.vasp.kp.gf/test.008/kp.ref
new file mode 100644
index 00000000..f641fe4e
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.008/kp.ref
@@ -0,0 +1,1 @@
+ 2117 2331 2128
diff --git a/tests/fp/data.vasp.kp.gf/test.009/POSCAR b/tests/fp/data.vasp.kp.gf/test.009/POSCAR
new file mode 100644
index 00000000..d647340d
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.009/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+6.4107824073770014e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+5.9514813102041653e-01 1.4122096000048717e-02 0.0000000000000000e+00 
+7.9753239756842043e-01 -3.1662388773523020e-03 1.4910307577850239e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.009/kp.ref b/tests/fp/data.vasp.kp.gf/test.009/kp.ref
new file mode 100644
index 00000000..3cebf71e
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.009/kp.ref
@@ -0,0 +1,1 @@
+ 4615 2843 2634
diff --git a/tests/fp/data.vasp.kp.gf/test.010/POSCAR b/tests/fp/data.vasp.kp.gf/test.010/POSCAR
new file mode 100644
index 00000000..d833a5dd
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.010/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+5.5550486411663158e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+6.8070960410020875e-01 1.4350480968449014e-02 0.0000000000000000e+00 
+9.6801337243813057e-01 1.7342606777491703e-02 2.0266814112522992e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.010/kp.ref b/tests/fp/data.vasp.kp.gf/test.010/kp.ref
new file mode 100644
index 00000000..8a3815ac
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.010/kp.ref
@@ -0,0 +1,1 @@
+ 3393 3602 1938
diff --git a/tests/fp/data.vasp.kp.gf/test.011/POSCAR b/tests/fp/data.vasp.kp.gf/test.011/POSCAR
new file mode 100644
index 00000000..97df8061
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.011/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+8.5870696695197124e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+5.1893704956323827e-01 1.1776894361646813e-02 0.0000000000000000e+00 
+6.3519056323670364e-01 5.0285215989483009e-03 1.5158501840668978e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.011/kp.ref b/tests/fp/data.vasp.kp.gf/test.011/kp.ref
new file mode 100644
index 00000000..8fc60f8f
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.011/kp.ref
@@ -0,0 +1,1 @@
+ 2371 3514 2591
diff --git a/tests/fp/data.vasp.kp.gf/test.012/POSCAR b/tests/fp/data.vasp.kp.gf/test.012/POSCAR
new file mode 100644
index 00000000..9a5b00f6
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.012/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+9.4351735339550946e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+6.0999656860152052e-01 1.7148923876854596e-02 0.0000000000000000e+00 
+7.1637100648807928e-01 1.1870854711635171e-02 1.1964593611508943e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.012/kp.ref b/tests/fp/data.vasp.kp.gf/test.012/kp.ref
new file mode 100644
index 00000000..455476a5
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.012/kp.ref
@@ -0,0 +1,1 @@
+ 1801 3226 3283
diff --git a/tests/fp/data.vasp.kp.gf/test.013/POSCAR b/tests/fp/data.vasp.kp.gf/test.013/POSCAR
new file mode 100644
index 00000000..f73c9eaa
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.013/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+5.9990177759298668e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+9.2886495622654708e-01 2.5044515831327989e-02 0.0000000000000000e+00 
+6.1638694777449798e-01 3.5946492305453936e-03 1.3705944562333917e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.013/kp.ref b/tests/fp/data.vasp.kp.gf/test.013/kp.ref
new file mode 100644
index 00000000..38e72b31
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.013/kp.ref
@@ -0,0 +1,1 @@
+ 3350 1622 2866
diff --git a/tests/fp/data.vasp.kp.gf/test.014/POSCAR b/tests/fp/data.vasp.kp.gf/test.014/POSCAR
new file mode 100644
index 00000000..623135c3
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.014/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+8.4054798625146632e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+6.6292027037099721e-01 2.0213000030988901e-02 0.0000000000000000e+00 
+6.5074072860649845e-01 7.0429905975569664e-03 1.0835310572355412e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.014/kp.ref b/tests/fp/data.vasp.kp.gf/test.014/kp.ref
new file mode 100644
index 00000000..daef6b04
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.014/kp.ref
@@ -0,0 +1,1 @@
+ 2372 2318 3625
diff --git a/tests/fp/data.vasp.kp.gf/test.015/POSCAR b/tests/fp/data.vasp.kp.gf/test.015/POSCAR
new file mode 100644
index 00000000..59e542f7
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.015/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+9.0592670804143993e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+7.0164106324818487e-01 2.1732588605303776e-02 0.0000000000000000e+00 
+8.8666934784642748e-01 1.8228661223474250e-02 2.0519776281709610e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.015/kp.ref b/tests/fp/data.vasp.kp.gf/test.015/kp.ref
new file mode 100644
index 00000000..5ce551c9
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.015/kp.ref
@@ -0,0 +1,1 @@
+ 1536 2417 1914
diff --git a/tests/fp/data.vasp.kp.gf/test.016/POSCAR b/tests/fp/data.vasp.kp.gf/test.016/POSCAR
new file mode 100644
index 00000000..80e21ce0
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.016/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+6.2808818210241246e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+6.2949227090630400e-01 1.5699128478506564e-02 0.0000000000000000e+00 
+5.9031653449750210e-01 9.0790581254778426e-03 1.8332430081517040e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.016/kp.ref b/tests/fp/data.vasp.kp.gf/test.016/kp.ref
new file mode 100644
index 00000000..d44e7991
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.016/kp.ref
@@ -0,0 +1,1 @@
+ 2624 2792 2143
diff --git a/tests/fp/data.vasp.kp.gf/test.017/POSCAR b/tests/fp/data.vasp.kp.gf/test.017/POSCAR
new file mode 100644
index 00000000..4acd4d1b
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.017/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+6.7183926821441775e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+6.4140141985920385e-01 1.4352733214998581e-02 0.0000000000000000e+00 
+9.8021519702240911e-01 3.8684916997537011e-03 1.7031593077790490e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.017/kp.ref b/tests/fp/data.vasp.kp.gf/test.017/kp.ref
new file mode 100644
index 00000000..0bd060d6
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.017/kp.ref
@@ -0,0 +1,1 @@
+ 3809 2806 2306
diff --git a/tests/fp/data.vasp.kp.gf/test.018/POSCAR b/tests/fp/data.vasp.kp.gf/test.018/POSCAR
new file mode 100644
index 00000000..95e3625a
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.018/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+9.0904675499270871e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+7.1357506069253507e-01 2.0653299473695933e-02 0.0000000000000000e+00 
+5.6191429011053162e-01 6.8530669078996310e-03 8.2949112079975656e-03 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.018/kp.ref b/tests/fp/data.vasp.kp.gf/test.018/kp.ref
new file mode 100644
index 00000000..135de949
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.018/kp.ref
@@ -0,0 +1,1 @@
+ 2258 2467 4735
diff --git a/tests/fp/data.vasp.kp.gf/test.019/POSCAR b/tests/fp/data.vasp.kp.gf/test.019/POSCAR
new file mode 100644
index 00000000..f0b6b934
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.019/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+6.4026766094815746e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+8.9305845794356431e-01 2.4670136019966725e-02 0.0000000000000000e+00 
+8.1428436058792186e-01 6.0057917170911659e-03 1.4588637440111405e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.019/kp.ref b/tests/fp/data.vasp.kp.gf/test.019/kp.ref
new file mode 100644
index 00000000..a909be0a
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.019/kp.ref
@@ -0,0 +1,1 @@
+ 3352 1722 2692
diff --git a/tests/fp/data.vasp.kp.gf/test.020/POSCAR b/tests/fp/data.vasp.kp.gf/test.020/POSCAR
new file mode 100644
index 00000000..ab1189c6
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.020/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+6.8594934473558355e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+9.6687449166074457e-01 2.3715030862177477e-02 0.0000000000000000e+00 
+6.8762327046143379e-01 1.0364949378730682e-02 1.5799497242638412e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.020/kp.ref b/tests/fp/data.vasp.kp.gf/test.020/kp.ref
new file mode 100644
index 00000000..3008e329
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.020/kp.ref
@@ -0,0 +1,1 @@
+ 2525 1981 2486
diff --git a/tests/fp/data.vasp.kp.gf/test.021/POSCAR b/tests/fp/data.vasp.kp.gf/test.021/POSCAR
new file mode 100644
index 00000000..696e6c24
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.021/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+7.3554024077214453e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+8.1638656898051709e-01 2.5391675987756768e-02 0.0000000000000000e+00 
+6.2524529611437596e-01 9.3128812085326602e-03 1.3441851906291361e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.021/kp.ref b/tests/fp/data.vasp.kp.gf/test.021/kp.ref
new file mode 100644
index 00000000..946f4068
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.021/kp.ref
@@ -0,0 +1,1 @@
+ 2151 1882 2922
diff --git a/tests/fp/data.vasp.kp.gf/test.022/POSCAR b/tests/fp/data.vasp.kp.gf/test.022/POSCAR
new file mode 100644
index 00000000..a422e0c4
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.022/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+8.8048895544046824e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+9.6154868911418356e-01 3.2033436833257448e-02 0.0000000000000000e+00 
+9.7271788298409301e-01 8.3132749231043680e-03 1.6867644942364032e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.022/kp.ref b/tests/fp/data.vasp.kp.gf/test.022/kp.ref
new file mode 100644
index 00000000..0d7ca624
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.022/kp.ref
@@ -0,0 +1,1 @@
+ 2335 1367 2329
diff --git a/tests/fp/data.vasp.kp.gf/test.023/POSCAR b/tests/fp/data.vasp.kp.gf/test.023/POSCAR
new file mode 100644
index 00000000..e50e30ef
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.023/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+9.9242002811213836e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+7.3678428169130761e-01 1.3088540016532589e-02 0.0000000000000000e+00 
+6.7762054769321078e-01 1.4681922343327957e-03 1.2965836382839194e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.023/kp.ref b/tests/fp/data.vasp.kp.gf/test.023/kp.ref
new file mode 100644
index 00000000..86b6e289
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.023/kp.ref
@@ -0,0 +1,1 @@
+ 2875 3020 3029
diff --git a/tests/fp/data.vasp.kp.gf/test.024/POSCAR b/tests/fp/data.vasp.kp.gf/test.024/POSCAR
new file mode 100644
index 00000000..73c2ee95
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.024/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+7.2216474674443032e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+6.6935422004335077e-01 1.6694693700306504e-02 0.0000000000000000e+00 
+8.9534541552420710e-01 1.7436949895310000e-02 2.3785962099237896e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.024/kp.ref b/tests/fp/data.vasp.kp.gf/test.024/kp.ref
new file mode 100644
index 00000000..d1f4da59
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.024/kp.ref
@@ -0,0 +1,1 @@
+ 2227 2917 1651
diff --git a/tests/fp/data.vasp.kp.gf/test.025/POSCAR b/tests/fp/data.vasp.kp.gf/test.025/POSCAR
new file mode 100644
index 00000000..b3362a18
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.025/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+8.9117435342322038e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+6.3409939955121208e-01 1.9968611983052557e-02 0.0000000000000000e+00 
+5.0895483976207867e-01 6.3684100723567965e-03 8.3841132142836797e-03 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.025/kp.ref b/tests/fp/data.vasp.kp.gf/test.025/kp.ref
new file mode 100644
index 00000000..7af96f06
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.025/kp.ref
@@ -0,0 +1,1 @@
+ 2136 2470 4684
diff --git a/tests/fp/data.vasp.kp.gf/test.026/POSCAR b/tests/fp/data.vasp.kp.gf/test.026/POSCAR
new file mode 100644
index 00000000..60a3b0ab
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.026/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+6.6146943697405836e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+7.5311939800441674e-01 1.4380427233774489e-02 0.0000000000000000e+00 
+6.3888769875715334e-01 -1.6310546934199758e-03 1.1825304039599110e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.026/kp.ref b/tests/fp/data.vasp.kp.gf/test.026/kp.ref
new file mode 100644
index 00000000..bb709195
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.026/kp.ref
@@ -0,0 +1,1 @@
+ 4785 2757 3321
diff --git a/tests/fp/data.vasp.kp.gf/test.027/POSCAR b/tests/fp/data.vasp.kp.gf/test.027/POSCAR
new file mode 100644
index 00000000..367b4bc5
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.027/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+6.8488504358517499e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+6.4733602786911981e-01 1.8986412365836220e-02 0.0000000000000000e+00 
+5.4847407769833134e-01 6.7603520231260773e-03 1.2632337835217923e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.027/kp.ref b/tests/fp/data.vasp.kp.gf/test.027/kp.ref
new file mode 100644
index 00000000..637d2b03
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.027/kp.ref
@@ -0,0 +1,1 @@
+ 2431 2346 3109
diff --git a/tests/fp/data.vasp.kp.gf/test.028/POSCAR b/tests/fp/data.vasp.kp.gf/test.028/POSCAR
new file mode 100644
index 00000000..2036ea84
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.028/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+7.7714368902548037e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+5.1744302821750987e-01 9.2339899572028723e-03 0.0000000000000000e+00 
+8.0249076087440185e-01 1.8781333828875989e-02 1.9301537101012855e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.028/kp.ref b/tests/fp/data.vasp.kp.gf/test.028/kp.ref
new file mode 100644
index 00000000..bbaddc01
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.028/kp.ref
@@ -0,0 +1,1 @@
+ 2907 5934 2035
diff --git a/tests/fp/data.vasp.kp.gf/test.029/POSCAR b/tests/fp/data.vasp.kp.gf/test.029/POSCAR
new file mode 100644
index 00000000..f6666f03
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.029/POSCAR
@@ -0,0 +1,9 @@
+Al1 
+1.0
+8.1827757864115269e-01 0.0000000000000000e+00 0.0000000000000000e+00 
+7.0976104277800611e-01 1.2594842675049416e-02 0.0000000000000000e+00 
+6.0244177763787687e-01 1.3692427728208972e-02 1.1282872913318998e-02 
+Al 
+1 
+cartesian
+   0.0000000000    0.0000000000    0.0000000000
diff --git a/tests/fp/data.vasp.kp.gf/test.029/kp.ref b/tests/fp/data.vasp.kp.gf/test.029/kp.ref
new file mode 100644
index 00000000..d577087b
--- /dev/null
+++ b/tests/fp/data.vasp.kp.gf/test.029/kp.ref
@@ -0,0 +1,1 @@
+ 2799 4903 3481
diff --git a/tests/fp/test_vasp.py b/tests/fp/test_vasp.py
new file mode 100644
index 00000000..5dd0ea83
--- /dev/null
+++ b/tests/fp/test_vasp.py
@@ -0,0 +1,106 @@
+from context import dpgen2
+import os,sys,json,glob,shutil,textwrap
+import dpdata
+import numpy as np
+import unittest
+from dpgen2.fp.vasp import make_kspacing_kpoints, VaspInputs
+from pathlib import Path
+
+class TestVASPInputs(unittest.TestCase):
+    def setUp(self):
+        Path('template.incar').write_text('foo')
+        Path('POTCAR_H').write_text('bar H\n')
+        Path('POTCAR_O').write_text('bar O\n')
+
+    def tearDown(self):
+        os.remove('template.incar')
+        os.remove('POTCAR_H')
+        os.remove('POTCAR_O')        
+        if Path('POSCAR').is_file():
+            os.remove('POSCAR')
+
+    def test_make_kp (self):
+        kspacing = 0.16
+        gamma = False
+        test_path = (Path(__file__).parent)
+        all_test = glob.glob(os.path.join(test_path/'data.vasp.kp.gf', 'test.*'))
+        self.assertEqual(len(all_test), 30)
+        for ii in all_test :
+            ss = dpdata.System(Path(ii)/'POSCAR')            
+            ret=make_kspacing_kpoints(ss['cells'][0], kspacing, gamma)
+            kp = [int(jj) for jj in (ret.split('\n')[3].split())]
+            kp_ref = list(np.loadtxt(os.path.join(ii, 'kp.ref'), dtype = int))
+            self.assertTrue(kp == kp_ref)
+
+    def test_vasp_input_incar_potcar(self):
+        iincar = 'template.incar'
+        ipotcar = {'H' : 'POTCAR_H', 'O' : 'POTCAR_O'}
+        vi = VaspInputs(0.16, True, iincar, ipotcar)
+        self.assertEqual(vi.incar_template, 'foo')
+        self.assertEqual(vi.potcars['O'], 'bar O\n')
+        self.assertEqual(vi.potcars['H'], 'bar H\n')
+        atom_names = ['O', 'H']
+        self.assertEqual(vi.make_potcar(atom_names), 'bar O\nbar H\n')
+
+    def test_vasp_input_kp(self):
+        ref = textwrap.dedent(
+"""Automatic mesh
+0
+Gamma
+10 7 7
+0  0  0
+"""
+        )
+        poscar = textwrap.dedent(
+"""Foo
+1
+0.00 6.00 6.00
+8.00 0.00 8.00
+9.00 9.00 0.00
+O 
+1 
+Selective dynamics
+Cartesian
+0.00 0.00 0.00 T T F
+"""
+        )
+        Path('POSCAR').write_text(poscar)
+        iincar = 'template.incar'
+        ipotcar = {'H' : 'POTCAR_H', 'O' : 'POTCAR_O'}
+        vi = VaspInputs(0.1, True, iincar, ipotcar)
+        ss = dpdata.System('POSCAR')
+        kps = vi.make_kpoints(ss['cells'][0])
+        self.assertEqual(ref, kps)
+
+        
+    def test_vasp_input_kp(self):
+        ref = textwrap.dedent(
+"""K-Points
+0
+Monkhorst Pack
+10 7 7
+0  0  0
+"""
+        )
+        poscar = textwrap.dedent(
+"""Cubic BN
+1
+0.00 6.00 6.00
+8.00 0.00 8.00
+9.00 9.00 0.00
+O 
+1 
+Selective dynamics
+Cartesian
+0.00 0.00 0.00 T T F
+"""
+        )
+        Path('POSCAR').write_text(poscar)
+        iincar = 'template.incar'
+        ipotcar = {'H' : 'POTCAR_H', 'O' : 'POTCAR_O'}
+        vi = VaspInputs(0.1, False, iincar, ipotcar)
+        ss = dpdata.System('POSCAR')
+        kps = vi.make_kpoints(ss['cells'][0])
+        self.assertEqual(ref, kps)
+
+        
diff --git a/tests/op/test_prep_vasp.py b/tests/op/test_prep_vasp.py
new file mode 100644
index 00000000..bbbc1a5e
--- /dev/null
+++ b/tests/op/test_prep_vasp.py
@@ -0,0 +1,119 @@
+from context import dpgen2
+import os,sys,json,glob,shutil,textwrap
+import dpdata
+import numpy as np
+import unittest
+from dpgen2.fp.vasp import VaspInputs
+from dpgen2.op.prep_vasp import PrepVasp
+from pathlib import Path
+from dpgen2.constants import (
+    vasp_task_pattern,
+    vasp_input_name,
+    vasp_pot_name,
+    vasp_kp_name,
+    vasp_conf_name,
+)
+from fake_data_set import fake_system, fake_multi_sys
+from dflow.python import (
+    OP,
+    OPIO,
+    OPIOSign,
+    Artifact,
+    TransientError,
+    FatalError,
+)
+
+
+class TestPrepVasp(unittest.TestCase):
+    def setUp(self):
+        Path('template.incar').write_text('foo')
+        Path('POTCAR_H').write_text('bar H\n')
+        Path('POTCAR_O').write_text('bar O\n')
+        self.nframes_0 = [2, 5, 3]
+        self.natoms_0 = [4, 3, 4]
+        self.nframes_1 = [3, 4, 2]
+        self.natoms_1 = [5, 3, 2]
+        ms_0 = fake_multi_sys( self.nframes_0, self.natoms_0, 'O')
+        ms_1 = fake_multi_sys( self.nframes_1, self.natoms_1, 'H')
+        ms_0.to_deepmd_npy('data-0')
+        ms_1.to_deepmd_npy('data-1')
+        self.confs = ['data-0', 'data-1']
+        self.confs = [Path(ii) for ii in self.confs]    
+        
+    def tearDown(self):
+        os.remove('template.incar')
+        os.remove('POTCAR_H')
+        os.remove('POTCAR_O')
+        for ii in self.confs:
+            if ii.is_dir():
+                shutil.rmtree(ii)
+        tot_f_0 = sum(self.nframes_0)
+        tot_f_1 = sum(self.nframes_1)
+        tot_f = tot_f_0 + tot_f_1
+        for ii in range(tot_f):
+            tname = Path(vasp_task_pattern%ii)
+            if tname.is_dir():
+                shutil.rmtree(tname)
+        
+    def check_sys(self, ss0, ss1):
+        self.assertEqual(ss0['atom_numbs'], ss1['atom_numbs'])
+        self.assertEqual(ss0['atom_names'], ss1['atom_names'])
+
+        
+    def test(self):
+        refkp = textwrap.dedent(
+"""Automatic mesh
+0
+Gamma
+63 63 63
+0  0  0
+""")
+        iincar = 'template.incar'
+        ipotcar = {'H' : 'POTCAR_H', 'O' : 'POTCAR_O'}
+        vi = VaspInputs(0.1, True, iincar, ipotcar)
+        op = PrepVasp()
+        opout = op.execute(OPIO({
+            'inputs': vi,
+            'confs' : self.confs,
+        }))
+        task_names = opout['task_names']
+        task_paths = opout['task_paths']
+        tot_f_0 = sum(self.nframes_0)
+        tot_f_1 = sum(self.nframes_1)
+        tot_f = tot_f_0 + tot_f_1
+        for ii in range(tot_f):
+            self.assertEqual(task_names[ii], vasp_task_pattern%ii)
+            self.assertEqual(str(task_paths[ii]), vasp_task_pattern%ii)
+        for ii in range(tot_f_0):
+            ipath = task_paths[ii]
+            self.assertEqual('foo', (ipath/vasp_input_name).read_text())
+            self.assertEqual('bar O\n', (ipath/vasp_pot_name).read_text())
+            self.assertEqual(refkp, (ipath/vasp_kp_name).read_text())
+        for ii in range(tot_f_0, tot_f):
+            ipath = task_paths[ii]
+            self.assertEqual('foo', (ipath/vasp_input_name).read_text())
+            self.assertEqual('bar H\n', (ipath/vasp_pot_name).read_text())
+            self.assertEqual(refkp, (ipath/vasp_kp_name).read_text())
+        ms0 = dpdata.MultiSystems()
+        ms0.from_deepmd_npy(self.confs[0])
+        ms1 = dpdata.MultiSystems()
+        ms1.from_deepmd_npy(self.confs[1])
+        self.check_sys(dpdata.System(task_paths[0]/vasp_conf_name), ms0[0][0])
+        self.check_sys(dpdata.System(task_paths[1]/vasp_conf_name), ms0[0][1])
+        self.check_sys(dpdata.System(task_paths[2]/vasp_conf_name), ms0[0][2])
+        self.check_sys(dpdata.System(task_paths[3]/vasp_conf_name), ms0[0][3])
+        self.check_sys(dpdata.System(task_paths[4]/vasp_conf_name), ms0[0][4])
+        self.check_sys(dpdata.System(task_paths[5]/vasp_conf_name), ms0[1][0])
+        self.check_sys(dpdata.System(task_paths[6]/vasp_conf_name), ms0[1][1])
+        self.check_sys(dpdata.System(task_paths[7]/vasp_conf_name), ms0[1][2])
+        self.check_sys(dpdata.System(task_paths[8]/vasp_conf_name), ms0[1][3])
+        self.check_sys(dpdata.System(task_paths[9]/vasp_conf_name), ms0[1][4])
+        self.check_sys(dpdata.System(task_paths[10]/vasp_conf_name), ms1[0][0])
+        self.check_sys(dpdata.System(task_paths[11]/vasp_conf_name), ms1[0][1])
+        self.check_sys(dpdata.System(task_paths[12]/vasp_conf_name), ms1[1][0])
+        self.check_sys(dpdata.System(task_paths[13]/vasp_conf_name), ms1[1][1])
+        self.check_sys(dpdata.System(task_paths[14]/vasp_conf_name), ms1[1][2])
+        self.check_sys(dpdata.System(task_paths[15]/vasp_conf_name), ms1[1][3])
+        self.check_sys(dpdata.System(task_paths[16]/vasp_conf_name), ms1[2][0])
+        self.check_sys(dpdata.System(task_paths[17]/vasp_conf_name), ms1[2][1])
+        self.check_sys(dpdata.System(task_paths[18]/vasp_conf_name), ms1[2][2])