Writing Formatted Output¶
Overview¶
Questions¶
How do I display status information during a simulation?
How can I log user-defined quantities?
How can I write formatted output to a text file?
Objectives¶
Demonstrate user-defined log quantities.
Explain the use of Table to display status information during a simulation run.
Show that Table can write to a file.
Boilerplate code¶
[1]:
import datetime
import hoomd
Define the Simulation¶
This tutorial executes the Lennard-Jones particle simulation from a previous tutorial. See Introducing Molecular Dyamics for a complete description of this code.
[3]:
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(device=cpu)
sim.create_state_from_gsd(
filename='../01-Introducing-Molecular-Dynamics/random.gsd')
integrator = hoomd.md.Integrator(dt=0.005)
cell = hoomd.md.nlist.Cell(buffer=0.4)
lj = hoomd.md.pair.LJ(nlist=cell)
lj.params[('A', 'A')] = dict(epsilon=1, sigma=1)
lj.r_cut[('A', 'A')] = 2.5
integrator.forces.append(lj)
nvt = hoomd.md.methods.NVT(kT=1.5, filter=hoomd.filter.All(), tau=1.0)
integrator.methods.append(nvt)
sim.operations.integrator = integrator
Formatted output¶
The Table writer formats log quantities in human-readable text and writes them to stdout
or a file. Table only supports scalar
and string
quantities due to the limitations of this format. This section shows you how to use Table to display status information during a simulation run.
Add quantities to a Logger¶
The categories
argument to Logger defines the categories that it will accept.
[4]:
logger = hoomd.logging.Logger(categories=['scalar', 'string'])
Log the and simulation timestep
and tps
quantities:
[5]:
logger.add(sim, quantities=['timestep', 'tps'])
You can also log user-defined quantities using functions, callable class instances, or class properties. For example, this class computes the estimated time remaining:
[6]:
class Status():
def __init__(self, sim):
self.sim = sim
@property
def seconds_remaining(self):
try:
return (self.sim.final_timestep - self.sim.timestep) / self.sim.tps
except ZeroDivisionError:
return 0
@property
def etr(self):
return str(datetime.timedelta(seconds=self.seconds_remaining))
Assign the loggable quantity using the tuple (object, property_name, flag)
, where flag
is the string name of the flag for this quantity. (The tuple for callable objects would be (callable, flag)
).
[7]:
status = Status(sim)
logger[('Status', 'etr')] = (status, 'etr', 'string')
Represent the namespace of your user-defined quantity with a tuple of strings - ('Status', 'etr'
) above. You can use any number of arbitrary strings in the tuple to name your quantity.
Display quantities with Table¶
Table is a Writer that formats the quantities in a Logger into a human readable table. Create one that triggers periodically:
[8]:
table = hoomd.write.Table(trigger=hoomd.trigger.Periodic(period=5000),
logger=logger)
Add it to the simulation:
[9]:
sim.operations.writers.append(table)
Run the simulation and see the output:
[10]:
sim.run(100000)
Simulation.timestep Simulation.tps Status.etr
15000 7079.19236 0:00:13.419610
20000 7711.58264 0:00:11.670756
25000 7873.23870 0:00:10.796065
30000 7998.88650 0:00:10.001392
35000 8067.65223 0:00:09.296385
40000 8130.34130 0:00:08.609725
45000 8161.39123 0:00:07.964328
50000 8198.28541 0:00:07.318603
55000 8220.85883 0:00:06.690299
60000 8243.20310 0:00:06.065603
65000 8260.47214 0:00:05.447631
70000 8281.81727 0:00:04.829858
75000 8297.38171 0:00:04.218198
80000 8302.28728 0:00:03.613462
85000 8311.39834 0:00:03.007917
90000 8320.74372 0:00:02.403631
95000 8318.73378 0:00:01.803159
100000 8328.36479 0:00:01.200716
105000 8335.28337 0:00:00.599860
110000 8341.92073 0:00:00
Later in this notebook, you are going to create another Table Writer. Remove table
now to avoid confusing the two:
[11]:
sim.operations.writers.remove(table)
Save Table output to a file¶
Table writes to stdout
by default. It can write to a file (or any Python file-like object with write
and flush
methods) instead.
Open the file to write:
[12]:
file = open('log.txt', mode='x', newline='\n')
Create a Table Writer that outputs to this file and add it to the Simulation:
[13]:
table_file = hoomd.write.Table(output=file,
trigger=hoomd.trigger.Periodic(period=5000),
logger=logger)
sim.operations.writers.append(table_file)
Run the simulation:
[14]:
sim.run(100000)
You can read the file with standard tools:
[15]:
!tail log.txt
165000 8394.76121 0:00:05.360486
170000 8398.18003 0:00:04.762937
175000 8395.87278 0:00:04.168715
180000 8406.33943 0:00:03.568735
185000 8416.43930 0:00:02.970377
190000 8415.16128 0:00:02.376663
195000 8412.77978 0:00:01.783002
200000 8404.64913 0:00:01.189818
205000 8407.71957 0:00:00.594692
210000 8413.83845 0:00:00
In this section, you have displayed loggable quantities during a simulation run and saved them to a text file. This is the last section in the logging tutorial.