cgDNA 'real' units and potential file reading for non-modifiable potential parameters (#15)
* oxDNA potential file reading and real units This allows for pair and bond coefficients to be read from an appropriately formatted potential file, and also allows for the use of 'real' units within oxDNA1. The correct backend coefficients for pair and bonded interactions are set when the atom vector is initialised through the "ConstantsOxdna" class, based on the units specified within the input file. * Extract seqav/seqdep and temp from potential files Also includes miscellaneous string consistency changes and removes unnecessary parameter from reader.next_line instances. * oxDNA2 potential file reading and real units This extends previous changes to oxDNA2 specific potentials, being FENE, excluded volume, coaxial stacking and Debye-Hückel. Units now default to LJ values rather than 0. * oxDNA potential files * LJ <-> real units conversion tool Converts standard oxDNA data and input file to real units, with inverse flag available for real -> LJ. * oxRNA2 potential file reading and real units For RNA, d_cs_x is treated as d_cs within ConstantsOxdna in order to reduce code duplication and complexity. * Reparameterise real units * Generalise PotentialFileReader logs * Extract stk xi and kappa from potential files This allows users to edit these values from the input script, as is documented, rather than them being within the potential files. * Real unit and potential file documentation This adds examples for real unit parameters and specific potential file documentation for each bond and pair style.
This commit is contained in:
604
examples/PACKAGES/cgdna/util/lj2real.py
Normal file
604
examples/PACKAGES/cgdna/util/lj2real.py
Normal file
@ -0,0 +1,604 @@
|
||||
"""
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
https://www.lammps.org/ Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing authors: Kierran Falloon (University of Strathclyde, Glasgow)
|
||||
Oliver Henrich (University of Strathclyde, Glasgow)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
Program:
|
||||
|
||||
Usage:
|
||||
$$ python lj2real.py <datafile> <inputfile> [-i]
|
||||
$$ [-i] flag is optional and is used to convert real -> LJ units.
|
||||
|
||||
Requirements:
|
||||
LAMMPS data file and input file.
|
||||
|
||||
This script assumes a input and data file structure similar to those found in examples/PACKAGES/cgdna/examples/.
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
class Sections:
|
||||
"""Sections of the data file"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
bounds: bool,
|
||||
masses: bool,
|
||||
atoms: bool,
|
||||
velocities: bool,
|
||||
ellipsoids: bool,
|
||||
):
|
||||
self.bounds = bounds # xlo, xhi, ylo, yhi, zlo, zhi
|
||||
self.masses = masses # Masses
|
||||
self.atoms = atoms # Atoms
|
||||
self.velocities = velocities # Velocities
|
||||
self.ellipsoids = ellipsoids # Ellipsoids
|
||||
|
||||
|
||||
# Conversion factors
|
||||
class ConversionFactors:
|
||||
"""Conversion factors for LJ to real units"""
|
||||
|
||||
def __init__(self, invert: bool = False):
|
||||
self.inverted = False
|
||||
self.temp_conv_factor = 3000.038822
|
||||
self.energy_conv_factor = 5.961689060210325
|
||||
self.kT_conv_factor = 0.001987204155
|
||||
self.mass_conv_factor = 100.0277580236
|
||||
self.length_conv_factor = 8.518
|
||||
self.time_conv_factor = 1706.0
|
||||
self.vel_conv_factor = 0.004992966002344666
|
||||
self.angular_mom_conv_factor = 4.254188991883894
|
||||
self.density_conv_factor = 0.2687551067436886
|
||||
|
||||
self.oxdna_fene_string = "11.92337812042065 2.1295 6.409795"
|
||||
self.oxdna_excv_string = "11.92337812042065 5.9626 5.74965 11.92337812042065 4.38677 4.259 11.92337812042065 2.81094 2.72576"
|
||||
self.oxdna_stk_string = "0.70439070204273 3.4072 7.6662 2.72576 6.3885 1.3 0.0 0.8 0.9 0.0 0.95 0.9 0.0 0.95 2.0 0.65 2.0 0.65"
|
||||
self.oxdna_hbond_string = "0.0 0.93918760272364 3.4072 6.3885 2.89612 5.9626 1.5 0.0 0.7 1.5 0 0.7 1.5 0 0.7 0.46 3.141592654 0.7 4.0 1.570796327 0.45 4.0 1.570796327 0.45"
|
||||
self.oxdna_hbond_1_4_2_3_string = "6.42073911784652 0.93918760272364 3.4072 6.3885 2.89612 5.9626 1.5 0 0.7 1.5 0.0 0.7 1.5 0 0.7 0.46 3.141592654 0.7 4.0 1.570796327 0.45 4.0 1.570796327 0.45"
|
||||
self.oxdna_xstk_string = "3.9029021145006 4.89785 5.74965 4.21641 5.57929 2.25 0.791592654 0.58 1.7 1.0 0.68 1.7 1.0 0.68 1.5 0 0.65 1.7 0.875 0.68 1.7 0.875 0.68"
|
||||
self.oxdna_coaxstk_string = "3.77965257404268 3.4072 5.1108 1.87396 4.94044 2.0 2.541592654 0.65 1.3 0 0.8 0.9 0 0.95 0.9 0 0.95 2 -0.65 2 -0.65"
|
||||
|
||||
self.oxdna2_fene_string = "11.92337812042065 2.1295 6.4430152"
|
||||
self.oxdna2_excv_string = "11.92337812042065 5.9626 5.74965 11.92337812042065 4.38677 4.259 11.92337812042065 2.81094 2.72576"
|
||||
self.oxdna2_stk_string = "0.70439070204273 3.4072 7.6662 2.72576 6.3885 1.3 0.0 0.8 0.9 0.0 0.95 0.9 0.0 0.95 2.0 0.65 2.0 0.65"
|
||||
self.oxdna2_hbond_string = "0.0 0.93918760272364 3.4072 6.3885 2.89612 5.9626 1.5 0.0 0.7 1.5 0 0.7 1.5 0 0.7 0.46 3.141592654 0.7 4.0 1.570796327 0.45 4.0 1.570796327 0.45"
|
||||
self.oxdna2_hbond_1_4_2_3_string = "6.36589157849259 0.93918760272364 3.4072 6.3885 2.89612 5.9626 1.5 0 0.7 1.5 0.0 0.7 1.5 0 0.7 0.46 3.141592654 0.7 4.0 1.570796327 0.45 4.0 1.570796327 0.45"
|
||||
self.oxdna2_xstk_string = "3.9029021145006 4.89785 5.74965 4.21641 5.57929 2.25 0.791592654 0.58 1.7 1.0 0.68 1.7 1.0 0.68 1.5 0 0.65 1.7 0.875 0.68 1.7 0.875 0.68"
|
||||
self.oxdna2_coaxstk_string = "4.80673207785863 3.4072 5.1108 1.87396 4.94044 2.0 2.891592653589793 0.65 1.3 0 0.8 0.9 0 0.95 0.9 0 0.95 40.0 3.116592653589793"
|
||||
|
||||
self.oxrna2_fene_string = "11.92337812042065 2.1295 6.482800913"
|
||||
self.oxrna2_excv_string = "11.92337812042065 5.9626 5.74965 11.92337812042065 4.38677 4.259 11.92337812042065 2.81094 2.72576"
|
||||
self.oxrna2_stk_string = "0.70439070204273 3.66274 7.92174 2.9813 6.64404 0.9 0.0 0.95 0.9 0.0 0.95 1.3 0.0 0.8 1.3 0.0 0.8 2.0 0.65 2.0 0.65"
|
||||
self.oxrna2_hbond_string = "0.0 0.93918760272364 3.4072 6.3885 2.89612 5.9626 1.5 0.0 0.7 1.5 0.0 0.7 1.5 0.0 0.7 0.46 3.141592653589793 0.7 4.0 1.5707963267948966 0.45 4.0 1.5707963267948966 0.45"
|
||||
self.oxrna2_hbond_1_4_2_3_3_4_string = "5.18928666388042 0.93918760272364 3.4072 6.3885 2.89612 5.9626 1.5 0.0 0.7 1.5 0.0 0.7 1.5 0.0 0.7 0.46 3.141592653589793 0.7 4.0 1.5707963267948966 0.45 4.0 1.5707963267948966 0.45"
|
||||
self.oxrna2_xstk_string = "4.92690859644113 4.259 5.1108 3.57756 4.94044 2.25 0.505 0.58 1.7 1.266 0.68 1.7 1.266 0.68 1.7 0.309 0.68 1.7 0.309 0.68"
|
||||
self.oxrna2_coaxstk_string = "6.57330882442206 4.259 5.1108 3.57756 4.94044 2.0 2.592 0.65 1.3 0.151 0.8 0.9 0.685 0.95 0.9 0.685 0.95 2.0 -0.65 2.0 -0.65"
|
||||
|
||||
if invert:
|
||||
self.invert()
|
||||
|
||||
def invert(self):
|
||||
"""Inverts the conversion factors for real -> LJ"""
|
||||
self.inverted = True
|
||||
self.temp_conv_factor = 1.0 / self.temp_conv_factor
|
||||
self.energy_conv_factor = 1.0 / self.energy_conv_factor
|
||||
self.kT_conv_factor = 1.0 / self.kT_conv_factor
|
||||
self.mass_conv_factor = 1.0 / self.mass_conv_factor
|
||||
self.length_conv_factor = 1.0 / self.length_conv_factor
|
||||
self.time_conv_factor = 1.0 / self.time_conv_factor
|
||||
self.vel_conv_factor = 1.0 / self.vel_conv_factor
|
||||
self.angular_mom_conv_factor = 1.0 / self.angular_mom_conv_factor
|
||||
self.density_conv_factor = 1.0 / self.density_conv_factor
|
||||
|
||||
self.oxdna_fene_string = "2.0 0.25 0.7525"
|
||||
self.oxdna_excv_string = "2.0 0.7 0.675 2.0 0.515 0.5 2.0 0.33 0.32"
|
||||
self.oxdna_stk_string = (
|
||||
"6.0 0.4 0.9 0.32 0.75 1.3 0 0.8 0.9 0 0.95 0.9 0 0.95 2.0 0.65 2.0 0.65"
|
||||
)
|
||||
self.oxdna_hbond_string = "0.0 8.0 0.4 0.75 0.34 0.7 1.5 0 0.7 1.5 0 0.7 1.5 0 0.7 0.46 3.141592653589793 0.7 4.0 1.5707963267948966 0.45 4.0 1.5707963267948966 0.45"
|
||||
self.oxdna_hbond_1_4_2_3_string = "1.077 8.0 0.4 0.75 0.34 0.7 1.5 0 0.7 1.5 0 0.7 1.5 0 0.7 0.46 3.141592653589793 0.7 4.0 1.5707963267948966 0.45 4.0 1.5707963267948966 0.45"
|
||||
self.oxdna_xstk_string = "47.5 0.575 0.675 0.495 0.655 2.25 0.791592653589793 0.58 1.7 1.0 0.68 1.7 1.0 0.68 1.5 0 0.65 1.7 0.875 0.68 1.7 0.875 0.68"
|
||||
self.oxdna_coaxstk_string = "46.0 0.4 0.6 0.22 0.58 2.0 2.541592653589793 0.65 1.3 0 0.8 0.9 0 0.95 0.9 0 0.95 2.0 -0.65 2.0 -0.65"
|
||||
|
||||
self.oxdna2_fene_string = "2.0 0.25 0.7564"
|
||||
self.oxdna2_excv_string = "2.0 0.7 0.675 2.0 0.515 0.5 2.0 0.33 0.32"
|
||||
self.oxdna2_stk_string = (
|
||||
"6.0 0.4 0.9 0.32 0.75 1.3 0 0.8 0.9 0 0.95 0.9 0 0.95 2.0 0.65 2.0 0.65"
|
||||
)
|
||||
self.oxdna2_hbond_string = "0.0 8.0 0.4 0.75 0.34 0.7 1.5 0 0.7 1.5 0 0.7 1.5 0 0.7 0.46 3.141592653589793 0.7 4.0 1.5707963267948966 0.45 4.0 1.5707963267948966 0.45"
|
||||
self.oxdna2_hbond_1_4_2_3_string = "1.0678 8.0 0.4 0.75 0.34 0.7 1.5 0 0.7 1.5 0 0.7 1.5 0 0.7 0.46 3.141592653589793 0.7 4.0 1.5707963267948966 0.45 4.0 1.5707963267948966 0.45"
|
||||
self.oxdna2_xstk_string = "47.5 0.575 0.675 0.495 0.655 2.25 0.791592653589793 0.58 1.7 1.0 0.68 1.7 1.0 0.68 1.5 0 0.65 1.7 0.875 0.68 1.7 0.875 0.68"
|
||||
self.oxdna2_coaxstk_string = "58.5 0.4 0.6 0.22 0.58 2.0 2.891592653589793 0.65 1.3 0 0.8 0.9 0 0.95 0.9 0 0.95 40.0 3.116592653589793"
|
||||
|
||||
self.oxrna2_fene_string = "2.0 0.25 0.761070781051"
|
||||
self.oxrna2_excv_string = "2.0 0.7 0.675 2.0 0.515 0.5 2.0 0.33 0.32"
|
||||
self.oxrna2_stk_string = "6.0 0.43 0.93 0.35 0.78 0.9 0 0.95 0.9 0 0.95 1.3 0 0.8 1.3 0 0.8 2.0 0.65 2.0 0.65"
|
||||
self.oxrna2_hbond_string = "0.0 8.0 0.4 0.75 0.34 0.7 1.5 0 0.7 1.5 0 0.7 1.5 0 0.7 0.46 3.141592653589793 0.7 4.0 1.5707963267948966 0.45 4.0 1.5707963267948966 0.45"
|
||||
self.oxrna2_hbond_1_4_2_3_3_4_string = "0.870439 8.0 0.4 0.75 0.34 0.7 1.5 0 0.7 1.5 0 0.7 1.5 0 0.7 0.46 3.141592653589793 0.7 4.0 1.5707963267948966 0.45 4.0 1.5707963267948966 0.45"
|
||||
self.oxrna2_xstk_string = "59.9626 0.5 0.6 0.42 0.58 2.25 0.505 0.58 1.7 1.266 0.68 1.7 1.266 0.68 1.7 0.309 0.68 1.7 0.309 0.68"
|
||||
self.oxrna2_coaxstk_string = "80 0.5 0.6 0.42 0.58 2.0 2.592 0.65 1.3 0.151 0.8 0.9 0.685 0.95 0.9 0.685 0.95 2.0 -0.65 2.0 -0.65"
|
||||
|
||||
|
||||
def check_datafile_header(line: str, sections: Sections):
|
||||
"""Checks for headers to modify corresponding data, since datafile is split into headers.
|
||||
Modifies the Sections object to keep track of the current section.
|
||||
|
||||
Args:
|
||||
line (str): The line to check
|
||||
masses_section (bool): If the current section is the masses section
|
||||
atoms_section (bool): If the current section is the atoms section
|
||||
velocities_section (bool): If the current section is the velocities section
|
||||
ellipsoids_section (bool): If the current section is the ellipsoids section
|
||||
"""
|
||||
|
||||
if any(header in line for header in ["xlo", "xhi", "ylo", "yhi", "zlo", "zhi"]):
|
||||
sections.bounds = True
|
||||
sections.masses = False
|
||||
sections.atoms = False
|
||||
sections.velocities = False
|
||||
sections.ellipsoids = False
|
||||
elif "Masses" in line:
|
||||
sections.bounds = False
|
||||
sections.masses = True
|
||||
sections.atoms = False
|
||||
sections.velocities = False
|
||||
sections.ellipsoids = False
|
||||
elif "Atoms" in line:
|
||||
sections.bounds = False
|
||||
sections.masses = False
|
||||
sections.atoms = True
|
||||
sections.velocities = False
|
||||
sections.ellipsoids = False
|
||||
elif "Velocities" in line:
|
||||
sections.bounds = False
|
||||
sections.masses = False
|
||||
sections.atoms = False
|
||||
sections.velocities = True
|
||||
sections.ellipsoids = False
|
||||
elif "Ellipsoids" in line:
|
||||
sections.bounds = False
|
||||
sections.masses = False
|
||||
sections.atoms = False
|
||||
sections.velocities = False
|
||||
sections.ellipsoids = True
|
||||
elif "Bonds" in line:
|
||||
sections.bounds = False
|
||||
sections.masses = False
|
||||
sections.atoms = False
|
||||
sections.velocities = False
|
||||
sections.ellipsoids = False
|
||||
|
||||
|
||||
def modify_datafile(datafile_path: str, conversion_factors: ConversionFactors):
|
||||
"""Modifies the file by header to use real units.
|
||||
|
||||
Args:
|
||||
datafile_path (str): The path to the file to modify
|
||||
"""
|
||||
lines_changed = 0
|
||||
current_section = Sections(False, False, False, False, False)
|
||||
|
||||
with open(datafile_path, "r", encoding="UTF-8") as file:
|
||||
lines = file.readlines()
|
||||
if conversion_factors.inverted:
|
||||
lines[0] = (
|
||||
"LAMMPS data file in LJ units via oxdna lj2real.py, date "
|
||||
+ str(datetime.date.today())
|
||||
+ "\n"
|
||||
)
|
||||
else:
|
||||
lines[0] = (
|
||||
"LAMMPS data file in real units via oxdna lj2real.py, date "
|
||||
+ str(datetime.date.today())
|
||||
+ "\n"
|
||||
)
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
check_datafile_header(line, current_section) # check for headers
|
||||
|
||||
elements = line.split()
|
||||
if (
|
||||
not elements
|
||||
or elements[0] == "#"
|
||||
or any(
|
||||
header in line
|
||||
for header in ["Masses", "Atoms", "Velocities", "Ellipsoids", "Bonds"]
|
||||
)
|
||||
):
|
||||
continue
|
||||
|
||||
# modify the line based on the current section it is in
|
||||
if current_section.bounds:
|
||||
elements[0:2] = [
|
||||
str(int(float(x) * conversion_factors.length_conv_factor))
|
||||
for x in elements[0:2]
|
||||
]
|
||||
lines[i] = " ".join(elements) + "\n"
|
||||
lines_changed += 1
|
||||
if current_section.masses:
|
||||
elements[1] = str(
|
||||
round(float(elements[1]) * conversion_factors.mass_conv_factor, 4)
|
||||
)
|
||||
lines[i] = " ".join(elements) + "\n"
|
||||
lines_changed += 1
|
||||
elif current_section.atoms:
|
||||
elements[2:5] = [
|
||||
str(float(x) * conversion_factors.length_conv_factor)
|
||||
for x in elements[2:5]
|
||||
]
|
||||
elements[7] = str(
|
||||
float(elements[7]) * conversion_factors.density_conv_factor
|
||||
)
|
||||
lines[i] = " ".join(elements) + "\n"
|
||||
lines_changed += 1
|
||||
elif current_section.velocities:
|
||||
elements[1:4] = [
|
||||
str(float(x) * conversion_factors.vel_conv_factor)
|
||||
for x in elements[1:4]
|
||||
]
|
||||
elements[4:7] = [
|
||||
str(float(x) * conversion_factors.angular_mom_conv_factor)
|
||||
for x in elements[4:7]
|
||||
]
|
||||
lines[i] = " ".join(elements) + "\n"
|
||||
lines_changed += 1
|
||||
elif current_section.ellipsoids:
|
||||
elements[1:4] = [
|
||||
str(float(x) * conversion_factors.length_conv_factor)
|
||||
for x in elements[1:4]
|
||||
]
|
||||
lines[i] = " ".join(elements) + "\n"
|
||||
lines_changed += 1
|
||||
|
||||
if conversion_factors.inverted:
|
||||
new_datafile_path = datafile_path + "_lj"
|
||||
else:
|
||||
new_datafile_path = datafile_path + "_real"
|
||||
|
||||
with open(new_datafile_path, "w", encoding="UTF-8") as file:
|
||||
file.writelines(lines)
|
||||
if lines_changed == 0:
|
||||
print(
|
||||
"Warning: No lines changed in data file. Ensure correct usage: python lj2real.py <datafile> <inputfile> [-i]"
|
||||
)
|
||||
else:
|
||||
print(f"Data file lines changed: {lines_changed}")
|
||||
|
||||
return new_datafile_path
|
||||
|
||||
|
||||
def modify_inputfile(inputfile_path: str, conversion_factors: ConversionFactors):
|
||||
"""Modifies the input file line by line to use real units.
|
||||
|
||||
Args:
|
||||
inputfile_path (str): The path to the input file to modify
|
||||
"""
|
||||
|
||||
lines_changed = 0
|
||||
oxdna2_flag, oxrna2_flag = False, False
|
||||
|
||||
with open(inputfile_path, "r", encoding="UTF-8") as file:
|
||||
lines = file.readlines()
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
if "oxdna2" in line and not oxdna2_flag:
|
||||
oxdna2_flag = True
|
||||
print("Note: oxdna2 found in input file. Using oxdna2 conversion factors.")
|
||||
if "oxrna2" in line and not oxrna2_flag:
|
||||
oxrna2_flag = True
|
||||
print("Note: oxrna2 found in input file. Using oxrna2 conversion factors.")
|
||||
if oxdna2_flag and oxrna2_flag:
|
||||
print(
|
||||
"Warning: Both oxdna2 and oxrna2 found in input file. Output will likely be incorrect."
|
||||
)
|
||||
|
||||
if "variable T" in line:
|
||||
old_value = line.split()[3]
|
||||
|
||||
new_value = str(
|
||||
round(float(old_value) * conversion_factors.temp_conv_factor, 1)
|
||||
)
|
||||
lines[i] = line.replace(old_value, new_value)
|
||||
lines_changed += 1
|
||||
|
||||
elif "units" in line:
|
||||
if conversion_factors.inverted:
|
||||
lines[i] = "units lj\n"
|
||||
else:
|
||||
lines[i] = "units real\n"
|
||||
lines_changed += 1
|
||||
|
||||
elif "atom_modify" in line:
|
||||
elements = line.split()
|
||||
elements[3] = str(
|
||||
round(float(elements[3]) * conversion_factors.length_conv_factor, 3)
|
||||
)
|
||||
lines[i] = " ".join(elements) + "\n"
|
||||
lines_changed += 1
|
||||
|
||||
elif "neighbor" in line:
|
||||
elements = line.split()
|
||||
elements[1] = str(
|
||||
round(float(elements[1]) * conversion_factors.length_conv_factor, 3)
|
||||
)
|
||||
lines[i] = " ".join(elements) + "\n"
|
||||
lines_changed += 1
|
||||
|
||||
elif "read_data" in line:
|
||||
elements = line.split()
|
||||
if conversion_factors.inverted:
|
||||
elements[1] = elements[1] + "_lj"
|
||||
else:
|
||||
elements[1] = (
|
||||
elements[1] + "_real"
|
||||
) # naming convention of datafile after conversion
|
||||
lines[i] = " ".join(elements) + "\n"
|
||||
lines_changed += 1
|
||||
|
||||
elif "mass" in line:
|
||||
elements = line.split()
|
||||
elements[4] = str(
|
||||
round(float(elements[4]) * conversion_factors.mass_conv_factor, 4)
|
||||
)
|
||||
lines[i] = " ".join(elements) + "\n"
|
||||
lines_changed += 1
|
||||
|
||||
elif "bond_coeff" in line or "pair_coeff" in line:
|
||||
if ".lj" in line or ".real" in line:
|
||||
if conversion_factors.inverted:
|
||||
line = line.replace(".real", ".lj")
|
||||
else:
|
||||
line = line.replace(".lj", ".real")
|
||||
lines[i] = line
|
||||
lines_changed += 1
|
||||
|
||||
if "stk" in line and "xstk" not in line and "coaxstk" not in line:
|
||||
elements = line.split()
|
||||
elements[6] = str( # convert xi
|
||||
round(
|
||||
float(elements[6]) * conversion_factors.energy_conv_factor,
|
||||
14,
|
||||
)
|
||||
)
|
||||
elements[7] = str( # convert kappa
|
||||
round(float(elements[7]) * conversion_factors.kT_conv_factor, 9)
|
||||
)
|
||||
lines[i] = " ".join(elements) + "\n"
|
||||
|
||||
else:
|
||||
elements = line.split()
|
||||
|
||||
if "bond_coeff" in line:
|
||||
if oxdna2_flag:
|
||||
elements[2:] = conversion_factors.oxdna2_fene_string.split()
|
||||
elif oxrna2_flag:
|
||||
elements[2:] = conversion_factors.oxrna2_fene_string.split()
|
||||
else:
|
||||
elements[2:] = conversion_factors.oxdna_fene_string.split()
|
||||
|
||||
elif "excv" in line:
|
||||
if oxdna2_flag:
|
||||
elements[4:] = conversion_factors.oxdna2_excv_string.split()
|
||||
elif oxrna2_flag:
|
||||
elements[4:] = conversion_factors.oxrna2_excv_string.split()
|
||||
else:
|
||||
elements[4:] = conversion_factors.oxdna_excv_string.split()
|
||||
|
||||
elif "stk" in line:
|
||||
|
||||
if "coaxstk" in line:
|
||||
if oxdna2_flag:
|
||||
elements[4:] = (
|
||||
conversion_factors.oxdna2_coaxstk_string.split()
|
||||
)
|
||||
elif oxrna2_flag:
|
||||
elements[4:] = (
|
||||
conversion_factors.oxrna2_coaxstk_string.split()
|
||||
)
|
||||
else:
|
||||
elements[4:] = (
|
||||
conversion_factors.oxdna_coaxstk_string.split()
|
||||
)
|
||||
|
||||
elif "xstk" in line:
|
||||
if oxdna2_flag:
|
||||
elements[4:] = conversion_factors.oxdna2_xstk_string.split()
|
||||
elif oxrna2_flag:
|
||||
elements[4:] = conversion_factors.oxrna2_xstk_string.split()
|
||||
else:
|
||||
elements[4:] = conversion_factors.oxdna_xstk_string.split()
|
||||
|
||||
else: # stk
|
||||
elements[6] = str( # convert xi
|
||||
round(
|
||||
float(elements[6])
|
||||
* conversion_factors.energy_conv_factor,
|
||||
14,
|
||||
)
|
||||
)
|
||||
elements[7] = str( # convert kappa
|
||||
round(
|
||||
float(elements[7]) * conversion_factors.kT_conv_factor,
|
||||
9,
|
||||
)
|
||||
)
|
||||
if oxdna2_flag:
|
||||
elements[8:] = conversion_factors.oxdna2_stk_string.split()
|
||||
elif oxrna2_flag:
|
||||
elements[8:] = conversion_factors.oxrna2_stk_string.split()
|
||||
else:
|
||||
elements[8:] = conversion_factors.oxdna_stk_string.split()
|
||||
|
||||
elif "hbond" in line:
|
||||
if elements[1] == "*" and elements[2] == "*":
|
||||
if oxdna2_flag:
|
||||
elements[5:] = (
|
||||
conversion_factors.oxdna2_hbond_string.split()
|
||||
)
|
||||
elif oxrna2_flag:
|
||||
elements[5:] = (
|
||||
conversion_factors.oxrna2_hbond_string.split()
|
||||
)
|
||||
else:
|
||||
elements[5:] = conversion_factors.oxdna_hbond_string.split()
|
||||
else:
|
||||
if oxdna2_flag:
|
||||
elements[5:] = (
|
||||
conversion_factors.oxdna2_hbond_1_4_2_3_string.split()
|
||||
)
|
||||
elif oxrna2_flag:
|
||||
elements[5:] = (
|
||||
conversion_factors.oxrna2_hbond_1_4_2_3_3_4_string.split()
|
||||
)
|
||||
else:
|
||||
elements[5:] = (
|
||||
conversion_factors.oxdna_hbond_1_4_2_3_string.split()
|
||||
)
|
||||
lines[i] = " ".join(elements) + "\n"
|
||||
lines_changed += 1
|
||||
|
||||
elif "langevin" in line:
|
||||
elements = line.split()
|
||||
elements[6] = str(
|
||||
round(float(elements[6]) * conversion_factors.time_conv_factor, 2)
|
||||
)
|
||||
lines[i] = " ".join(elements) + "\n"
|
||||
lines_changed += 1
|
||||
|
||||
elif "timestep" in line:
|
||||
elements = line.split()
|
||||
elements[1] = str(
|
||||
round(float(elements[1]) * conversion_factors.time_conv_factor, 5)
|
||||
)
|
||||
lines[i] = " ".join(elements) + "\n"
|
||||
lines_changed += 1
|
||||
|
||||
elif "comm_modify" in line:
|
||||
elements = line.split()
|
||||
elements[2] = str(
|
||||
round(float(elements[2]) * conversion_factors.length_conv_factor, 1)
|
||||
)
|
||||
lines[i] = " ".join(elements) + "\n"
|
||||
lines_changed += 1
|
||||
|
||||
else:
|
||||
continue
|
||||
|
||||
if conversion_factors.inverted:
|
||||
new_inputfile_path = inputfile_path + "_lj"
|
||||
else:
|
||||
new_inputfile_path = inputfile_path + "_real"
|
||||
|
||||
with open(new_inputfile_path, "w", encoding="UTF-8") as file:
|
||||
if conversion_factors.inverted:
|
||||
file.write(
|
||||
"# LAMMPS input file in LJ units via oxdna lj2real.py, date "
|
||||
+ str(datetime.date.today())
|
||||
+ "\n"
|
||||
)
|
||||
else:
|
||||
file.write(
|
||||
"# LAMMPS input file in real units via oxdna lj2real.py, date "
|
||||
+ str(datetime.date.today())
|
||||
+ "\n"
|
||||
)
|
||||
file.writelines(lines)
|
||||
if lines_changed == 0:
|
||||
print(
|
||||
"Warning: No lines changed in input file. Ensure correct usage: python lj2real.py <datafile> <inputfile> [-i]"
|
||||
)
|
||||
else:
|
||||
print(f"Input file lines changed: {lines_changed}")
|
||||
|
||||
return new_inputfile_path
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function"""
|
||||
|
||||
print(
|
||||
"\nLAMMPS data and input file conversion to real units via oxdna convert_data.py\n"
|
||||
"Note: This script assumes a input and data file structure similar to those found in examples/PACKAGES/cgdna/examples/.\n"
|
||||
"Ensure output is checked for correctness."
|
||||
)
|
||||
|
||||
if len(sys.argv) > 2:
|
||||
datafile_path = sys.argv[1]
|
||||
inputfile_path = sys.argv[2]
|
||||
invert = False
|
||||
if len(sys.argv) > 3:
|
||||
if sys.argv[3] == "-i":
|
||||
invert = True
|
||||
print("Performing real -> LJ conversion.")
|
||||
else:
|
||||
print(
|
||||
"Invalid flag. Usage: python lj2real.py <datafile> <inputfile> [-i]"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
if invert:
|
||||
conversion_factors = ConversionFactors(invert=True)
|
||||
print(
|
||||
"\nUsing conversion factors (real T, m, l, t, v, ρ -> LJ T*, m*, l*, t*, v*, ρ*):"
|
||||
)
|
||||
|
||||
else:
|
||||
conversion_factors = ConversionFactors(invert=False)
|
||||
print(
|
||||
"\nUsing conversion factors (LJ T*, m*, l*, t*, v*, ρ* -> real T, m, l, t, v, ρ):"
|
||||
)
|
||||
|
||||
else:
|
||||
print("\nUsage: python lj2real.py <datafile> <inputfile> [-i]")
|
||||
print("\t[-i] flag is optional and is used to convert real -> LJ units.\n")
|
||||
sys.exit(1)
|
||||
|
||||
conversion_factors_string = (
|
||||
f"Temperature T\t≈ {round(conversion_factors.temp_conv_factor, 6)} T* (K)\n"
|
||||
f"Energy ε\t≈ {round(conversion_factors.energy_conv_factor, 6)} ε* (kcal/mol)\n"
|
||||
f"Mass m\t\t≈ {round(conversion_factors.mass_conv_factor, 6)} m* (g/mol)\n"
|
||||
f"Length l\t≈ {round(conversion_factors.length_conv_factor, 6)} l* (Å)\n"
|
||||
f"Time t\t\t≈ {round(conversion_factors.time_conv_factor, 6)} t* (fs)\n"
|
||||
f"Velocity v\t≈ {round(conversion_factors.vel_conv_factor, 6)} v* (Å/fs)\n"
|
||||
f"AngMom l\t≈ {round(conversion_factors.angular_mom_conv_factor, 6)} (g/mol Å^2/fs)\n"
|
||||
f"Density ρ\t≈ {round(conversion_factors.density_conv_factor, 6)} ρ* (g/cm^3)\n"
|
||||
f"Calculated using Sengar, Ouldridge, Henrich, Rovigatti, & Šulc. Front Mol Biosci 8 (2021). & https://docs.lammps.org/units.html.\n"
|
||||
f"See examples/PACKAGES/cgdna/util/lj2real.py for exact conversion factors.\n"
|
||||
)
|
||||
print(conversion_factors_string)
|
||||
|
||||
print("Current directory: ", os.getcwd())
|
||||
|
||||
try:
|
||||
new_datafile_path = modify_datafile(datafile_path, conversion_factors)
|
||||
print(f"New data file: {new_datafile_path}")
|
||||
except Exception as e:
|
||||
print(f"Error modifying data file: {e}")
|
||||
|
||||
try:
|
||||
new_inputfile_path = modify_inputfile(inputfile_path, conversion_factors)
|
||||
print(f"New input file: {new_inputfile_path}\n")
|
||||
except Exception as e:
|
||||
print(f"Error modifying input file: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user