From 1144c1b3f9570b30e7313ef2326856836c0edf9f Mon Sep 17 00:00:00 2001
From: rjones <rjones@f3b2605a-c512-4ea7-a41b-209d697bcdaa>
Date: Wed, 21 Aug 2013 23:40:18 +0000
Subject: [PATCH] first drafts of benchmark,py - numerical comparison of log
 files regression.sh - script for cron

git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@10640 f3b2605a-c512-4ea7-a41b-209d697bcdaa
---
 regress/benchmark.py  | 235 ++++++++++++++++++++++++++++++++++++++++++
 regress/regression.sh |  11 ++
 2 files changed, 246 insertions(+)
 create mode 100755 regress/benchmark.py
 create mode 100755 regress/regression.sh

diff --git a/regress/benchmark.py b/regress/benchmark.py
new file mode 100755
index 0000000000..209c91f8d9
--- /dev/null
+++ b/regress/benchmark.py
@@ -0,0 +1,235 @@
+#!/usr/bin/env python 
+"""
+  function: numerical comparisions of logs and corresponding benchmarks
+  usage: benchmark.py <nprocs> <njobs> <dirs>
+"""
+import sys
+import os
+import math
+import re
+from operator import itemgetter
+from glob import glob
+import time
+import multiprocessing as mp
+try:
+  import Queue as queue # 2.6
+except ImportError:
+  import queue # 3.0
+
+#====================================================
+### constants
+#====================================================
+thermo_pattern  = re.compile("^Step "); # fragile
+data_pattern    = re.compile("\s*\d"); # fragile
+fail_pattern    = re.compile("FAIL"); 
+tol = 1.e-6 # 1.e-10
+arch = "openmpi"
+src_path = "../src/" #relative to home
+exe_path = "../"+src_path
+
+#====================================================
+### date
+#====================================================
+def date():
+ return time.asctime()
+
+#====================================================
+### timer
+#====================================================
+## NOTE these don't seem to work how I expect them to
+def start():
+  global dt
+  dt = -(time.clock())
+def stop():
+  global dt
+  dt += (time.clock())
+  return dt
+
+#====================================================
+### run a benchmark
+#====================================================
+def run_test(test):
+  input = "in."+test;
+  log = "log."+test
+  stdout = "stdout."+test
+  ref = (glob(log+"*."+str(np)))[0];
+  msg = "==== comparing "+log+" with "+ref+" ====\n"
+  if (os.path.isfile(log)): os.remove(log)
+  if (os.path.isfile(stdout)): os.remove(stdout)
+  os.system(lmps+input+" >& "+stdout);
+  if (not os.path.isfile(log)) :
+    msg += "!!! no "+log+"\n";
+    msg += "!!! test "+test+" FAILED\n"
+    return msg
+  [cdict,cdata] = extract_data(log);
+  [bdict,bdata] = extract_data(ref);
+  cols = range(len(bdict)) 
+  if (len(cdata) != len(bdata)):
+    msg += "!!! data size "+str(len(cdata))+" does not match data "+str(len(bdata))+" in "+ref+"\n";
+    msg += "!!! test "+test+" FAILED\n"
+    return msg
+  fail = False 
+  i = 0
+  for name in bdict:
+    [passing,cmsg] = compare(name,cdata[cols[i]],bdata[cols[i]]);
+    i += 1
+    msg += cmsg
+    if (not passing) : fail = True
+  if (fail) :
+    msg += "!!! test "+test+" FAILED\n"
+  else : 
+    msg += "*** test "+test+" passed\n"
+  return msg
+
+#====================================================
+### extract data from log file
+#====================================================
+def extract_data(file):
+  dictionary = [];
+  data = []
+  read = False
+  for line in open(file):
+    if (read and data_pattern.match(line)) :
+      cols = line.split();
+      data.append(cols)
+    else :
+      read = False
+    if (thermo_pattern.match(line)):
+      dictionary = line.split();
+      read = True
+  return [dictionary,data]
+
+#====================================================
+### compare columns of current and benchmark
+#====================================================
+def compare(name,col1,col2):
+  err = 0.
+  norm1 = 0.
+  norm2 = 0.
+  n = len(col2)
+  for i in range(n):
+    v1 = float(col1[i])
+    v2 = float(col2[i])
+    norm1 += v1*v1
+    norm2 += v2*v2
+    dv = v1-v2
+    err   += dv*dv
+  norm1 /= n
+  norm2 /= n
+  err   /= n
+  if (norm2 > tol) :  
+    msg = "{0:7s}  relative error {1:4} wrt norm {2:7}\n".format(name,err,norm2)
+  else :
+    msg = "{0:7s}           error {1:4}\n"               .format(name,err)
+  return [(err < tol),msg];
+
+#################################################################
+class Worker(mp.Process):
+  def __init__(self, work_queue, result_queue):
+    mp.Process.__init__(self)
+    self.work_queue = work_queue
+    self.result_queue = result_queue
+  def run(self):
+    while True:
+      try:
+        job = self.work_queue.get_nowait()
+      except queue.Empty:
+        break
+      #print(">>> starting " + str(job[1]) + " ...")
+      os.chdir(job[0])
+      start()
+      msg = run_test(job[1])
+      elapsed_time = stop()
+      msg += "elapsed time "+str(elapsed_time)+"\n"
+      os.chdir(home)
+      self.result_queue.put([job[1],msg])
+
+#====================================================
+### parse
+#====================================================
+def init() :
+  global np, njobs, ntests, lmps, arch, home
+  home = os.getcwd()
+  if (len(sys.argv) < 4) :
+    print "usage: benchmark.py <nprocs> <njobs> <test_dirs>"
+    sys.exit(1)
+  np = int(sys.argv[1])
+  njobs = int(sys.argv[2])
+  lmps = "../"+src_path+"lmp_"+arch+" -in "
+  if (np > 1): 
+    lmps = "mpirun -np "+str(np)+" "+lmps
+  else:
+    arch = "serial"
+    lmps = exe_path+"lmp_"+arch+" -in "
+  pool = mp.Pool(njobs)
+  dirs = sys.argv[3:]
+  tests = []
+  for dir in dirs:
+    os.chdir(dir);
+    for path in glob("./in.*"):
+      test = path[5:];
+      tests.append([dir,test])
+    os.chdir(home)
+  ntests = len(tests)
+  print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+  print "start: ",date()
+  print "arch:",arch,
+  print "nprocs:",np
+  print "ntests:",ntests,
+  print "njobs:",njobs
+  print "relative tolerance:",tol
+  print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+  print
+  return tests
+
+#====================================================
+### build executable
+#====================================================
+def build(arch):
+  os.system("cd ..; svn update >& svn_update.log")
+  os.system("cd ../src; make no-atc >& /dev/null")
+  os.system("cd ../src; make clean-all >& /dev/null")
+  #os.system("cd ../src; make yes-all >& /dev/null")
+  os.system("cd ../src; make yes-dipole >& /dev/null")
+  sys.stdout.flush()
+  print "** building ",arch,"...",
+  os.system("cd "+src_path+"; make -j "+str(np)+" "+arch+" >& build_"+arch+".log")
+  if (not os.path.isfile(src_path+"lmp_"+arch)) :
+    print "!!! build ",arch," FAILED"
+    sys.exit()
+  else:
+    print "done"
+  print
+
+#====================================================
+### main
+#====================================================
+if __name__ == '__main__':
+  tests = init()
+  build(arch)
+  work_queue = mp.Queue()
+  for test in tests:
+    work_queue.put(test)
+  result_queue = mp.Queue()
+  nfails = 0
+  fail_list = []
+  for i in range(njobs):
+    w = Worker(work_queue, result_queue)
+    w.start()
+  for i in range(ntests):
+    [test,msg] = result_queue.get()
+    if (fail_pattern.search(msg)) : 
+      nfails += 1
+      fail_list.append(test)
+      #print msg # can print only if failed
+    print msg # can print only if failed
+    #print test, " passed"
+  print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+  print "end:",date()
+  if (nfails == 0):
+    print "*** no failures ***"
+  else :
+    print "!!!",nfails,"of",ntests,"tests failed"
+    for test in fail_list:
+      print test
+  print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
diff --git a/regress/regression.sh b/regress/regression.sh
new file mode 100755
index 0000000000..8aac9612fb
--- /dev/null
+++ b/regress/regression.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+cd /code/lammps-atc/regression
+./benchmark.py 4 12 min dipole >& latest
+fail=`grep -c FAIL latest`
+addrs="rjones@sandia.gov jatempl@sandia.gov jzimmer@sandia.gov sjplimp@sandia.gov akohlmey@gmail.com" 
+if [ $fail == 0 ] ; then
+  mhmail  $addrs -subject "LAMMPS regression passes" <  latest
+else
+  mhmail  $addrs -subject "LAMMPS regression $fail tests failed" < latest
+fi
+
-- 
GitLab