Skip to content

Commit

Permalink
Temperature settings (#98)
Browse files Browse the repository at this point in the history
* temperature stuff and some input checks
  • Loading branch information
lukasbaldauf committed Jun 19, 2024
1 parent 153cdd1 commit b236b30
Show file tree
Hide file tree
Showing 12 changed files with 110 additions and 49 deletions.
4 changes: 2 additions & 2 deletions examples/cp2k/H2/infretis.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ wmdrun = ['0',

[simulation]
interfaces = [ 3.45, 3.625, 3.777, 3.922, 4.068, 4.224, 4.399, 4.612, 4.915, 12.0]
steps = 1000
steps = 100
seed = 0
load_dir = 'load'
shooting_moves = ['sh','sh', 'wf', 'wf', 'wf', 'wf', 'wf', 'wf', 'wf', 'wf', 'wf']
Expand All @@ -21,7 +21,6 @@ allowmaxlength = false
zero_momentum = true # we do not remove momentum by default in lammps
n_jumps = 3
interface_cap = 5.4
temperature = 300

[engine]
class = 'cp2k'
Expand All @@ -30,6 +29,7 @@ input_path = 'cp2k_input'
cp2k = 'cp2k.ssmp'
timestep = 0.2
subcycles = 10
temperature = 300

[orderparameter]
class = 'Distance'
Expand Down
4 changes: 1 addition & 3 deletions examples/gromacs/H2/gromacs_input/grompp.mdp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
integrator = sd
integrator = sd ; LGTM
nsteps = 10000
dt = 0.0002

Expand All @@ -22,13 +22,11 @@ coulombtype = cutoff
rcoulomb = 1.20

tcoupl = no
ref-t = 300
tau-t = 0.1
tc-grps = System

pbc = xyz

gen_temp = 300
gen_seed = -1
gen_vel = no
nstcalcenergy = 1
9 changes: 4 additions & 5 deletions examples/gromacs/H2/infretis.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# infretis config

[dask]
workers = 4
workers = 1
wmdrun = ['gmx mdrun -ntomp 1 -ntmpi 1 -pinoffset 0 -pin on',
'gmx mdrun -ntomp 1 -ntmpi 1 -pinoffset 1 -pin on',
'gmx mdrun -ntomp 1 -ntmpi 1 -pinoffset 2 -pin on',
Expand All @@ -21,10 +21,6 @@ allowmaxlength = false
zero_momentum = true # momentum true
n_jumps = 3
interface_cap = 0.54
temperature = 300
infretis_genvel = true # generate velocities with infretis
mass = [1.008, 1.008] # then we also need to give masses


[engine]
class = 'gromacs'
Expand All @@ -34,6 +30,9 @@ gmx_format = 'g96'
input_path = 'gromacs_input'
gmx = 'gmx' # gromacs executable, may also be gmx_mpi, gmx_2023.3, etc.
subcycles = 10
temperature = 300
infretis_genvel = true # generate velocities with infretis
masses = [1.008, 1.008] # or "masses.txt" stored in input_path/masses.txt in any csv format

[orderparameter]
class = 'Distance'
Expand Down
2 changes: 1 addition & 1 deletion examples/gromacs/puckering/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ Fire off `mdrun`. This should take a couple of minutes.
As you may have guessed by now, a good order parameter for the transition we want to study is the $\theta$ angle. To calculate the angle during the MD run, open `infretis.toml` and replace the indices with the ones you wrote down earlier. You can then recalculate the order parameter using:

```bash
inft recalculate_order -trr md.trr -toml infretis.toml -out md-order.txt
inft recalculate_order -traj md.trr -toml infretis.toml -out md-order.txt

```
Plot the $\theta$ values (column 1) vs time (column 0) from the MD run using e.g. gnuplot.
Expand Down
1 change: 0 additions & 1 deletion examples/gromacs/puckering/gromacs_input/grompp.mdp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ vdwtype = cut-off ; Straight cut off for vdw interactions
tcoupl = V-rescale ; Canonical sampling thorugh stochastic velocity rescaling
tc-grps = System ; two coupling groups - more accurate
tau_t = 0.1 ; time constant, in ps
ref_t = 300 ; reference temperature

; Pressure coupling
pcoupl = no ; pressure coupling is on for NPT
Expand Down
3 changes: 1 addition & 2 deletions examples/gromacs/puckering/step3_infretis/infretis.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ shooting_moves = ['sh', 'sh', 'wf', 'wf', 'wf', 'wf', 'wf', 'wf', 'wf', 'wf', 'w
maxlength = 2000 # maximum path length (NB! this should never be reached )
allowmaxlength = false # do not allow paths to exceed maxlength when shooting from load paths
zero_momentum = true # remove the center of mass motion when generating vels, done by gromacs by default
temperature = 300 # velocities are generated at this temperature
high_accept = true # we do want high-acceptance
n_jumps = 2 # number of wirefencing jumps
interface_cap = 70.0 # wirefencing interface cap

Expand All @@ -37,6 +35,7 @@ gmx_format = 'g96' # only g96 is supported for gromacs
input_path = '../gromacs_input' # path to topolofy files
gmx = 'gmx' # gromacs executable, may also be gmx_mpi, gmx_2023.3, etc.
subcycles = 3 # number of MD steps for each infretis step
temperature = 300 # temperature of the simulation and velocity generations

[orderparameter]
class = 'puckering'
Expand Down
4 changes: 2 additions & 2 deletions examples/lammps/H2/infretis.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# infretis config

[dask]
workers = 4
workers = 1
wmdrun = ['0',
'0',
'0',
Expand All @@ -21,7 +21,6 @@ allowmaxlength = false
zero_momentum = true # we do not remove momentum by default in lammps
n_jumps = 3
interface_cap = 5.4
temperature = 300

[engine]
class = 'lammps'
Expand All @@ -30,6 +29,7 @@ input_path = 'lammps_input'
lmp = 'lmp_mpi'
timestep = 0.2
subcycles = 10
temperature = 300

[orderparameter]
class = 'Distance'
Expand Down
23 changes: 17 additions & 6 deletions infretis/classes/engines/cp2k.py
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,7 @@ def __init__(
input_path: str,
timestep: float,
subcycles: int,
temperature: float,
extra_files: list[str] | None = None,
exe_path: str | Path = Path(".").resolve(),
sleep: float = 0.1,
Expand All @@ -700,6 +701,7 @@ def __init__(
input_path: The path to the directory containing CP2K input files.
timestep: The time step used in the CP2K simulation.
subcycles: The number of steps each CP2K run is composed of.
temperature: The temperature of the simulation.
extra_files: List of extra files which may be required to run CP2K.
exe_path: The path on which the engine is executed
sleep: A time in seconds, used to wait for files to be ready.
Expand Down Expand Up @@ -731,18 +733,27 @@ def __init__(
]
self.mass = np.reshape(mass, (len(mass), 1))

# read temperature from CP2K input, defaults to 300
self.temperature = None
# Check that the temperature set in cp2k.inp and infretis.toml
# are the same. Often one modifies one and forgets about the other
# If no temperature is set in cp2k.inp its NVE with NVT shooting
# and we proceed without any remarks (?)
section = "MOTION->MD"
nodes = read_cp2k_input(self.input_files["template"])
node_ref = set_parents(nodes)
md_settings = node_ref[section]
for data in md_settings.data:
if "temperature" in data.lower():
self.temperature = float(data.split()[-1])
if self.temperature is None:
logger.info("No temperature specified in CP2K input. Using 300 K.")
self.temperature = 300.0
cp2k_temp = float(data.split()[1])
if cp2k_temp != temperature:
msg = (
f"The temperature in the cp2k input {cp2k_temp} !="
+ f" {temperature} which is specified in the .toml. "
+ "They should be the same since we generate "
+ "velocities internally at the .toml temperature."
)
raise ValueError(msg)

self.temperature = temperature
self.kb = 3.16681534e-6 # hartree
self.beta = 1 / (self.temperature * self.kb)

Expand Down
2 changes: 1 addition & 1 deletion infretis/classes/engines/enginebase.py
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ def _modify_input(

@staticmethod
def _read_input_settings(
sourcefile: str, delim: str = "="
sourcefile: str | Path, delim: str = "="
) -> dict[str, Any]:
"""Read input settings for simulation input files.
Expand Down
78 changes: 63 additions & 15 deletions infretis/classes/engines/gromacs.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,14 @@ def __init__(
input_path: str | Path,
timestep: float,
subcycles: int,
temperature: float,
exe_path: str | Path = Path(".").resolve(),
maxwarn: int = 0,
gmx_format: str = "g96",
write_vel: bool = True,
write_force: bool = False,
infretis_genvel: bool = False,
masses: bool | list | str = False,
):
"""Set up the GROMACS engine.
Expand All @@ -107,10 +110,17 @@ def __init__(
subcycles: The number of steps each GROMACS MD run is composed of.
exe_path: The absolute path at which the main simulation will be
run.
temperature: The temperature during the MD run, used when
generating velocities and thermostatting by gromacs.
maxwarn: Setting for the GROMACS `grompp -maxwarn` option.
gmx_format: The format used for GROMACS configurations.
write_vel: Determines if GROMACS should write velocities or not.
write_force: Determines if GROMACS should write forces or not.
infretis_genvel: If true we generate the velocities
internally by drawing random numbers from a maxwell-boltzmann
distribution. Mostly used for testing purposes.
masses: A list of particle masses or a txt file with particle
masses
"""
super().__init__("GROMACS engine zamn", timestep, subcycles)
self.ext = gmx_format
Expand All @@ -127,7 +137,7 @@ def __init__(
# Define the energy terms, these are hard-coded, but
# here we open up for changing that:
self.energy_terms = self.select_energy_terms("path")
self.input_path = Path(exe_path) / input_path
self.input_path = (Path(exe_path) / input_path).resolve()
# Set the defaults input files:
default_files = {
"conf": f"conf.{self.ext}",
Expand All @@ -149,10 +159,55 @@ def __init__(
)
# Check the input file and create new input file with
# consistent settings:
check_set = self._read_input_settings(self.input_files["input_o"])
for key in check_set.keys():
val = check_set[key]
if (
key == "integrator"
and "md-vv" not in val
and "LGTM" not in val
):
msg = (
"Gromacs integrator should be md-vv with "
+ "path-sampling. Add a coment LGTM to the relevant"
+ " line to overwrite this error."
)
raise ValueError(msg)

if key in ["ref-t", "ref_t", "gen-temp", "gen_temp"]:
msg = (
f"Found key '{key}' in {self.input_files['input_o']}. "
+ "This key is set by infretis and should be removed "
+ "from this file."
)
raise ValueError(msg)

self.temperature = temperature
self.kb = 0.0083144621 # kJ/(K*mol)
self.beta = 1 / (self.temperature * self.kb)

# get masses if generating velocites internally
self.infretis_genvel = infretis_genvel
if infretis_genvel:
if not masses:
msg = (
"If you want to generate velocites internally you also "
+ "need to specify the particle masses either as a list "
+ f"or string pointing to a csv file in {self.input_path}"
)
raise ValueError(msg)
if isinstance(masses, str):
self.masses = np.reshape(
np.genfromtxt(self.input_path / masses), (-1, 1)
)
elif isinstance(masses, list):
self.masses = np.reshape(masses, (-1, 1))

settings: dict[str, str | float | int] = {
"dt": self.timestep,
"nstxout-compressed": 0,
"gen_vel": "no",
"ref-t": self.temperature,
}
for key in (
"nsteps",
Expand All @@ -169,9 +224,6 @@ def __init__(
if not write_force:
settings["nstfout"] = 0

# Add boltzmann constant
self.kb = 0.0083144621 # kJ/(K*mol)

# Create the .mdp file name:
self.input_files["input"] = os.path.join(
self.input_path, "infretis.mdp"
Expand Down Expand Up @@ -639,6 +691,7 @@ def _prepare_shooting_point(
"gen_seed": -1,
"nsteps": 0,
"continuation": "no",
"gen-temp": self.temperature,
}
self._modify_input(
self.input_files["input"], gen_mdp, settings, delim="="
Expand Down Expand Up @@ -712,11 +765,6 @@ def modify_velocities(
vel_settings: A dict containing
'zero_momentum': boolean, if true we reset the linear momentum
to zero after generating velocities internally.
'infretis_genvel': boolen, if true we generate the velocities
internally by drawing random numbers from a maxwell-boltzmann
distribution. Mostly used for testing purposes.
'mass': list, the particle masses when generating velocities
internally.
Returns:
Expand All @@ -728,7 +776,7 @@ def modify_velocities(
kin_old = system.ekin
pos = self.dump_frame(system)
# generate velocities with gromacs
if not vel_settings.get("infretis_genvel", False):
if not self.infretis_genvel:
if vel_settings.get("zero_momentum", True) is False:
msg = (
"Velocitiy generation with gromacs "
Expand All @@ -744,18 +792,18 @@ def modify_velocities(

# generate velocities by drawing random numbers
else:
mass = np.reshape(vel_settings["mass"], (-1, 1))
beta = 1 / (vel_settings["temperature"] * self.kb)
txt, xyz, vel, _ = read_gromos96_file(pos)
if not txt["VELOCITY"]:
print(f"{pos} did not contain velocity information.")
txt["VELOCITY"] = txt["POSITION"]
vel, _ = self.draw_maxwellian_velocities(vel, mass, beta)
vel, _ = self.draw_maxwellian_velocities(
vel, self.masses, self.beta
)
if vel_settings.get("zero_momentum", False):
vel = reset_momentum(vel, mass)
vel = reset_momentum(vel, self.masses)
conf_out = os.path.join(self.exe_dir, f"genvel.{self.ext}")
write_gromos96_file(conf_out, txt, xyz, vel)
kin_new = kinetic_energy(vel, mass)[0]
kin_new = kinetic_energy(vel, self.masses)[0]
system.config = (conf_out, 0)
system.ekin = kin_new

Expand Down
Loading

1 comment on commit b236b30

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Coverage Report
FileStmtsMissCoverMissing
infretis
   __init__.py00100% 
   bin.py14286%19, 25
   scheduler.py160100% 
   setup.py96595%56, 77–78, 101, 111
infretis/classes
   __init__.py00100% 
   formatter.py4027382%51, 54–55, 62, 104–105, 120, 189, 201, 210–213, 257, 305, 339, 368–372, 388–390, 394, 437–438, 443, 449, 456–459, 467, 472–477, 491–495, 500, 519, 526–527, 539–546, 564–566, 583, 587–591, 595–600, 608, 671, 721, 737, 784, 791, 956–960, 964, 970, 986, 1022
   orderparameter.py1874675%432–452, 456–500
   path.py2719864%78–79, 107, 115–116, 134, 141–142, 159–160, 177–188, 208, 222–225, 243, 260–273, 283–324, 328, 332, 348, 352, 358, 366–370, 373–375, 420–429, 435–438, 446–448, 507–531
   repex.py6279984%118, 209–233, 318–328, 409, 477, 519–520, 526–534, 553, 590–605, 632–679, 686, 723, 807–808, 830, 840, 847–848, 852–853, 857, 949, 1020–1023, 1076–1077
   system.py220100% 
infretis/classes/engines
   __init__.py00100% 
   cp2k.py47327442%95, 126–140, 154–158, 224–238, 263–296, 311–335, 352–372, 407, 415–419, 421–427, 431, 447–460, 482–496, 520–525, 551–552, 636–670, 748–754, 764–771, 794, 834–1025, 1029–1036, 1041–1047, 1073, 1084–1085, 1122
   enginebase.py2775381%67, 96–101, 176, 222–223, 504, 529–547, 556–557, 562–563, 571–572, 586–624, 628, 633–634, 646–647, 657–658, 694
   engineparts.py2129953%117–119, 140–154, 173–177, 225, 239–241, 300, 383–384, 414–417, 424, 452–456, 462–468, 474–502, 531–583
   factory.py39685%39, 47, 64, 69, 74, 81
   gromacs.py68246632%129–132, 170–175, 178–183, 193–198, 200, 223, 287, 320, 322, 340–347, 365–375, 395–405, 417–431, 446–461, 471, 491–499, 503–506, 527–537, 570–664, 684–710, 714–717, 736–738, 750–756, 780–791, 797–798, 862–876, 880–917, 921–922, 926–1003, 1007–1012, 1016–1033, 1037, 1041, 1045–1055, 1072–1086, 1100–1135, 1145–1155, 1215–1218, 1225–1226, 1234–1235, 1259, 1268–1271, 1291–1294, 1311–1322, 1336–1337, 1360–1371, 1381–1397, 1417–1426, 1449–1456, 1470–1487, 1504–1506, 1525–1549, 1573–1579, 1584, 1594–1598
   lammps.py24313445%122–157, 188–204, 244, 360–521, 538–540, 578, 598
   turtlemdengine.py137497%162, 205, 305, 351
infretis/core
   __init__.py00100% 
   core.py132894%240–245, 250–252
   tis.py3486083%60–63, 340–341, 349, 410–419, 430–431, 437, 481–483, 515–516, 530, 578, 581–582, 630, 644–645, 687, 693–695, 770–772, 871–872, 887, 889, 894, 927–929, 941, 943, 958, 971, 1000–1003, 1034–1054
infretis/tools
   __init__.py00100% 
   generate_H2_loadpaths.py78780%9–137
   get-interfaces.py63630%1–119
   minutes_since_start.py26260%1–49
   pattern.py63630%1–140
TOTAL4408165762% 

Coverage summary (Python 3.12.4)

Tests Skipped Failures Errors Time
50 0 💤 0 ❌ 0 🔥 40.235s ⏱️

Please sign in to comment.