@@ -13,28 +13,28 @@ To follow the tutorial, |MDAnalysis|, |NumPy|, and
1313MD system
1414---------
1515
16- .. image :: ../figures/tutorials/ isotropic-systems /snapshot-dark.png
16+ .. image :: isotropic-system /snapshot-dark.png
1717 :class: only-dark
1818 :alt: PEG-water mixture simulated with LAMMPS - Dipolar NMR relaxation time calculation
1919 :width: 250
2020 :align: right
2121
22- .. image :: ../figures/tutorials/ isotropic-systems /snapshot-light.png
22+ .. image :: isotropic-system /snapshot-light.png
2323 :class: only-light
2424 :alt: PEG-water mixture simulated with LAMMPS - Dipolar NMR relaxation time calculation
2525 :width: 250
2626 :align: right
2727
28- The system consists of a bulk mixture of 320 :math: `\text {H}_2 \text {O}` water
29- molecules and 32 :math: `\text {PEG 300 }` polymer molecules. The :math: `\text {TIP4 P}-\epsilon `
28+ The system consists of a bulk mixture of 420 :math: `\text {H}_2 \text {O}` water
29+ molecules and 30 :math: `\text {PEG 300 }` polymer molecules. The :math: `\text {TIP4 P}-\epsilon `
3030is used for the water :cite: `fuentes-azcatlNonPolarizableForceField2014 `.
3131:math: `\text {PEG 300 }` refers to polyethylene glycol chains with a molar mass of
3232:math: `300 ~\text {g/mol}`. The trajectory was recorded during a
3333:math: `10 ~\text {ns}` production run performed using the open-source code
3434LAMMPS in the :math: `NpT` ensemble with a timestep of :math: `1 ~\text {fs}`.
3535The temperature was set to :math: `T = 300 ~\text {K}` and the pressure to
3636:math: `p = 1 ~\text {atm}`. Atomic positions were saved in the **prod.xtc ** file
37- every :math: `1 ~\text {ps}`.
37+ every :math: `2 ~\text {ps}`.
3838
3939.. admonition :: Note
4040 :class: non-title-info
@@ -98,6 +98,7 @@ of molecules (water and PEG):
9898 n_TOT = u.atoms.n_residues
9999 n_H2O = u.select_atoms(" type 6 7" ).n_residues
100100 n_PEG = u.select_atoms(" type 1 2 3 4 5" ).n_residues
101+
101102 print (f " The total number of molecules is { n_TOT} ( { n_H2O} H2O, { n_PEG} PEG) " )
102103
103104 Executing the script using Python will return:
@@ -135,142 +136,173 @@ Executing the script using Python will return:
135136Launch the H-NMR analysis
136137-------------------------
137138
138- Let us create three atom groups: the hydrogen atoms of the PEG, the hydrogen
139- atoms of the water, and all hydrogen atoms:
139+ First, we create three atom groups: the hydrogen atoms of the PEG, the
140+ hydrogen atoms of the water, and all hydrogen atoms:
140141
141142.. code-block :: python
142143
143144 H_PEG = u.select_atoms(" type 3 5" )
144145 H_H2O = u.select_atoms(" type 7" )
145146 H_ALL = H_PEG + H_H2O
146147
147- Then, let us first run NMRDfromMD for all hydrogen atoms:
148+ Next, we run `` NMRDfromMD `` for all hydrogen atoms:
148149
149150.. code-block :: python
150151
151152 nmr_all = NMRD(
152153 u = u,
153154 atom_group = H_ALL ,
154155 neighbor_group = H_ALL ,
155- number_i = 40 )
156+ number_i = 20 )
156157 nmr_all.run_analysis()
157158
158- With ``number_i = 40 ``, only 40 randomly selected atoms from ``H_ALL `` are
159- used in the calculation. Increase this number for better statistical resolution,
160- or set ``number_i = 0 `` to include all atoms in the group. Here, ``H_ALL ``
161- is specified as both the ``atom_group `` and ``neighbor_group ``.
159+ With ``number_i = 20 ``, only 20 randomly selected atoms from ``H_ALL `` are
160+ included in the calculation. Increasing this number improves statistical
161+ resolution, while setting ``number_i = 0 `` includes all atoms in the group.
162+ Here, ``H_ALL `` is specified as both the ``atom_group `` and the
163+ ``neighbor_group ``.
162164
163- Let us access the calculated value of the NMR relaxation time :math: `T_1 `
164- in :math: `f \to 0 ` by adding the following lines to the Python script:
165+ To access the calculated value of the NMR relaxation time :math: `T_1 ` in
166+ the limit :math: `f \to 0 `, add the following lines to your Python script:
165167
166168.. code-block :: python
167169
168170 T1 = np.round(nmr_all.T1, 2 )
169171
170172 print (f " The NMR relaxation time is T1 = { T1} s " )
171173
172- which should return :
174+ The output should be similar to :
173175
174176.. code-block :: bw
175177
176178 The NMR relaxation time is T1 = 1.59 s
177179
178- The exact value you obtain will be different, as it depends on which hydrogen
179- atoms were randomly selected for the calculation. With the small value
180- ``number_i = 40 ``, the noise is important. You can increase that number
181- for more precise result, but this will obviously increase the computation time.
180+ The exact value you obtain may differ, as it depends on the specific hydrogen
181+ atoms that were randomly selected for the calculation. With the relatively
182+ small value of ``number_i = 20 ``, the uncertainty is significant. Increasing
183+ ``number_i `` will yield more precise results but at the cost of increased
184+ computation time.
182185
183186Extract the NMR spectra
184187-----------------------
185188
186- The full :math: `R_1 ` and :math: `T_2 ` spectra can be extracted as
187- ``1/nmr_ALL.R1 `` and ``1/nmr_ALL.R2 ``, respectively. The corresponding
188- frequencies are stored in ``nmr_ALL.f ``.
189+ The relaxation rates :math: `R_1 (f) = 1 /T_1 (f)` (in units of
190+ :math: `\text {s}^{-1 }`) and :math: `R_2 (f) = 1 /T_2 (f)` can be extracted for
191+ all frequencies :math: `f` (in MHz) as ``nmr_all.R1 `` and ``nmr_all.R2 ``,
192+ respectively. The corresponding frequencies are stored in ``nmr_all.f ``.
189193
190194.. code-block :: python
191195
192- R1_spectrum = nmr_ALL.R1
193- R2_spectrum = nmr_ALL.R2
194- T1_spectrum = 1 / R1_spectrum
195- T2_spectrum = 1 / R2_spectrum
196- f = nmr_ALL.f
196+ R1_spectrum = nmr_all.R1
197+ R2_spectrum = nmr_all.R2
198+ f = nmr_all.f
197199
198- The spectra :math: `T_ 1 ` and :math: `T_ 2 ` can then be plotted as a function of
199- :math: `f` using ``pyplot ``:
200+ The spectra :math: `R_ 1 (f) ` and :math: `R_ 2 (f) ` can then be plotted as a
201+ function of :math: `f` using ``pyplot ``:
200202
201203.. code-block :: python
202204
203205 from matplotlib import pyplot as plt
204- plt.loglog(f, T1_spectrum, ' o' , label = ' T1' )
205- plt.loglog(f, T2_spectrum, ' s' , label = ' T2' )
206- plt.xlabel(" f (MHz)" )
207- plt.ylabel(" T1, T2 (s)" )
206+
207+ # Plot settings
208+ plt.figure(figsize = (8 , 5 ))
209+ plt.loglog(f, R1_spectrum, ' o' , label = ' R1' , markersize = 5 )
210+ plt.loglog(f, R2_spectrum, ' s' , label = ' R2' , markersize = 5 )
211+ # Labels and Title
212+ plt.xlabel(" Frequency (MHz)" , fontsize = 12 )
213+ plt.ylabel(" Relaxation Rates (s⁻¹)" , fontsize = 12 )
214+ # Grid and boundaries
215+ plt.grid(True , which = " both" , linestyle = ' --' , linewidth = 0.7 )
216+ plt.xlim(80 , 1e5 )
217+ plt.ylim(0.05 , 2 )
218+ # Legend
208219 plt.legend()
220+ plt.tight_layout()
209221 plt.show()
210222
211- .. image :: ../figures/tutorials/ isotropic-systems/T1-dark .png
223+ .. image :: isotropic-system/nmr-total-dm .png
212224 :class: only-dark
213225 :alt: NMR results obtained from the LAMMPS simulation of water
214226
215- .. image :: ../figures/tutorials/ isotropic-systems/T1-light .png
227+ .. image :: isotropic-system/nmr-total .png
216228 :class: only-light
217229 :alt: NMR results obtained from the LAMMPS simulation of water
218230
219231.. container :: figurelegend
220232
221- Figure: NMR relaxation times :math: `T_1 ` (disks) and :math: `T_2 ` (squares)
222- as a function of the frequency :math: `f` for the
223- :math: `\text {PEG-H}_2 \text {O}` bulk mixture.
233+ Figure: NMR relaxation rates :math: `R_1 ` (A) and :math: `R_2 ` (B) as a
234+ function of the frequency :math: `f` for the
235+ :math: `\text {PEG-H}_2 \text {O}` bulk mixture. Results are shown for two
236+ different values of ``number_i ``, :math: `n_i`.
237+
238+ Separating intra from intermolecular contributions
239+ --------------------------------------------------
224240
225- Calculate the intra-molecular NMR relaxation
226- --------------------------------------------
241+ So far, the calculations were performed for the two molecule types, PEG and
242+ :math: `\text {H}_2 \text {O}`, without distinguishing between intra and intermolecular
243+ contributions. However, this separation is meaningful and allows for
244+ identifying the primary contributors to the relaxation process.
227245
228- Let us measure the intra-molecular contribution to the NMR relaxation time.
229- To simplify the analysis, we will differentiate between PEG and
230- :math: `\text {H}_2 \text {O}` molecules and perform two separate analyses.
246+ Let us extract the intramolecular contributions to the relaxation for
247+ both water and PEG, separately:
231248
232249.. code-block :: python
233250
234- nmr_H2O_intra = nmrmd.NMR(u, atom_group = H_H2O , type_analysis = " intra_molecular" , number_i = 40 )
235- nmr_PEG_intra = nmrmd.NMR(u, atom_group = H_PEG , type_analysis = " intra_molecular" , number_i = 40 )
251+ nmr_h2o_intra = NMRD(
252+ u = u,
253+ atom_group = H_H2O ,
254+ type_analysis = " intra_molecular" ,
255+ number_i = 200 )
256+ nmr_h2o_intra.run_analysis()
236257
237- The correlation function :math: `G_{ij}` can be accessed from
238- ``nmr_H2O_intra.gij[0] ``, and the corresponding time values from
239- ``nmr_H2O_intra.t ``:
258+ nmr_peg_intra = NMRD(
259+ u = u,
260+ atom_group = H_PEG ,
261+ type_analysis = " intra_molecular" ,
262+ number_i = 200 )
263+ nmr_peg_intra.run_analysis()
264+
265+ We can also measure the intermolecular contributions:
240266
241267.. code-block :: python
242268
243- t = nmr_PEG_intra.t
244- G_intra_H2O = nmr_H2O_intra.gij[0 ]
245- G_intra_PEG = nmr_PEG_intra.gij[0 ]
269+ nmr_h2o_inter = NMRD(
270+ u = u,
271+ atom_group = H_H2O ,
272+ type_analysis = " inter_molecular" ,
273+ number_i = 200 )
274+ nmr_h2o_inter.run_analysis()
246275
247- .. image :: ../figures/tutorials/isotropic-systems/Gintra-dark.png
276+ nmr_peg_inter = NMRD(
277+ u = u,
278+ atom_group = H_PEG ,
279+ type_analysis = " inter_molecular" ,
280+ number_i = 200 )
281+ nmr_peg_inter.run_analysis()
282+
283+ Importantly, when no ``neighbor_group `` is specified, the ``atom_group `` is
284+ used as the neighbor group. Thus, in this case, intermolecular
285+ contributions are calculated between molecules of the same type only.
286+
287+ When comparing the NMR spectra ``nmr_h2o_inter.R1 `` and ``nmr_h2o_intra.R1 ``,
288+ you may observe that the intramolecular contributions to :math: `R_1 ` are
289+ larger than the intermolecular contributions. Additionally, the
290+ intra- and intermolecular spectra display different scaling with
291+ frequency :math: `f`, reflecting distinct motion types contributing to each
292+ term.
293+
294+ .. image :: isotropic-system/nmr-intra-dm.png
248295 :class: only-dark
249- :alt: NMR results obtained from the LAMMPS simulation of water-PEG
296+ :alt: NMR results obtained from the LAMMPS simulation of water
250297
251- .. image :: ../figures/tutorials/ isotropic-systems/Gintra-light .png
298+ .. image :: isotropic-system/nmr-intra .png
252299 :class: only-light
253- :alt: NMR results obtained from the LAMMPS simulation of water-PEG
300+ :alt: NMR results obtained from the LAMMPS simulation of water
254301
255302.. container :: figurelegend
256303
257- Figure: Intra-molecular correlation function :math: `G_\text {R}` for both
258- PEG (squares) and :math: `\text {H}_2 \text {O}` (disks).
259-
260- From the correlation functions, one can obtain the typical rotational
261- time of the molecules:
262-
263- .. code-block :: python
264-
265- tau_rot_H2O = np.round(np.trapz(G_intra_H2O, t)/ G_intra_H2O[0 ],2 )
266- tau_rot_PEG = np.round(np.trapz(G_intra_PEG, t)/ G_intra_PEG[0 ],2 )
267- print (f " The rotational time of H2O is = { tau_rot_H2O} ps " )
268- print (f " The rotational time of PEG is = { tau_rot_PEG} ps " )
269-
270- This should return (again, the exact values will likely differ in your
271- case):
272-
273- .. code-block :: bw
274-
275- >> The rotational time of H2O is = 6.35 ps
276- >> The rotational time of PEG is = 8.34 ps
304+ Figure: Intramolecular NMR relaxation rates :math: `R_{1 \text {R}}` (A) and
305+ Intermolecular NMR relaxation rates :math: `R_{1 \text {T}}` (B) as a
306+ function of the frequency :math: `f` for the
307+ :math: `\text {PEG-H}_2 \text {O}` bulk mixture. Results are shown for
308+ :math: `n_i = 1280 `.
0 commit comments