4
1
mirror of https://github.com/pfloos/quack synced 2024-12-31 08:36:05 +01:00

workflow for testing

This commit is contained in:
Abdallah Ammar 2024-11-15 17:22:07 +01:00
parent 1cccc81c0d
commit 8bf9c44027
6 changed files with 121 additions and 39 deletions

View File

@ -11,27 +11,30 @@ on:
jobs: jobs:
configuration: build:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
name: Dependencies name: Dependencies
steps: steps:
- name: install dependencies - name: Checkout repository
uses: actions/checkout@v3
- name: Install dependencies
run: | run: |
sudo apt install gfortran gcc liblapack-dev libblas-dev wget python3 make m4 pkg-config sudo apt-get update
sudo apt-get install -y gfortran gcc liblapack-dev libblas-dev wget python3 make m4 pkg-config
compilation:
name: Compilation
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- name: Configuration - name: Configuration
run: | run: |
./configure -i ninja || : ./configure -i ninja || :
- name: Compilation - name: Compilation
run: | run: |
bash -c "source quack.rc ; cd src ; exec make" bash -c "source quack.rc ; cd src ; make"
- name: Upload compiled binary
uses: actions/upload-artifact@v3
with:
name: fortran-binary
path: ./bin/QuAcK

37
.github/workflows/testing.yml vendored Normal file
View File

@ -0,0 +1,37 @@
name: QuAcK Testing
on:
workflow_run:
workflows: ["QuAcK Compilation"]
types:
- completed
jobs:
test:
runs-on: ubuntu-20.04
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Download compiled binary from previous workflow
uses: actions/download-artifact@v3
with:
name: fortran-binary
path: ./bin/QuAcK
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install pyscf
- name: Run tests
run: |
bash -c "source quack.rc ; cd tests ; python lunch_bench.py -s light -t 1e-1"

View File

@ -212,7 +212,7 @@ program QuAcK
dotest = doRtest .or. doUtest .or. doGtest dotest = doRtest .or. doUtest .or. doGtest
if(dotest) call init_test(doRtest,doUtest,doGtest) if(dotest) call init_test(working_dir,doRtest,doUtest,doGtest)
!-------------------------! !-------------------------!
! Restricted QuAcK branch ! ! Restricted QuAcK branch !

View File

@ -1,21 +1,41 @@
subroutine init_test(doRtest,doUtest,doGtest) subroutine init_test(working_dir,doRtest,doUtest,doGtest)
implicit none implicit none
! Input variables ! Input variables
character(len=256),intent(in) :: working_dir
logical,intent(in) :: doRtest logical,intent(in) :: doRtest
logical,intent(in) :: doUtest logical,intent(in) :: doUtest
logical,intent(in) :: doGtest logical,intent(in) :: doGtest
! Local variables ! Local variables
integer :: status
character(len=256) :: file_path
! Output variables ! Output variables
if(doRtest) open(unit=1231597, file='test/Rtest.dat') if(doRtest) then
file_path = trim(working_dir) // '/test/Rtest.dat'
open(unit=1231597, file=file_path, iostat=status)
if(status /= 0) then
print *, "Error opening file: ", file_path
stop
else
print *, "opening file successed"
endif
endif
if(doUtest) open(unit=1232584, file='test/Utest.dat') if(doUtest) then
file_path = trim(working_dir) // '/test/Utest.dat'
open(unit=1232584, file=file_path)
endif
if(doGtest) open(unit=1234181, file='test/Gtest.dat') if(doGtest) then
file_path = trim(working_dir) // '/test/Gtest.dat'
open(unit=1234181, file=file_path)
endif
end subroutine end subroutine

View File

