@@ -121,6 +121,97 @@ def extract_fragment(
121121 selection_string = f"index { frag .indices [0 ]} :{ frag .indices [- 1 ]} "
122122 return self .select_atoms (universe , selection_string )
123123
124+ def convert_lammps (
125+ self ,
126+ tprfile : str ,
127+ trrfile ,
128+ fileformat : str | None = None ,
129+ ) -> mda .Universe :
130+ """Update the units produced from the universe produced from LAMMPS
131+ format topology and trajectory files. MDA currently has a bug that
132+ results in forces not being converted to the correct units
133+ (see issue for more details:
134+ https://github.com/MDAnalysis/mdanalysis/issues/5115
135+ )
136+ The method currently expects the following additional columns in the
137+ lammps dump file: fx fy fz c_5 c_7
138+ where c_5 and c_7 are the atom potential and kinetic energies respectively.
139+
140+ This method loads:
141+
142+ - Coordinates and dimensions from the coordinate trajectory
143+ (``tprfile`` + ``trrfile``).
144+
145+ Args:
146+ tprfile: Topology input file.
147+ trrfile: Coordinate trajectory file(s). This can be a single path or a
148+ list, as accepted by MDAnalysis.
149+ fileformat: Optional file format for the coordinate trajectory, as
150+ recognised by MDAnalysis.
151+
152+ Returns:
153+ MDAnalysis.Universe: A new Universe containing coordinates, forces and
154+ dimensions loaded into memory.
155+
156+ Raises:
157+ ValueError: If fileformat is not one of the supported values.
158+ """
159+
160+ def _convert_lammps_forces_energies (ts ):
161+ """
162+ Convert lammps forces from kcal/mol/Ang to kJ/mol/Ang.
163+ Assumes columns for per-atom potential (c_5) and kinetic energies (c_7)
164+ are provided and converts these too.
165+
166+ Args:
167+ ts: MDAnalysis timeseries from the trajectory.
168+
169+ Returns:
170+ A converted time series.
171+ """
172+ ts .forces *= 4.184
173+ ts .data ["c_5" ] *= 4.184
174+ ts .data ["c_7" ] *= 4.184
175+ return ts
176+
177+ def _convert_lammps_forces (ts ):
178+ """
179+ Convert lammps forces from kcal/mol/Ang to kJ/mol/Ang.
180+
181+ Args:
182+ ts: MDAnalysis timeseries from the trajectory.
183+
184+ Returns:
185+ A converted time series.
186+ """
187+ ts .forces *= 4.184
188+ return ts
189+
190+ if fileformat == "LAMMPSDUMP" :
191+ try :
192+ return mda .Universe (
193+ tprfile ,
194+ trrfile ,
195+ format = fileformat ,
196+ additional_columns = ["fx" , "fy" , "fz" , "c_5" , "c_7" ],
197+ transformations = [_convert_lammps_forces_energies ],
198+ )
199+ except KeyError :
200+ logger .debug (
201+ f"Warning: Energy columns not found in LAMMPSDUMP: { trrfile } "
202+ )
203+ return mda .Universe (
204+ tprfile ,
205+ trrfile ,
206+ format = fileformat ,
207+ additional_columns = ["fx" , "fy" , "fz" ],
208+ transformations = [_convert_lammps_forces ],
209+ )
210+ else :
211+ raise ValueError (
212+ f"Incorrect file format: { fileformat } , LAMMPSDUMP expected"
213+ )
214+
124215 def merge_forces (
125216 self ,
126217 tprfile : str ,
0 commit comments