Initiated the regression test setup
This commit is contained in:
172
tools/regression-tests/run_tests.py
Normal file
172
tools/regression-tests/run_tests.py
Normal file
@ -0,0 +1,172 @@
|
||||
'''
|
||||
UPDATE: Oct 25, 2023:
|
||||
Launching the LAMMPS binary under testing using a configuration defined in a yaml file (e.g. config.yaml)
|
||||
this way we can launch LAMMPS with mpirun with more flexibility. Also it simplifies the build configuration.
|
||||
|
||||
python3 run_tests.py /path/to/lmp_binary
|
||||
|
||||
Original plan: using the LAMMPS Python module
|
||||
The following steps are for setting up regression tests with the LAMMPS Python module
|
||||
|
||||
0) Create a virtual environment, and activate it
|
||||
|
||||
python -m venv lmp-venv
|
||||
source lmp-venv/bin/activate
|
||||
PYTHON_EXECUTABLE=`which python`
|
||||
INSTALL_PREFIX=$(${PYTHON_EXECUTABLE} -c "import sys; print(sys.prefix)")
|
||||
|
||||
1) Build LAMMPS as a shared lib and install the LAMMPS python module into the virtual environment
|
||||
|
||||
git clone https://github.com/lammps/lammps.git lammps
|
||||
cd lammps
|
||||
mkdir build && cd build
|
||||
cmake ../cmake/presets/basic.cmake -DBUILD_SHARED_LIBS=on -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX
|
||||
make -j4
|
||||
make install-python
|
||||
|
||||
2) Run this script, after activating the virtual environment and having the input scripts with markers ready:
|
||||
|
||||
source lmp-venv/bin/activate
|
||||
python3 run_tests.py
|
||||
|
||||
'''
|
||||
|
||||
#from lammps import lammps
|
||||
import sys
|
||||
import re, yaml
|
||||
import subprocess
|
||||
|
||||
try:
|
||||
from yaml import CSafeLoader as Loader
|
||||
except ImportError:
|
||||
from yaml import SafeLoader as Loader
|
||||
|
||||
'''
|
||||
inputFileName: input file with comments #REG:ADD and #REG:SUB as markers
|
||||
outputFileName: modified input file ready for testing
|
||||
'''
|
||||
def processing_markers(inputFileName, outputFileName):
|
||||
# read in the script
|
||||
with open(inputFileName, 'r') as file:
|
||||
data = file.read()
|
||||
|
||||
# replace #REG:ADD with empty string (i.e. adding the text at the end of the line)
|
||||
data = data.replace("#REG:ADD", "")
|
||||
|
||||
# replace the line contaning #REG:SUB with a line with the text that follows this marker
|
||||
data = data.splitlines()
|
||||
separator="#REG:SUB"
|
||||
out = []
|
||||
for line in data:
|
||||
s = line.split(separator)
|
||||
if len(s) < 2:
|
||||
out.append(line)
|
||||
else:
|
||||
out.append(s[1])
|
||||
|
||||
# write data to the new script
|
||||
with open(outputFileName, 'w') as file:
|
||||
for line in out:
|
||||
file.write(line + "\n")
|
||||
|
||||
'''
|
||||
yamlFileName: input YAML file with thermo structured as described in https://docs.lammps.org/Howto_structured_data.html
|
||||
return: thermo, which is a list containing a dictionary for each run where the tag "keywords" maps to the list
|
||||
of thermo header strings and the tag “data” has a list of lists where the outer list represents the lines
|
||||
of output and the inner list the values of the columns matching the header keywords for that step.
|
||||
'''
|
||||
def extract_thermo(yamlFileName):
|
||||
docs = ""
|
||||
with open(yamlFileName) as f:
|
||||
for line in f:
|
||||
m = re.search(r"^(keywords:.*$|data:$|---$|\.\.\.$| - \[.*\]$)", line)
|
||||
if m: docs += m.group(0) + '\n'
|
||||
|
||||
thermo = list(yaml.load_all(docs, Loader=Loader))
|
||||
return thermo
|
||||
|
||||
'''
|
||||
launch LAMMPS using the configuration defined in the dictionary config with an input file
|
||||
TODO:
|
||||
- generate new reference values if needed
|
||||
- wrap subprocess with try/catch to handle exceptions
|
||||
'''
|
||||
def execute(lmp_binary, config, input_file_name, generate_ref_yaml=False):
|
||||
cmd_str = config['mpiexec'] + " " + config['mpiexec_numproc_flag'] + " " + config['nprocs'] + " "
|
||||
cmd_str += lmp_binary + " -in " + input_file_name + " " + config['args']
|
||||
print(f"Execute: {cmd_str}")
|
||||
p = subprocess.run(cmd_str, shell=True, text=True, capture_output=True)
|
||||
output = p.stdout.split('\n')
|
||||
|
||||
'''
|
||||
TODO:
|
||||
- process "lmp -h" to get the list of installed packages
|
||||
- automate tagging the example input scripts of the installed packages
|
||||
'''
|
||||
if __name__ == "__main__":
|
||||
|
||||
lmp_binary = ""
|
||||
# if lmp binary is specified in the command line
|
||||
if len(sys.argv) >= 2:
|
||||
lmp_binary = sys.argv[1]
|
||||
|
||||
# list of input scripts with markers #REG:SUB and #REG:ADD
|
||||
input_list=['in.lj', 'in.rhodo']
|
||||
|
||||
# read in the configuration of the tests
|
||||
with open("config.yaml", 'r') as f:
|
||||
config = yaml.load(f, Loader=Loader)
|
||||
print(config)
|
||||
|
||||
# check if lmp_binary is specified in the config yaml
|
||||
if lmp_binary == "":
|
||||
if config['lmp_binary'] == "":
|
||||
print("Needs a valid LAMMPS binary")
|
||||
exit
|
||||
else:
|
||||
lmp_binary = config['lmp_binary']
|
||||
|
||||
# iterative over the input scripts
|
||||
for input in input_list:
|
||||
input_test=input + '.test'
|
||||
processing_markers(input, input_test)
|
||||
|
||||
str_t = "Running " + input_test
|
||||
print(str_t)
|
||||
print(f"-"*len(str_t))
|
||||
|
||||
# using the LAMMPS python module (for single-proc runs)
|
||||
# lmp = lammps()
|
||||
# lmp.file(input_test)
|
||||
|
||||
# or more customizable with config.yaml
|
||||
execute(lmp_binary, config, input_test)
|
||||
|
||||
# process thermo output
|
||||
thermo = extract_thermo("log.lammps")
|
||||
|
||||
num_runs = len(thermo)
|
||||
if num_runs == 0:
|
||||
print(f"Failed with {input_test}\n")
|
||||
continue
|
||||
|
||||
print(f"Number of runs: {num_runs}")
|
||||
|
||||
# read in the thermo yaml output
|
||||
thermo_ref_file = 'thermo.' + input + '.yaml'
|
||||
thermo_ref = extract_thermo(thermo_ref_file)
|
||||
|
||||
# comparing output vs reference values
|
||||
width = 20
|
||||
print("Quantities".ljust(width) + "Output".center(width) + "Reference".center(width) + "Diff.".center(width))
|
||||
irun = 0
|
||||
num_fields = len(thermo[irun]['keywords'])
|
||||
for i in range(num_fields):
|
||||
val = thermo[irun]['data'][2][i]
|
||||
ref = thermo[0]['data'][2][i]
|
||||
diff = float(val) - float(ref)
|
||||
print(f"{thermo[0]['keywords'][i].ljust(width)} {str(val).rjust(20)} {str(ref).rjust(20)} {str(diff).rjust(20)}")
|
||||
print("-"*(4*width+3))
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user