@ -57,11 +57,13 @@ parser.add_argument(
default='light', default='light',
help="Specify the type of data set: light (default), medium, or heavy." help="Specify the type of data set: light (default), medium, or heavy."
) )
thresh_default = 1e-7
parser.add_argument( parser.add_argument(
'-t', '--thresh', '-t', '--thresh',
type=float, type=float,
default=1e-7, default=thresh_default,
help='Threshold for acceptable difference (default: 1e-8)' help='Threshold for acceptable difference, default = {}'.format(thresh_default)
) )
@ -91,29 +93,32 @@ print("\n\n")
class Quack_Job: class Quack_Job:
def __init__(self, mol, multip, basis, geom, methd): def __init__(self, mol, multip, basis, geom, methd, workdir):
self.mol = mol self.mol = mol
self.multip = multip self.multip = multip
self.basis = basis self.basis = basis
self.geom = geom self.geom = geom
self.methd = methd self.methd = methd
self.workdir = workdir
def prep_inp(self): def prep_inp(self):
# geometry # geometry
generate_xyz(self.geom, filename="{}/mol/{}.xyz".format(quack_root, self.mol)) if not os.path.exists("{}/mol".format(self.workdir)):
os.makedirs("{}/mol".format(self.workdir))
generate_xyz(self.geom, filename="{}/mol/{}.xyz".format(self.workdir, self.mol))
# input files # input files
for inp in ["methods", "options"]: for inp in ["methods", "options"]:
inp_file = "{}.{}".format(inp, self.methd.upper()) inp_file = "{}.{}".format(inp, self.methd.upper())
if os.path.exists("inp/{}".format(inp_file)): if os.path.exists("inp/{}".format(inp_file)):
shutil.copy("{}/tests/inp/{}".format(quack_root, inp_file), shutil.copy("{}/tests/inp/{}".format(quack_root, inp_file),
"{}/input/{}".format(quack_root, inp)) "{}/input/{}".format(self.workdir, inp))
else: else:
print_col("File 'inp/{}' does not exist.".format(inp_file), "red") print_col("File 'inp/{}' does not exist.".format(inp_file), "red")
sys.exit(1) sys.exit(1)
def run(self, work_path): def run(self):
def display_spinner(): def display_spinner():
spinner = ['|', '/', '-', '\\'] spinner = ['|', '/', '-', '\\']
@ -137,13 +142,14 @@ class Quack_Job:
command = [ command = [
'python{}'.format(PYTHON_VERSION), 'PyDuck.py', 'python{}'.format(PYTHON_VERSION), 'PyDuck.py',
'--working_dir', '{}'.format(self.workdir),
'-x', '{}'.format(self.mol), '-x', '{}'.format(self.mol),
'-b', '{}'.format(self.basis), '-b', '{}'.format(self.basis),
'-m', '{}'.format(self.multip) '-m', '{}'.format(self.multip)
] ]
#print_col(f" $ {' '.join(command)}", "magenta") #print_col(f" $ {' '.join(command)}", "magenta")
file_out = "{}/{}/{}_{}_{}.out".format(work_path, self.methd, self.mol, self.multip, self.basis) file_out = "{}/{}/{}_{}_{}.out".format(self.workdir, self.methd, self.mol, self.multip, self.basis)
with open(file_out, 'w') as fobj: with open(file_out, 'w') as fobj:
result = subprocess.run(command, stdout=fobj, stderr=subprocess.PIPE, text=True) result = subprocess.run(command, stdout=fobj, stderr=subprocess.PIPE, text=True)
if result.stderr: if result.stderr:
@ -161,8 +167,8 @@ class Quack_Job:
done_event.set() done_event.set()
spinner_thread.join() spinner_thread.join()
def check_data(self, data_ref): def check_data(self, data_ref, test_failed_):
filepath = '../test/Rtest.dat' filepath = '{}/test/Rtest.dat'.format(self.workdir)
data_new = {} data_new = {}
try: try:
# read data_new # read data_new
@ -177,12 +183,14 @@ class Quack_Job:
for key in data_ref: for key in data_ref:
if key not in data_new: if key not in data_new:
print_col(f" 😐 {key} missing ⚠️ ", "yellow") print_col(f" 😐 {key} missing ⚠️ ", "yellow")
test_failed_ = True
else: else:
diff = abs(data_new[key] - data_ref[key]) / (1e-15 + abs(data_ref[key])) diff = abs(data_new[key] - data_ref[key]) / (1e-15 + abs(data_ref[key]))
if(diff <= THRESH): if(diff <= THRESH):
print_col(f" 🙂 {key}", "green") print_col(f" 🙂 {key}", "green")
else: else:
print_col(f" ☹️ {key}: ❌ {data_ref[key]}{data_new[key]}", "red") print_col(f" ☹️ {key}: ❌ {data_ref[key]}{data_new[key]}", "red")
test_failed_ = True
except FileNotFoundError: except FileNotFoundError:
print_col(f"Error: The file '{filepath}' does not exist.", "red") print_col(f"Error: The file '{filepath}' does not exist.", "red")
sys.exit(1) sys.exit(1)
@ -201,6 +209,11 @@ def main():
work_path.mkdir(parents=True, exist_ok=True) work_path.mkdir(parents=True, exist_ok=True)
print(f"Directory '{work_path}' created.\n") print(f"Directory '{work_path}' created.\n")
# to save QuAcK output
if not os.path.exists("{}/test".format(work_path)):
os.makedirs("{}/test".format(work_path))
test_failed = False
for mol in molecules: for mol in molecules:
mol_name = mol.name mol_name = mol.name
@ -226,16 +239,23 @@ def main():
if not work_methd.exists(): if not work_methd.exists():
work_methd.mkdir(parents=True, exist_ok=True) work_methd.mkdir(parents=True, exist_ok=True)
New_Quack_Job = Quack_Job(mol_name, mol_mult, basis_name, mol_geom, methd) New_Quack_Job = Quack_Job(mol_name, mol_mult, basis_name, mol_geom, methd, work_path)
New_Quack_Job.prep_inp() New_Quack_Job.prep_inp()
New_Quack_Job.run(work_path) New_Quack_Job.run()
New_Quack_Job.check_data(basis_data)
test_failed_ = False
New_Quack_Job.check_data(basis_data, test_failed_)
if (test_failed_):
test_failed = True
print() print()
print() print()
print() print()
quit() if test_failed:
sys.exit(1)
sys.exit(0)
db_name = '{}.db'.format(bench) db_name = '{}.db'.format(bench)

2
tests/work/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*