From 98b908387f083735884f89d79c1dbb25d2e715b0 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 7 Apr 2022 02:05:47 -0400 Subject: [PATCH] add unit test for yaml style thermo output and updated logfile class --- examples/README | 1 + examples/yaml/in.yaml | 37 +++++++ examples/yaml/log.7Apr22.yaml.g++.1 | 151 ++++++++++++++++++++++++++++ python/lammps/formats.py | 38 +++++-- unittest/python/python-formats.py | 22 ++++ 5 files changed, 243 insertions(+), 6 deletions(-) create mode 100644 examples/yaml/in.yaml create mode 100644 examples/yaml/log.7Apr22.yaml.g++.1 diff --git a/examples/README b/examples/README index 0c09b6d847..d9637af5c2 100644 --- a/examples/README +++ b/examples/README @@ -118,6 +118,7 @@ ttm: two-temeperature model examples vashishta: models using the Vashishta potential voronoi: Voronoi tesselation via compute voronoi/atom command wall: use of reflective walls with different stochastic models +yaml: demonstrates use of yaml thermo and dump styles Here is how you might run and visualize one of the sample problems: diff --git a/examples/yaml/in.yaml b/examples/yaml/in.yaml new file mode 100644 index 0000000000..28660751c8 --- /dev/null +++ b/examples/yaml/in.yaml @@ -0,0 +1,37 @@ +# 3d Lennard-Jones melt + +variable x index 1 +variable y index 1 +variable z index 1 + +variable xx equal 20*$x +variable yy equal 20*$y +variable zz equal 20*$z + +units lj +atom_style atomic + +lattice fcc 0.8442 +region box block 0 ${xx} 0 ${yy} 0 ${zz} +create_box 1 box +create_atoms 1 box +mass 1 1.0 + +velocity all create 1.44 87287 loop geom + +pair_style lj/cut 2.5 +pair_coeff 1 1 1.0 1.0 2.5 + +neighbor 0.3 bin +neigh_modify delay 0 every 20 check no + +fix 1 all nve +thermo_style yaml +thermo 10 + +dump 1 all yaml 25 dump.yaml id type x y z ix iy iz vx vy vz +dump_modify 1 sort id thermo yes units yes time yes format 1 %5d format float "% 12.8e" format int %2d + +run 100 + +run 100 diff --git a/examples/yaml/log.7Apr22.yaml.g++.1 b/examples/yaml/log.7Apr22.yaml.g++.1 new file mode 100644 index 0000000000..0c39dbe6a3 --- /dev/null +++ b/examples/yaml/log.7Apr22.yaml.g++.1 @@ -0,0 +1,151 @@ +LAMMPS (24 Mar 2022) +OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:98) + using 1 OpenMP thread(s) per MPI task +# 3d Lennard-Jones melt + +variable x index 1 +variable y index 1 +variable z index 1 + +variable xx equal 20*$x +variable xx equal 20*1 +variable yy equal 20*$y +variable yy equal 20*1 +variable zz equal 20*$z +variable zz equal 20*1 + +units lj +atom_style atomic + +lattice fcc 0.8442 +Lattice spacing in x,y,z = 1.6795962 1.6795962 1.6795962 +region box block 0 ${xx} 0 ${yy} 0 ${zz} +region box block 0 20 0 ${yy} 0 ${zz} +region box block 0 20 0 20 0 ${zz} +region box block 0 20 0 20 0 20 +create_box 1 box +Created orthogonal box = (0 0 0) to (33.591924 33.591924 33.591924) + 1 by 1 by 1 MPI processor grid +create_atoms 1 box +Created 32000 atoms + using lattice units in orthogonal box = (0 0 0) to (33.591924 33.591924 33.591924) + create_atoms CPU = 0.003 seconds +mass 1 1.0 + +velocity all create 1.44 87287 loop geom + +pair_style lj/cut 2.5 +pair_coeff 1 1 1.0 1.0 2.5 + +neighbor 0.3 bin +neigh_modify delay 0 every 20 check no + +fix 1 all nve +thermo_style yaml +thermo 10 + +dump 1 all yaml 25 dump.yaml id type x y z ix iy iz vx vy vz +dump_modify 1 sort id thermo yes units yes time yes format 1 %5d format float "% 12.8e" format int %2d + +run 100 + generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update every 20 steps, delay 0 steps, check no + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 2.8 + ghost atom cutoff = 2.8 + binsize = 1.4, bins = 24 24 24 + 1 neighbor lists, perpetual/occasional/extra = 1 0 0 + (1) pair lj/cut, perpetual + attributes: half, newton on + pair build: half/bin/atomonly/newton + stencil: half/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 20.56 | 20.56 | 20.56 Mbytes +--- +keywords: [Step, Temp, KinEng, PotEng, E_bond, E_angle, E_dihed, E_impro, E_vdwl, E_coul, E_long, Press, ] +data: + - [0, 1.44000000000001, 2.15993250000001, -6.77336805323422, 0, 0, 0, 0, -6.77336805323422, 0, 0, -5.01970725908556, ] + - [10, 1.12539487029313, 1.68803955255514, -6.30005271976029, 0, 0, 0, 0, -6.30005271976029, 0, 0, -2.55968522600129, ] + - [20, 0.625793798302192, 0.938661363368992, -5.55655653922756, 0, 0, 0, 0, -5.55655653922756, 0, 0, 0.973517658007722, ] + - [30, 0.745927295413064, 1.11885597777762, -5.73951278150759, 0, 0, 0, 0, -5.73951278150759, 0, 0, 0.339284096694852, ] + - [40, 0.731026217827733, 1.09650505988764, -5.71764564663628, 0, 0, 0, 0, -5.71764564663628, 0, 0, 0.388973418756238, ] + - [50, 0.740091517740786, 1.11010258482128, -5.73150426762886, 0, 0, 0, 0, -5.73150426762886, 0, 0, 0.335273324523691, ] + - [60, 0.750500641591031, 1.12571578266897, -5.74713299283555, 0, 0, 0, 0, -5.74713299283555, 0, 0, 0.26343139026926, ] + - [70, 0.755436366857812, 1.13311913920702, -5.75480059117447, 0, 0, 0, 0, -5.75480059117447, 0, 0, 0.224276619217515, ] + - [80, 0.759974280364828, 1.13992579675285, -5.76187162670983, 0, 0, 0, 0, -5.76187162670983, 0, 0, 0.191626237124102, ] + - [90, 0.760464250735042, 1.14066072934081, -5.76280209529731, 0, 0, 0, 0, -5.76280209529731, 0, 0, 0.189478083345243, ] + - [100, 0.757453103239936, 1.13614414924569, -5.75850548601596, 0, 0, 0, 0, -5.75850548601596, 0, 0, 0.207261053624723, ] +... +Loop time of 1.89046 on 1 procs for 100 steps with 32000 atoms + +Performance: 22851.622 tau/day, 52.897 timesteps/s +99.6% CPU use with 1 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 1.2896 | 1.2896 | 1.2896 | 0.0 | 68.22 +Neigh | 0.17687 | 0.17687 | 0.17687 | 0.0 | 9.36 +Comm | 0.014543 | 0.014543 | 0.014543 | 0.0 | 0.77 +Output | 0.37678 | 0.37678 | 0.37678 | 0.0 | 19.93 +Modify | 0.028638 | 0.028638 | 0.028638 | 0.0 | 1.51 +Other | | 0.003975 | | | 0.21 + +Nlocal: 32000 ave 32000 max 32000 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 19657 ave 19657 max 19657 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 1.20283e+06 ave 1.20283e+06 max 1.20283e+06 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 1202833 +Ave neighs/atom = 37.588531 +Neighbor list builds = 5 +Dangerous builds not checked + +run 100 + generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Per MPI rank memory allocation (min/avg/max) = 20.57 | 20.57 | 20.57 Mbytes +--- +keywords: [Step, Temp, KinEng, PotEng, E_bond, E_angle, E_dihed, E_impro, E_vdwl, E_coul, E_long, Press, ] +data: + - [100, 0.757453103239935, 1.13614414924569, -5.7585054860159, 0, 0, 0, 0, -5.7585054860159, 0, 0, 0.207261053624721, ] + - [110, 0.759322359337036, 1.13894794576996, -5.7614668389562, 0, 0, 0, 0, -5.7614668389562, 0, 0, 0.194314975399602, ] + - [120, 0.759372342462676, 1.13902291811546, -5.76149365656489, 0, 0, 0, 0, -5.76149365656489, 0, 0, 0.191600048851267, ] + - [130, 0.756833027516501, 1.13521406472659, -5.75777334823494, 0, 0, 0, 0, -5.75777334823494, 0, 0, 0.208792327853067, ] + - [140, 0.759725426691298, 1.13955252790757, -5.76208910746081, 0, 0, 0, 0, -5.76208910746081, 0, 0, 0.193895435346637, ] + - [150, 0.760545839455106, 1.14078310859643, -5.7633284876011, 0, 0, 0, 0, -5.7633284876011, 0, 0, 0.187959630462945, ] + - [160, 0.758404626168493, 1.13757138903589, -5.76023198892283, 0, 0, 0, 0, -5.76023198892283, 0, 0, 0.19692107984108, ] + - [170, 0.758880300638885, 1.13828487844424, -5.76103232235402, 0, 0, 0, 0, -5.76103232235402, 0, 0, 0.197653518549842, ] + - [180, 0.753691827878246, 1.13050241251294, -5.75304767384283, 0, 0, 0, 0, -5.75304767384283, 0, 0, 0.237041776410937, ] + - [190, 0.757361226563721, 1.13600633853809, -5.75852399133222, 0, 0, 0, 0, -5.75852399133222, 0, 0, 0.219529562657488, ] + - [200, 0.759531750132731, 1.13926202214831, -5.76188923485725, 0, 0, 0, 0, -5.76188923485725, 0, 0, 0.209105747192796, ] +... +Loop time of 1.93916 on 1 procs for 100 steps with 32000 atoms + +Performance: 22277.687 tau/day, 51.569 timesteps/s +99.4% CPU use with 1 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 1.3292 | 1.3292 | 1.3292 | 0.0 | 68.55 +Neigh | 0.18317 | 0.18317 | 0.18317 | 0.0 | 9.45 +Comm | 0.013626 | 0.013626 | 0.013626 | 0.0 | 0.70 +Output | 0.38206 | 0.38206 | 0.38206 | 0.0 | 19.70 +Modify | 0.027034 | 0.027034 | 0.027034 | 0.0 | 1.39 +Other | | 0.004028 | | | 0.21 + +Nlocal: 32000 ave 32000 max 32000 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 19570 ave 19570 max 19570 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 1.19982e+06 ave 1.19982e+06 max 1.19982e+06 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 1199821 +Ave neighs/atom = 37.494406 +Neighbor list builds = 5 +Dangerous builds not checked +Total wall time: 0:00:04 diff --git a/python/lammps/formats.py b/python/lammps/formats.py index f7a7a4eb83..83d05dd9f7 100644 --- a/python/lammps/formats.py +++ b/python/lammps/formats.py @@ -14,14 +14,19 @@ ################################################################################ # LAMMPS output formats # Written by Richard Berger +# and Axel Kohlmeyer ################################################################################ -import re +import re, yaml +try: + from yaml import CSafeLoader as Loader, CSafeDumper as Dumper +except ImportError: + from yaml import SafeLoader as Loader, SafeDumper as Dumper class LogFile: """Reads LAMMPS log files and extracts the thermo information - It supports both the default thermo output style (including custom) and multi. + It supports the line, multi, and yaml thermo output styles. :param filename: path to log file :type filename: str @@ -33,11 +38,13 @@ class LogFile: STYLE_DEFAULT = 0 STYLE_MULTI = 1 + STYLE_YAML = 2 def __init__(self, filename): alpha = re.compile(r'[a-df-zA-DF-Z]') # except e or E for floating-point numbers kvpairs = re.compile(r'([a-zA-Z_0-9]+)\s+=\s*([0-9\.eE\-]+)') style = LogFile.STYLE_DEFAULT + yamllog = "" self.runs = [] self.errors = [] with open(filename, 'rt') as f: @@ -54,6 +61,24 @@ class LogFile: current_run = {} for k in keys: current_run[k] = [] + + elif re.match(r'^(keywords:.*$|data:$|---$| - \[.*\]$)', line): + style = LogFile.STYLE_YAML + yamllog += line; + current_run = {} + + elif re.match(r'^\.\.\.$', line): + thermo = yaml.load(yamllog, Loader=Loader) + for k in thermo['keywords']: + current_run[k] = [] + for step in thermo['data']: + icol = 0 + for k in thermo['keywords']: + current_run[k].append(step[icol]) + icol += 1 + self.runs.append(current_run) + yamllog = "" + elif re.match(r'^------* Step ', line): if not in_thermo: current_run = {'Step': [], 'CPU': []} @@ -65,28 +90,29 @@ class LogFile: cpu = float(str_cpu.split('=')[1].split()[0]) current_run["Step"].append(step) current_run["CPU"].append(cpu) + elif line.startswith('Loop time of'): in_thermo = False - self.runs.append(current_run) + if style != LogFile.STYLE_YAML: + self.runs.append(current_run) + elif in_thermo and in_data_section: if style == LogFile.STYLE_DEFAULT: if alpha.search(line): continue - for k, v in zip(keys, map(float, line.split())): current_run[k].append(v) + elif style == LogFile.STYLE_MULTI: if '=' not in line: in_data_section = False continue - for k,v in kvpairs.findall(line): if k not in current_run: current_run[k] = [float(v)] else: current_run[k].append(float(v)) - class AvgChunkFile: """Reads files generated by fix ave/chunk diff --git a/unittest/python/python-formats.py b/unittest/python/python-formats.py index ca877b8305..9e7863e198 100644 --- a/unittest/python/python-formats.py +++ b/unittest/python/python-formats.py @@ -7,6 +7,7 @@ EXAMPLES_DIR=os.path.abspath(os.path.join(__file__, '..', '..', '..', 'examples' DEFAULT_STYLE_EXAMPLE_LOG="melt/log.8Apr21.melt.g++.1" MULTI_STYLE_EXAMPLE_LOG="peptide/log.27Nov18.peptide.g++.1" AVG_CHUNK_FILE="VISCOSITY/profile.13Oct16.nemd.2d.g++.1" +YAML_STYLE_EXAMPLE_LOG="yaml/log.7Apr22.yaml.g++.1" class Logfiles(unittest.TestCase): def testLogFileNotFound(self): @@ -58,6 +59,27 @@ class Logfiles(unittest.TestCase): self.assertEqual(run0["Step"], list(range(0,350, 50))) + def testYamlLogFile(self): + log = LogFile(os.path.join(EXAMPLES_DIR, YAML_STYLE_EXAMPLE_LOG)) + self.assertEqual(len(log.runs), 2) + run = log.runs[0] + self.assertEqual(len(run.keys()), 12) + self.assertIn("Step", run) + self.assertIn("Temp", run) + self.assertIn("E_vdwl", run) + self.assertIn("E_coul", run) + self.assertIn("E_bond", run) + self.assertIn("E_angle", run) + self.assertIn("Press", run) + self.assertEqual(len(run["Step"]), 11) + self.assertEqual(len(run["Temp"]), 11) + self.assertEqual(len(run["E_vdwl"]), 11) + self.assertEqual(len(run["E_coul"]), 11) + self.assertEqual(len(run["E_bond"]), 11) + self.assertEqual(len(run["E_angle"]), 11) + self.assertEqual(len(run["Press"]), 11) + self.assertEqual(log.runs[0]["Step"], [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]) + class AvgChunkFiles(unittest.TestCase): def testAvgChunkFileNotFound(self):