From e5f823b67bb9dae6d58199358efec3e4fea9c834 Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Tue, 22 Jun 2021 12:04:44 -0700 Subject: [PATCH 01/55] add minimal support for merz and TIP4PFB water model --- mdgo/data/ion/merz/tip4pfb/Cl-.lmp | 28 ++++++++++++++++ mdgo/data/ion/merz/tip4pfb/Zn++.lmp | 27 +++++++++++++++ mdgo/data/water/water_tip4p_fb.lmp | 51 +++++++++++++++++++++++++++++ mdgo/forcefield.py | 2 ++ 4 files changed, 108 insertions(+) create mode 100644 mdgo/data/ion/merz/tip4pfb/Cl-.lmp create mode 100644 mdgo/data/ion/merz/tip4pfb/Zn++.lmp create mode 100644 mdgo/data/water/water_tip4p_fb.lmp diff --git a/mdgo/data/ion/merz/tip4pfb/Cl-.lmp b/mdgo/data/ion/merz/tip4pfb/Cl-.lmp new file mode 100644 index 00000000..7af53b08 --- /dev/null +++ b/mdgo/data/ion/merz/tip4pfb/Cl-.lmp @@ -0,0 +1,28 @@ +Cl- +# Sengupta et al. Parameterization of Monovalent Ions for the OPC3, OPC, TIP3P-FB, and +# TIP4P-FB Water Models. J. Chem. Information Modeling 61(2), 2021. +# https://pubs.acs.org/doi/10.1021/acs.jcim.0c01390 +# This set of values is optimized for reproducing ion-oxygen distance (Table 3) using +# the TIP4P-FB water model +# all values in 'real' units (kcal/mol and Angstrom) + + + 1 atoms + + 1 atom types + + 0.0 1.0 xlo xhi + 0.0 1.0 ylo yhi + 0.0 1.0 zlo zhi + +Masses + + 1 35.453 + +Pair Coeffs #lj/cut/coul/long + + 1 0.53486081 2.166 + +Atoms + + 1 1 1 -1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/merz/tip4pfb/Zn++.lmp b/mdgo/data/ion/merz/tip4pfb/Zn++.lmp new file mode 100644 index 00000000..279e11d8 --- /dev/null +++ b/mdgo/data/ion/merz/tip4pfb/Zn++.lmp @@ -0,0 +1,27 @@ +Zn++ +# Li et al. Systematic Parametrization of Divalent Metal Ions for the OPC3, OPC, +# TIP3P-FB, and TIP4P-FB Water Models. J. Chem. Theory and Computation 16(7), 2020. +# https://pubs.acs.org/doi/10.1021/acs.jctc.0c00194 +# This set of values is optimized for reproducing ion-oxygen distance (Table 3) using +# the TIP4P-FB water model +# all values in 'real' units (kcal/mol and Angstrom) + + 1 atoms + + 1 atom types + + 0.0 1.0 xlo xhi + 0.0 1.0 ylo yhi + 0.0 1.0 zlo zhi + +Masses + + 1 64.929 + +Pair Coeffs #lj/cut/coul/long + + 1 0.01314367 1.383 + +Atoms + + 1 1 1 2.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/water/water_tip4p_fb.lmp b/mdgo/data/water/water_tip4p_fb.lmp new file mode 100644 index 00000000..4697d87d --- /dev/null +++ b/mdgo/data/water/water_tip4p_fb.lmp @@ -0,0 +1,51 @@ +Optimized TIP4P-FB parameters for water +# Original model from Wang et al., Building Force Fields: An Automatic, +# Systematic, and Reproducible Approach, J. Phys. Chem. Letters 5(11), 2014. +# https://pubs.acs.org/doi/10.1021/jz500737m +# real units (kcal/mol, Angstrom) +# Command 'fix shake' is needed. + + 3 atoms + 2 bonds + 1 angles + + 2 atom types + 1 bond types + 1 angle types + + 0.0 3.1 xlo xhi + 0.0 3.1 ylo yhi + 0.0 3.1 zlo zhi + +Masses + + 1 1.00794 + 2 15.9994 + +Pair Coeffs #lj/cut/tip4p/long 2 1 1 1 0.10527 9.0 7.0 + + 1 0.000 0.000 + 2 0.74928 3.1655 + +Bond Coeffs #harmonic + + 1 0.0 0.9572 + +Angle Coeffs #harmonic + + 1 0.0 104.52 + +Atoms + + 1 1 2 -1.05740 1.55000 1.55000 1.50000 + 2 1 1 0.52587 1.55000 2.36649 2.07736 + 3 1 1 0.52587 1.55000 0.73351 2.07736 + +Bonds + + 1 1 1 2 + 2 1 1 3 + +Angles + + 1 1 2 1 3 diff --git a/mdgo/forcefield.py b/mdgo/forcefield.py index 13438ef4..5dce3cf6 100644 --- a/mdgo/forcefield.py +++ b/mdgo/forcefield.py @@ -66,6 +66,7 @@ "tip3pew": "water_tip3p_ew.lmp", "tip4p2005": "water_tip4p_2005.lmp", "tip4pew": "water_tip4p_ew.lmp", + "tip4pfb": "water_tip4p_fb.lmp" }, "ion": { "aq": ["default"], @@ -74,6 +75,7 @@ "jensen_jorgensen": ["default"], "jc": ["spce", "tip3p", "tip4pew"], "joung_cheatham": ["spce", "tip3p", "tip4pew"], + "merz": ["tip4pfb"], }, "alias": {"aq": "aqvist", "jj": "jensen_jorgensen", "jc": "joung_cheatham"}, } From 8d92e55b618b3e90d32718a337fa9a10541c7102 Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Wed, 23 Jun 2021 13:54:24 -0700 Subject: [PATCH 02/55] add stiff bonds to water models for energy min --- mdgo/data/water/water_spc.lmp | 6 ++++-- mdgo/data/water/water_spce.lmp | 6 ++++-- mdgo/data/water/water_tip4p_2005.lmp | 8 +++++--- mdgo/data/water/water_tip4p_ew.lmp | 6 ++++-- mdgo/data/water/water_tip4p_fb.lmp | 7 +++++-- 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/mdgo/data/water/water_spc.lmp b/mdgo/data/water/water_spc.lmp index 3629ab44..7a630ee3 100644 --- a/mdgo/data/water/water_spc.lmp +++ b/mdgo/data/water/water_spc.lmp @@ -1,5 +1,7 @@ SPC water model # Berendsen et al, in "Intermolecular forces", p. 331 (1981). Command 'fix shake' is needed. +# Bond and angle coefficients of 1000 are added to keep the water molecule together +# during e.g. energy minimization in LAMMPS when `fix shake` is not active. 3 atoms 2 bonds @@ -25,11 +27,11 @@ Pair Coeffs #lj/cut/coul/long 10.0 Bond Coeffs #harmonic - 1 0.0 1.0 + 1 1000 1.0 Angle Coeffs #harmonic - 1 0.0 109.47 + 1 1000 109.47 Atoms diff --git a/mdgo/data/water/water_spce.lmp b/mdgo/data/water/water_spce.lmp index fcc55ddd..fd8aa791 100644 --- a/mdgo/data/water/water_spce.lmp +++ b/mdgo/data/water/water_spce.lmp @@ -1,5 +1,7 @@ SPC/E water model # From Berendsen et al, J Phys Chem 91:6269 (1987). Command 'fix shake' is needed. +# Bond and angle coefficients of 1000 are added to keep the water molecule together +# during e.g. energy minimization in LAMMPS when `fix shake` is not active. 3 atoms 2 bonds @@ -25,11 +27,11 @@ Pair Coeffs #lj/cut/coul/long 10.0 Bond Coeffs #harmonic - 1 0.0 1.0 + 1 1000 1.0 Angle Coeffs #harmonic - 1 0.0 109.47 + 1 1000 109.47 Atoms diff --git a/mdgo/data/water/water_tip4p_2005.lmp b/mdgo/data/water/water_tip4p_2005.lmp index 4f448a9d..4b81832c 100644 --- a/mdgo/data/water/water_tip4p_2005.lmp +++ b/mdgo/data/water/water_tip4p_2005.lmp @@ -1,5 +1,7 @@ This forcefield file sets a 13-Angstrom cutoff, recommended for liquid-vapor simulations -# [Vega & de Miguel, J Chem Phys 126:154707 (2007), Vega et al, Faraday Discuss 141:251 (2009)]. Note that the original TIP4P/2005 model was run with an 8.5 Angstrom cutoff [Abascal & Vega, J Chem Phys 123:234505 (2005)]. +# [Vega & de Miguel, J Chem Phys 126:154707 (2007), Vega et al, Faraday Discuss 141:251 (2009)]. Note that the original TIP4P/2005 model was run with an 8.5 Angstrom cutoff [Abascal & Vega, J Chem Phys 123:234505 (2005)]. +# Bond and angle coefficients of 1000 are added to keep the water molecule together +# during e.g. energy minimization in LAMMPS when `fix shake` is not active. 3 atoms 2 bonds @@ -25,11 +27,11 @@ Pair Coeffs #lj/cut/tip4p/long 2 1 1 1 0.1546 13.0 Bond Coeffs #harmonic - 1 0.0 0.9572 + 1 1000 0.9572 Angle Coeffs #harmonic - 1 0.0 104.52 + 1 1000 104.52 Atoms diff --git a/mdgo/data/water/water_tip4p_ew.lmp b/mdgo/data/water/water_tip4p_ew.lmp index 4b079bae..a65b9343 100644 --- a/mdgo/data/water/water_tip4p_ew.lmp +++ b/mdgo/data/water/water_tip4p_ew.lmp @@ -1,5 +1,7 @@ Optimized TIP4P parameters to use with Ewald methods for long-range electrostatics. (e.g. pppm/tip4p 1.0e-5) # Original model from Horn et al, J Chem Phys 120: 9665 (2004). Command 'fix shake' is needed. +# Bond and angle coefficients of 1000 are added to keep the water molecule together +# during e.g. energy minimization in LAMMPS when `fix shake` is not active. 3 atoms 2 bonds @@ -25,11 +27,11 @@ Pair Coeffs #lj/cut/tip4p/long 2 1 1 1 0.125 10.0 Bond Coeffs #harmonic - 1 0.0 0.9572 + 1 1000 0.9572 Angle Coeffs #harmonic - 1 0.0 104.52 + 1 1000 104.52 Atoms diff --git a/mdgo/data/water/water_tip4p_fb.lmp b/mdgo/data/water/water_tip4p_fb.lmp index 4697d87d..ad2a7b63 100644 --- a/mdgo/data/water/water_tip4p_fb.lmp +++ b/mdgo/data/water/water_tip4p_fb.lmp @@ -4,6 +4,9 @@ Optimized TIP4P-FB parameters for water # https://pubs.acs.org/doi/10.1021/jz500737m # real units (kcal/mol, Angstrom) # Command 'fix shake' is needed. +# LJ and couloumb cutoffs of 9 and 7 angstroms were used in the original work +# Bond and angle coefficients of 1000 are added to keep the water molecule together +# during e.g. energy minimization in LAMMPS when `fix shake` is not active. 3 atoms 2 bonds @@ -29,11 +32,11 @@ Pair Coeffs #lj/cut/tip4p/long 2 1 1 1 0.10527 9.0 7.0 Bond Coeffs #harmonic - 1 0.0 0.9572 + 1 1000 0.9572 Angle Coeffs #harmonic - 1 0.0 104.52 + 1 1000 104.52 Atoms From d7bb5e1e05186fd699aebfb809e48ec68f11a7e8 Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Fri, 25 Jun 2021 10:50:19 -0700 Subject: [PATCH 03/55] fix typo in tip4p_fb water charge --- mdgo/data/water/water_tip4p_fb.lmp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mdgo/data/water/water_tip4p_fb.lmp b/mdgo/data/water/water_tip4p_fb.lmp index ad2a7b63..7ca4111c 100644 --- a/mdgo/data/water/water_tip4p_fb.lmp +++ b/mdgo/data/water/water_tip4p_fb.lmp @@ -40,7 +40,7 @@ Angle Coeffs #harmonic Atoms - 1 1 2 -1.05740 1.55000 1.55000 1.50000 + 1 1 2 -1.05174 1.55000 1.55000 1.50000 2 1 1 0.52587 1.55000 2.36649 2.07736 3 1 1 0.52587 1.55000 0.73351 2.07736 From f5487c71dd7abdc6e8d6e48a624f83e3d7ba2ba6 Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Fri, 16 Jul 2021 15:38:48 -0700 Subject: [PATCH 04/55] fix ion conversion mistake; add Na+ --- mdgo/data/ion/merz/tip4pfb/Cl-.lmp | 7 +++++-- mdgo/data/ion/merz/tip4pfb/Na+.lmp | 31 +++++++++++++++++++++++++++++ mdgo/data/ion/merz/tip4pfb/Zn++.lmp | 8 ++++++-- 3 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 mdgo/data/ion/merz/tip4pfb/Na+.lmp diff --git a/mdgo/data/ion/merz/tip4pfb/Cl-.lmp b/mdgo/data/ion/merz/tip4pfb/Cl-.lmp index 7af53b08..92d24e52 100644 --- a/mdgo/data/ion/merz/tip4pfb/Cl-.lmp +++ b/mdgo/data/ion/merz/tip4pfb/Cl-.lmp @@ -6,6 +6,9 @@ Cl- # the TIP4P-FB water model # all values in 'real' units (kcal/mol and Angstrom) +# Note that LAMMPS requires the value sigma (the distance at which the potential equals +# zero, rather than Rmin/2 which is reported in the paper. To convert, use +# sigma = Rmin/2 * 2^(5/6) 1 atoms @@ -19,9 +22,9 @@ Masses 1 35.453 -Pair Coeffs #lj/cut/coul/long +Pair Coeffs - 1 0.53486081 2.166 + 1 0.53486081 3.8594 Atoms diff --git a/mdgo/data/ion/merz/tip4pfb/Na+.lmp b/mdgo/data/ion/merz/tip4pfb/Na+.lmp new file mode 100644 index 00000000..ed4a062d --- /dev/null +++ b/mdgo/data/ion/merz/tip4pfb/Na+.lmp @@ -0,0 +1,31 @@ +Na+ +# Sengupta et al. Parameterization of Monovalent Ions for the OPC3, OPC, TIP3P-FB, and +# TIP4P-FB Water Models. J. Chem. Information Modeling 61(2), 2021. +# https://pubs.acs.org/doi/10.1021/acs.jcim.0c01390 +# This set of values is optimized for reproducing ion-oxygen distance (Table 3) using +# the TIP4P-FB water model +# all values in 'real' units (kcal/mol and Angstrom) + +# Note that LAMMPS requires the value sigma (the distance at which the potential equals +# zero, rather than Rmin/2 which is reported in the paper. To convert, use +# sigma = Rmin/2 * 2^(5/6) + + 1 atoms + + 1 atom types + + 0.0 1.0 xlo xhi + 0.0 1.0 ylo yhi + 0.0 1.0 zlo zhi + +Masses + + 1 22.9898 + +Pair Coeffs + + 1 0.02545423 2.5836 + +Atoms + + 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/merz/tip4pfb/Zn++.lmp b/mdgo/data/ion/merz/tip4pfb/Zn++.lmp index 279e11d8..c8c15eac 100644 --- a/mdgo/data/ion/merz/tip4pfb/Zn++.lmp +++ b/mdgo/data/ion/merz/tip4pfb/Zn++.lmp @@ -6,6 +6,10 @@ Zn++ # the TIP4P-FB water model # all values in 'real' units (kcal/mol and Angstrom) +# Note that LAMMPS requires the value sigma (the distance at which the potential equals +# zero, rather than Rmin/2 which is reported in the paper. To convert, use +# sigma = Rmin/2 * 2^(5/6) + 1 atoms 1 atom types @@ -18,9 +22,9 @@ Masses 1 64.929 -Pair Coeffs #lj/cut/coul/long +Pair Coeffs #lj/cut/tip4p/long 2 1 1 1 0.10527 9.0 7.0 - 1 0.01314367 1.383 + 1 0.01314367 2.4642 Atoms From cfac13d78b027a92cb1a35a1071c119cd15e33fd Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Wed, 21 Jul 2021 16:33:44 -0700 Subject: [PATCH 05/55] correct units of epsilon in tip4pfb; add tip3pfb reported as kJ/mol; need to convert to kcal/mol --- mdgo/data/water/water_tip3p_fb.lmp | 54 ++++++++++++++++++++++++++++++ mdgo/data/water/water_tip4p_fb.lmp | 2 +- 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 mdgo/data/water/water_tip3p_fb.lmp diff --git a/mdgo/data/water/water_tip3p_fb.lmp b/mdgo/data/water/water_tip3p_fb.lmp new file mode 100644 index 00000000..3f9f7776 --- /dev/null +++ b/mdgo/data/water/water_tip3p_fb.lmp @@ -0,0 +1,54 @@ +Optimized TIP3P-FB parameters for water +# Original model from Wang et al., Building Force Fields: An Automatic, +# Systematic, and Reproducible Approach, J. Phys. Chem. Letters 5(11), 2014. +# https://pubs.acs.org/doi/10.1021/jz500737m +# real units (kcal/mol, Angstrom) +# Command 'fix shake' is needed. +# LJ and couloumb cutoffs of 9 and 7 angstroms were used in the original work +# Bond and angle coefficients of 1000 are added to keep the water molecule together +# during e.g. energy minimization in LAMMPS when `fix shake` is not active. + + 3 atoms + 2 bonds + 1 angles + + 2 atom types + 1 bond types + 1 angle types + + 0.0 3.1 xlo xhi + 0.0 3.1 ylo yhi + 0.0 3.1 zlo zhi + +Masses + + 1 1.00794 + 2 15.9994 + +Pair Coeffs #lj/cut/coul/long 9.0 7.0 + + 1 0.000 0.000 + 2 0.15587 3.1780 + +Bond Coeffs #harmonic + + 1 1000 1.0118 + +Angle Coeffs #harmonic + + 1 1000 108.15 + +Atoms + + 1 1 2 -0.84844 1.55000 1.55000 1.50000 + 2 1 1 0.42422 1.55000 2.36649 2.07736 + 3 1 1 0.42422 1.55000 0.73351 2.07736 + +Bonds + + 1 1 1 2 + 2 1 1 3 + +Angles + + 1 1 2 1 3 diff --git a/mdgo/data/water/water_tip4p_fb.lmp b/mdgo/data/water/water_tip4p_fb.lmp index 7ca4111c..d5aee0a8 100644 --- a/mdgo/data/water/water_tip4p_fb.lmp +++ b/mdgo/data/water/water_tip4p_fb.lmp @@ -28,7 +28,7 @@ Masses Pair Coeffs #lj/cut/tip4p/long 2 1 1 1 0.10527 9.0 7.0 1 0.000 0.000 - 2 0.74928 3.1655 + 2 0.17908 3.1655 Bond Coeffs #harmonic From 9b3832064b22ea72854f837fae85c6c75dbdc322 Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Wed, 21 Jul 2021 17:15:16 -0700 Subject: [PATCH 06/55] overhaul ion parameter sets -Went back to original papers -checked and converted all values -cross-checked previous data entry -moved ion parameters into an .xlsx file instead of text files -reworked call signature of get_ion In the future it would be preferable to store the ion data as a .json instead of .xlsx. However pandas read_json does not support MultiIndex very well. --- docs/source/aqueous.rst | 136 ++++++++++++++++++++++++++++ mdgo/data/ion_lj_data.xlsx | Bin 0 -> 10920 bytes mdgo/forcefield.py | 179 ++++++++++++++++++++++++++----------- 3 files changed, 265 insertions(+), 50 deletions(-) create mode 100644 docs/source/aqueous.rst create mode 100644 mdgo/data/ion_lj_data.xlsx diff --git a/docs/source/aqueous.rst b/docs/source/aqueous.rst new file mode 100644 index 00000000..4dda720a --- /dev/null +++ b/docs/source/aqueous.rst @@ -0,0 +1,136 @@ + +================================ +Force Fields for Aqueous Systems +================================ + +The Aqueous module provides tools for setting up molecular dynamics simulations +involving water and ions. + +Water Models +============ + +`mdgo` contains parameters for several popular water models. This section lists +a brief description and literature reference to the available models. + +SPC +--- + +TIP3P-EW +-------- + +TIP3P-FB +-------- + +Wang, L., Martinez, T. J., Pande, V.S., Building Force Fields: An Automatic, Systematic, +and Reproducible Approach. J. Phys. Chem. Lett. 2014, 5, 11, 1885–1891. +https://pubs.acs.org/doi/abs/10.1021/jz500737m + +Parameters are given in Supporting Table 1. Note that the epsilon for Oxygen must be converted +from kJ/mol to kcal/mol. + +TIP4P-EW +-------- + +TIP4P-FB +-------- + +Wang, L., Martinez, T. J., Pande, V.S., Building Force Fields: An Automatic, Systematic, +and Reproducible Approach. J. Phys. Chem. Lett. 2014, 5, 11, 1885–1891. +https://pubs.acs.org/doi/abs/10.1021/jz500737m + +Parameters are given in Supporting Table 1. Note that the epsilon for Oxygen must be converted +from kJ/mol to kcal/mol. + +TIP4P-2005 +---------- + +OPC? +---- + +OPC3? +----- + + +Ion Parameter Sets +================== + +``mdgo`` contains a compilation of several sets of Lennard Jones +paramters for ions in water. All values are reported as :math:`\sigma_i` +and :math:`\epsilon_i` in the equation + +.. math:: + + E = 4 \\epsilon_i \\left[ \\left( \\frac{\sigma_i}{r} \\right)^{12} - \\left( \\frac{\sigma_i}{r} \\right)^{6} \\right] + +Values of :math:`\sigma_i` and :math:`\epsilon_i` are given in Angstrom +and kcal/mol, respectively, corresponding to the ‘real’ units system in +LAMMPS. + +Aqvist (aq) +----------- + +Aqvist, J. Ion-Water Interaction Potentials Derived from Free Energy +Perturbation Slmulations J. Phys. Chem. 1990, 94, 8021– 8024. +https://pubs.acs.org/doi/10.1021/j100384a009 + +Values were parameterized to the SPC water model and are reported in +Table I and II as :math:`A_i` and :math:`B_i` coefficients in the +following form of the Lennard-Jones potential: + +.. math:: + + + E = \left[ \left( \frac{A_i^2}{r} \right)^{12} - \left( \frac{B_i^2}{r} \right)^{6} \right] + +This parameter set is a work in progress! + +Jensen and Jorgensen (jj) +------------------------- + +Jensen, K. P. and Jorgensen, W. L., Halide, Ammonium, and Alkali Metal +Ion Parameters for Modeling Aqueous Solutions. J. Chem. Theory Comput. +2006, 2, 6, 1499–1509. https://pubs.acs.org/doi/abs/10.1021/ct600252r + +Values were parameterized to the TIP4P water model using geometric +combining rules and are reported directly as sigma_i and epsilon_i in +Table 2. + +Joung-Cheatham (jc) +------------------- + +Joung, and Thomas E. Cheatham, Thomas E. III, Determination of Alkali +and Halide Monovalent Ion Parameters for Use in Explicitly Solvated +Biomolecular Simulations. J. Phys. Chem. B 2008, 112, 30, 9020–9041. +https://pubs.acs.org/doi/10.1021/jp8001614 + +Values were parameterized for the SPC/E, TIP3P, and TIP4P_EW water +models using Lorentz-Berthelot combinging rules (LAMMPS: ‘arithmetic’) +and are reported in Table 5 as :math:`R_{min}`/2 and epsilon_i. R_min/2 +values are converted to :math:`\sigma_i` values using +:math:`\sigma_i = R_{min}/2 * 2^(5/6)` + +Li and Merz group (lm) +---------------------- + +Sengupta et al. Parameterization of Monovalent Ions for the OPC3, OPC, +TIP3P-FB, and TIP4P-FB Water Models. J. Chem. Information Modeling +61(2), 2021. https://pubs.acs.org/doi/10.1021/acs.jcim.0c01390 + +Li et al. Systematic Parametrization of Divalent Metal Ions for the +OPC3, OPC, TIP3P-FB, and TIP4P-FB Water Models. J. Chem. Theory and +Computation 16(7), 2020. +https://pubs.acs.org/doi/10.1021/acs.jctc.0c00194 + +Li et al. Parametrization of Trivalent and Tetravalent Metal Ions for +the OPC3, OPC, TIP3P-FB, and TIP4P-FB Water Models. J. Chem. Theory and +Computation 17(4), 2021. +https://pubs.acs.org/doi/10.1021/acs.jctc.0c01320 + +Values were parameterized for the OPC, OPC3, TIP3P-FB, and TIP4P-FB +water models using Lorentz-Berthelot combinging rules (LAMMPS: +‘arithmetic’) and are reported in Table 3 as :math:`R_{min}`/2 and +epsilon_i. R_min/2 values are converted to :math:`\sigma_i` values using +:math:`\sigma_i = R_{min}/2 * 2^(5/6)`. This set of values is optimized +for reproducing ion-oxygen distance. An alternate set of values optimized for +hydration free energies is available in the original papers. + diff --git a/mdgo/data/ion_lj_data.xlsx b/mdgo/data/ion_lj_data.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..a174b8cd038f1d46aafd8564de4e6a769981dd5d GIT binary patch literal 10920 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 literal 0 HcmV?d00001 diff --git a/mdgo/forcefield.py b/mdgo/forcefield.py index 86c7c955..34ddcc44 100644 --- a/mdgo/forcefield.py +++ b/mdgo/forcefield.py @@ -24,16 +24,19 @@ """ import time import os +import pandas as pd import re import shutil import signal import subprocess -from typing import Optional +from typing import Optional, Union from string import Template from urllib.parse import quote import numpy as np import pubchempy as pcp -from pymatgen.io.lammps.data import LammpsData +from pymatgen.core import Lattice, Structure +from pymatgen.core.ion import Ion +from pymatgen.io.lammps.data import LammpsData, ForceField, Topology, lattice_2_lmpbox from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait @@ -64,20 +67,11 @@ "spc": "water_spc.lmp", "spce": "water_spce.lmp", "tip3pew": "water_tip3p_ew.lmp", + "tip3pfb": "water_tip3p_fb.lmp", "tip4p2005": "water_tip4p_2005.lmp", "tip4pew": "water_tip4p_ew.lmp", - "tip4pfb": "water_tip4p_fb.lmp" + "tip4pfb": "water_tip4p_fb.lmp", }, - "ion": { - "aq": ["default"], - "aqvist": ["default"], - "jj": ["default"], - "jensen_jorgensen": ["default"], - "jc": ["spce", "tip3p", "tip4pew"], - "joung_cheatham": ["spce", "tip3p", "tip4pew"], - "merz": ["tip4pfb"], - }, - "alias": {"aq": "aqvist", "jj": "jensen_jorgensen", "jc": "joung_cheatham"}, } @@ -566,6 +560,22 @@ class Aqueous: """ A class for retreiving water and ion force field parameters. + Available water models are: + 1. SPC + 2. SPC/E + 3. TIP3P-EW + 4. TIP3P-FB + 5. TIP4P-EW + 6. TIP4P-2005 + 7. TIP4P-FB + + Multiple sets of Lennard Jones parameters for ions are available as well. + Not every set is available for every water model. The parameter sets included + are: + 1. Jensen and Jorgensen, 2006 (abbreviation 'jj') + 2. Joung and Cheatham, 2008 (abbreviation 'jc') + 3. Li and Merz group, 2020 (abbreviation, 'lm') + Examples: Retreive SPC/E water model: >>> spce_data = Aqueous.get_water() @@ -576,64 +586,133 @@ class Aqueous: """ @staticmethod - def get_water(model: str = "spce") -> Optional[LammpsData]: + def get_water(model: str = "spce") -> LammpsData: """ Retrieve water model parameters. Args: model: Water model to use. Valid choices are "spc", "spce", - "tip3pew", "tip4p2005", and "tip4pew". (Default: "spce") + "tip3pew", "tip3pfb", "tip4p2005", "tip4pew", and "tip4pfb". + (Default: "spce") Returns: LammpsData: Force field parameters for the chosen water model. If you specify an invalid water model, None is returned. """ - data_path = DATA_DIR signature = "".join(re.split(r"[\W|_]+", model)).lower() if DATA_MODELS["water"].get(signature): - return LammpsData.from_file(os.path.join(data_path, "water", DATA_MODELS["water"].get(signature))) - print("Water model not found. Please specify a customized data path or try another water model.\n") - return None + return LammpsData.from_file(os.path.join(DATA_DIR, "water", DATA_MODELS["water"].get(signature))) + raise ValueError("Water model not found. Please specify a customized data path or try another water model.\n") @staticmethod - def get_ion(model: str = "jensen_jorgensen", water: str = "default", ion: str = "li+") -> Optional[LammpsData]: + def get_ion( + ion: Union[Ion, str] = "li+", + water_model: str = "spce", + parameter_set: Optional[str] = None, + ) -> LammpsData: """ Retrieve force field parameters for an ion in water. Args: - model: Force field to use. Valid choices are "aqvist" (or "aq"), - "jensen_jorgensen" (or "jj"), ""joung_cheatham" (or "jc"). - water: Water model to use. For the jensen_jorgensen and aqvist - models, the only choice is 'default'. For the joung_cheatham - model, valid choices are "spce", "tip3p", and "tip4pew". - ion: Formula of the ion (e.g., "Li+"). + ion: Formula of the ion (e.g., "Li+"). Not case sensitive. May be + passed as either a string or an Ion object. + water_model: Water model to use. Models must be given as a string + (not case sensitive). "-" and "/" are ignored. Hence "tip3pfb" + and "TIP3P-FB" are both valid inputs for the TIP3P-FB water model. + Available water models are: + 1. SPC + 2. SPC/E + 3. TIP3P-EW + 4. TIP3P-FB + 5. TIP4P-EW + 6. TIP4P-2005 + 7. TIP4P-FB + The default water model is TIP4P-FB, the reparameterized TIP4P of + Wang, Martinez, and Pande (2014). See documentation. + parameter_set: Force field parameters to use for ions. + Valid choices are: + 1. "jj" for the Jensen and Jorgensen parameters (2006)" + 2. "jc" for Joung-Cheatham parameters (2008) + 3. "lm" for the Li and Merz group parameters (2020-2021)" + If None (default), then the parameter set is automatically set + to the recommended choice for the given water model. Recommended + choices are based on the water models originally used to parameterize + the ion parameters, but other combinations are possible at your own + risk. Returns: Force field parameters for the chosen water model. - If the desired combination of force field and water model - for the given ion is not available, None is returned. """ - data_path = DATA_DIR - alias = DATA_MODELS.get("alias", {}) - signature = model.lower() - if signature in alias: - signature = alias.get(model) - ion_type = ion.capitalize() - for key in DATA_MODELS["ion"]: - if key.startswith(signature): - ion_model = DATA_MODELS["ion"].get(key) - if water in ion_model: - if water == "default": - file_path = os.path.join(data_path, "ion", key, ion_type + ".lmp") - else: - file_path = os.path.join(data_path, "ion", key, water, ion_type + ".lmp") - if os.path.exists(file_path): - return LammpsData.from_file(file_path) - print("Ion not found. Please try another ion.\n") - return None - print("Water model not found. Please try another water model.\n") - return None - print("Ion model not found. Please try another ion model.\n") - return None + alias = {"aq": "aqvist", "jj": "jensen_jorgensen", "jc": "joung_cheatham", "lm": "li_merz"} + default_sets = { + "spc": None, + "spce": "jc", + "tip3p": "jc", + "tip3pew": None, + "tip3pfb": "lm", + "tip4p2005": None, + "tip4p": "jj", + "tip4pew": "jc", + "tip4pfb": "lm", + } + water_model = water_model.replace("-", "").replace("/", "").lower() + if parameter_set: + parameter_set = parameter_set.lower() + parameter_set = alias.get(parameter_set) + else: + parameter_set = default_sets.get(water_model) + + # Make the Ion object to get mass and charge + if isinstance(ion, Ion): + ion_obj = ion + else: + ion_obj = Ion.from_formula(ion.capitalize()) + + # load ion data + # ion_data = pd.read_json(os.path.join(DATA_DIR, "ion_lj_data.json")) + ion_data = pd.read_excel( + "/Users/ryan/miniconda3/envs/md/code/mdgo/mdgo/data/ion_lj_data.xlsx", header=[0, 1, 2], index_col=0 + ) + + # make sure the ion is in the DataFrame + key = ion_obj.reduced_formula + if key not in ion_data.index: + raise ValueError(f"Ion {key} not found in database. Please try a different ion.") + + # make sure the parameter set is in the DataFrame + key = ion_obj.reduced_formula + if parameter_set not in ion_data.columns.levels[0]: + raise ValueError( + f"Parameter set {parameter_set} not found in database. Please try a different parameter set." + ) + + # make sure the water model is in the DataFrame + key = ion_obj.reduced_formula + if water_model not in ion_data.columns.levels[1]: + raise ValueError(f"Water model {water_model} not found in database. Please try a different water model.") + + # we only consider monatomic ions at present + # construct a cubic LammpsBox from a lattice + lat = Lattice([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + box = lattice_2_lmpbox(lat)[0] + # put it in the center of a cubic Structure + struct = Structure(lat, ion_obj, [[0.5, 0.5, 0.5]]) + # construct Topology with the ion centered in the box + topo = Topology(struct, charges=[ion_obj.charge]) + + # retrieve Lennard-Jones parameters + # values may be np.nan if selected combination is not available + sigma = ion_data[parameter_set][water_model].loc[key, "σ (Å)"] + epsilon = ion_data[parameter_set][water_model].loc[key, "ε(kcal/mol)"] + if np.isfinite(sigma) and np.isfinite(epsilon): + # construct ForceField object + ff = ForceField([(str(e), e) for e in ion_obj.elements], nonbond_coeffs=[[epsilon, sigma]]) + + return LammpsData.from_ff_and_topologies(box, ff, [topo], atom_style="full") + + else: + raise ValueError( + f"No {parameter_set} ion parameters for water model {water_model}. See documentation and try a different combination." + ) class ChargeWriter: From c93d2d78a512c8393a50d4e3c6d3ac68ccc0f87e Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Wed, 21 Jul 2021 17:22:36 -0700 Subject: [PATCH 07/55] organize imports --- mdgo/forcefield.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/mdgo/forcefield.py b/mdgo/forcefield.py index 34ddcc44..c78144c0 100644 --- a/mdgo/forcefield.py +++ b/mdgo/forcefield.py @@ -22,34 +22,34 @@ https://www.schrodinger.com/kb/1842 for details. """ -import time import os -import pandas as pd import re import shutil import signal import subprocess -from typing import Optional, Union +import time from string import Template +from typing import Optional, Union from urllib.parse import quote + import numpy as np +import pandas as pd import pubchempy as pcp from pymatgen.core import Lattice, Structure from pymatgen.core.ion import Ion -from pymatgen.io.lammps.data import LammpsData, ForceField, Topology, lattice_2_lmpbox +from pymatgen.io.lammps.data import ForceField, LammpsData, Topology, lattice_2_lmpbox from selenium import webdriver -from selenium.webdriver.common.by import By -from selenium.webdriver.support.ui import WebDriverWait -from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import ( - TimeoutException, NoSuchElementException, + TimeoutException, WebDriverException, ) +from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.ui import WebDriverWait from typing_extensions import Final -from mdgo.util import lmp_mass_to_name, ff_parser, sdf_to_pdb - +from mdgo.util import ff_parser, lmp_mass_to_name, sdf_to_pdb __author__ = "Tingzheng Hou" __version__ = "1.0" From 0fc4e7fdcc763d14dbf4d7e69d865e5a07c3582a Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Wed, 21 Jul 2021 17:29:48 -0700 Subject: [PATCH 08/55] bugfixes --- mdgo/forcefield.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mdgo/forcefield.py b/mdgo/forcefield.py index c78144c0..0faabc5e 100644 --- a/mdgo/forcefield.py +++ b/mdgo/forcefield.py @@ -657,9 +657,9 @@ def get_ion( water_model = water_model.replace("-", "").replace("/", "").lower() if parameter_set: parameter_set = parameter_set.lower() - parameter_set = alias.get(parameter_set) else: parameter_set = default_sets.get(water_model) + parameter_set = alias.get(parameter_set) # Make the Ion object to get mass and charge if isinstance(ion, Ion): @@ -709,10 +709,10 @@ def get_ion( return LammpsData.from_ff_and_topologies(box, ff, [topo], atom_style="full") - else: - raise ValueError( - f"No {parameter_set} ion parameters for water model {water_model}. See documentation and try a different combination." - ) + raise ValueError( + f"No {parameter_set} ion parameters for water model {water_model}. " + "See documentation and try a different combination." + ) class ChargeWriter: From 6c6b3895a8f27bc339bbb555d36f8fab1a011b3a Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Tue, 22 Jun 2021 12:04:44 -0700 Subject: [PATCH 09/55] add minimal support for merz and TIP4PFB water model --- mdgo/data/ion/merz/tip4pfb/Cl-.lmp | 28 ++++++++++++++++ mdgo/data/ion/merz/tip4pfb/Zn++.lmp | 27 +++++++++++++++ mdgo/data/water/water_tip4p_fb.lmp | 51 +++++++++++++++++++++++++++++ mdgo/forcefield.py | 2 ++ 4 files changed, 108 insertions(+) create mode 100644 mdgo/data/ion/merz/tip4pfb/Cl-.lmp create mode 100644 mdgo/data/ion/merz/tip4pfb/Zn++.lmp create mode 100644 mdgo/data/water/water_tip4p_fb.lmp diff --git a/mdgo/data/ion/merz/tip4pfb/Cl-.lmp b/mdgo/data/ion/merz/tip4pfb/Cl-.lmp new file mode 100644 index 00000000..7af53b08 --- /dev/null +++ b/mdgo/data/ion/merz/tip4pfb/Cl-.lmp @@ -0,0 +1,28 @@ +Cl- +# Sengupta et al. Parameterization of Monovalent Ions for the OPC3, OPC, TIP3P-FB, and +# TIP4P-FB Water Models. J. Chem. Information Modeling 61(2), 2021. +# https://pubs.acs.org/doi/10.1021/acs.jcim.0c01390 +# This set of values is optimized for reproducing ion-oxygen distance (Table 3) using +# the TIP4P-FB water model +# all values in 'real' units (kcal/mol and Angstrom) + + + 1 atoms + + 1 atom types + + 0.0 1.0 xlo xhi + 0.0 1.0 ylo yhi + 0.0 1.0 zlo zhi + +Masses + + 1 35.453 + +Pair Coeffs #lj/cut/coul/long + + 1 0.53486081 2.166 + +Atoms + + 1 1 1 -1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/merz/tip4pfb/Zn++.lmp b/mdgo/data/ion/merz/tip4pfb/Zn++.lmp new file mode 100644 index 00000000..279e11d8 --- /dev/null +++ b/mdgo/data/ion/merz/tip4pfb/Zn++.lmp @@ -0,0 +1,27 @@ +Zn++ +# Li et al. Systematic Parametrization of Divalent Metal Ions for the OPC3, OPC, +# TIP3P-FB, and TIP4P-FB Water Models. J. Chem. Theory and Computation 16(7), 2020. +# https://pubs.acs.org/doi/10.1021/acs.jctc.0c00194 +# This set of values is optimized for reproducing ion-oxygen distance (Table 3) using +# the TIP4P-FB water model +# all values in 'real' units (kcal/mol and Angstrom) + + 1 atoms + + 1 atom types + + 0.0 1.0 xlo xhi + 0.0 1.0 ylo yhi + 0.0 1.0 zlo zhi + +Masses + + 1 64.929 + +Pair Coeffs #lj/cut/coul/long + + 1 0.01314367 1.383 + +Atoms + + 1 1 1 2.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/water/water_tip4p_fb.lmp b/mdgo/data/water/water_tip4p_fb.lmp new file mode 100644 index 00000000..4697d87d --- /dev/null +++ b/mdgo/data/water/water_tip4p_fb.lmp @@ -0,0 +1,51 @@ +Optimized TIP4P-FB parameters for water +# Original model from Wang et al., Building Force Fields: An Automatic, +# Systematic, and Reproducible Approach, J. Phys. Chem. Letters 5(11), 2014. +# https://pubs.acs.org/doi/10.1021/jz500737m +# real units (kcal/mol, Angstrom) +# Command 'fix shake' is needed. + + 3 atoms + 2 bonds + 1 angles + + 2 atom types + 1 bond types + 1 angle types + + 0.0 3.1 xlo xhi + 0.0 3.1 ylo yhi + 0.0 3.1 zlo zhi + +Masses + + 1 1.00794 + 2 15.9994 + +Pair Coeffs #lj/cut/tip4p/long 2 1 1 1 0.10527 9.0 7.0 + + 1 0.000 0.000 + 2 0.74928 3.1655 + +Bond Coeffs #harmonic + + 1 0.0 0.9572 + +Angle Coeffs #harmonic + + 1 0.0 104.52 + +Atoms + + 1 1 2 -1.05740 1.55000 1.55000 1.50000 + 2 1 1 0.52587 1.55000 2.36649 2.07736 + 3 1 1 0.52587 1.55000 0.73351 2.07736 + +Bonds + + 1 1 1 2 + 2 1 1 3 + +Angles + + 1 1 2 1 3 diff --git a/mdgo/forcefield.py b/mdgo/forcefield.py index 197528db..86c7c955 100644 --- a/mdgo/forcefield.py +++ b/mdgo/forcefield.py @@ -66,6 +66,7 @@ "tip3pew": "water_tip3p_ew.lmp", "tip4p2005": "water_tip4p_2005.lmp", "tip4pew": "water_tip4p_ew.lmp", + "tip4pfb": "water_tip4p_fb.lmp" }, "ion": { "aq": ["default"], @@ -74,6 +75,7 @@ "jensen_jorgensen": ["default"], "jc": ["spce", "tip3p", "tip4pew"], "joung_cheatham": ["spce", "tip3p", "tip4pew"], + "merz": ["tip4pfb"], }, "alias": {"aq": "aqvist", "jj": "jensen_jorgensen", "jc": "joung_cheatham"}, } From f5100ee95db997fd8011412773278d2eae97934d Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Wed, 23 Jun 2021 13:54:24 -0700 Subject: [PATCH 10/55] add stiff bonds to water models for energy min --- mdgo/data/water/water_spc.lmp | 6 ++++-- mdgo/data/water/water_spce.lmp | 6 ++++-- mdgo/data/water/water_tip4p_2005.lmp | 8 +++++--- mdgo/data/water/water_tip4p_ew.lmp | 6 ++++-- mdgo/data/water/water_tip4p_fb.lmp | 7 +++++-- 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/mdgo/data/water/water_spc.lmp b/mdgo/data/water/water_spc.lmp index 3629ab44..7a630ee3 100644 --- a/mdgo/data/water/water_spc.lmp +++ b/mdgo/data/water/water_spc.lmp @@ -1,5 +1,7 @@ SPC water model # Berendsen et al, in "Intermolecular forces", p. 331 (1981). Command 'fix shake' is needed. +# Bond and angle coefficients of 1000 are added to keep the water molecule together +# during e.g. energy minimization in LAMMPS when `fix shake` is not active. 3 atoms 2 bonds @@ -25,11 +27,11 @@ Pair Coeffs #lj/cut/coul/long 10.0 Bond Coeffs #harmonic - 1 0.0 1.0 + 1 1000 1.0 Angle Coeffs #harmonic - 1 0.0 109.47 + 1 1000 109.47 Atoms diff --git a/mdgo/data/water/water_spce.lmp b/mdgo/data/water/water_spce.lmp index fcc55ddd..fd8aa791 100644 --- a/mdgo/data/water/water_spce.lmp +++ b/mdgo/data/water/water_spce.lmp @@ -1,5 +1,7 @@ SPC/E water model # From Berendsen et al, J Phys Chem 91:6269 (1987). Command 'fix shake' is needed. +# Bond and angle coefficients of 1000 are added to keep the water molecule together +# during e.g. energy minimization in LAMMPS when `fix shake` is not active. 3 atoms 2 bonds @@ -25,11 +27,11 @@ Pair Coeffs #lj/cut/coul/long 10.0 Bond Coeffs #harmonic - 1 0.0 1.0 + 1 1000 1.0 Angle Coeffs #harmonic - 1 0.0 109.47 + 1 1000 109.47 Atoms diff --git a/mdgo/data/water/water_tip4p_2005.lmp b/mdgo/data/water/water_tip4p_2005.lmp index 4f448a9d..4b81832c 100644 --- a/mdgo/data/water/water_tip4p_2005.lmp +++ b/mdgo/data/water/water_tip4p_2005.lmp @@ -1,5 +1,7 @@ This forcefield file sets a 13-Angstrom cutoff, recommended for liquid-vapor simulations -# [Vega & de Miguel, J Chem Phys 126:154707 (2007), Vega et al, Faraday Discuss 141:251 (2009)]. Note that the original TIP4P/2005 model was run with an 8.5 Angstrom cutoff [Abascal & Vega, J Chem Phys 123:234505 (2005)]. +# [Vega & de Miguel, J Chem Phys 126:154707 (2007), Vega et al, Faraday Discuss 141:251 (2009)]. Note that the original TIP4P/2005 model was run with an 8.5 Angstrom cutoff [Abascal & Vega, J Chem Phys 123:234505 (2005)]. +# Bond and angle coefficients of 1000 are added to keep the water molecule together +# during e.g. energy minimization in LAMMPS when `fix shake` is not active. 3 atoms 2 bonds @@ -25,11 +27,11 @@ Pair Coeffs #lj/cut/tip4p/long 2 1 1 1 0.1546 13.0 Bond Coeffs #harmonic - 1 0.0 0.9572 + 1 1000 0.9572 Angle Coeffs #harmonic - 1 0.0 104.52 + 1 1000 104.52 Atoms diff --git a/mdgo/data/water/water_tip4p_ew.lmp b/mdgo/data/water/water_tip4p_ew.lmp index 4b079bae..a65b9343 100644 --- a/mdgo/data/water/water_tip4p_ew.lmp +++ b/mdgo/data/water/water_tip4p_ew.lmp @@ -1,5 +1,7 @@ Optimized TIP4P parameters to use with Ewald methods for long-range electrostatics. (e.g. pppm/tip4p 1.0e-5) # Original model from Horn et al, J Chem Phys 120: 9665 (2004). Command 'fix shake' is needed. +# Bond and angle coefficients of 1000 are added to keep the water molecule together +# during e.g. energy minimization in LAMMPS when `fix shake` is not active. 3 atoms 2 bonds @@ -25,11 +27,11 @@ Pair Coeffs #lj/cut/tip4p/long 2 1 1 1 0.125 10.0 Bond Coeffs #harmonic - 1 0.0 0.9572 + 1 1000 0.9572 Angle Coeffs #harmonic - 1 0.0 104.52 + 1 1000 104.52 Atoms diff --git a/mdgo/data/water/water_tip4p_fb.lmp b/mdgo/data/water/water_tip4p_fb.lmp index 4697d87d..ad2a7b63 100644 --- a/mdgo/data/water/water_tip4p_fb.lmp +++ b/mdgo/data/water/water_tip4p_fb.lmp @@ -4,6 +4,9 @@ Optimized TIP4P-FB parameters for water # https://pubs.acs.org/doi/10.1021/jz500737m # real units (kcal/mol, Angstrom) # Command 'fix shake' is needed. +# LJ and couloumb cutoffs of 9 and 7 angstroms were used in the original work +# Bond and angle coefficients of 1000 are added to keep the water molecule together +# during e.g. energy minimization in LAMMPS when `fix shake` is not active. 3 atoms 2 bonds @@ -29,11 +32,11 @@ Pair Coeffs #lj/cut/tip4p/long 2 1 1 1 0.10527 9.0 7.0 Bond Coeffs #harmonic - 1 0.0 0.9572 + 1 1000 0.9572 Angle Coeffs #harmonic - 1 0.0 104.52 + 1 1000 104.52 Atoms From b4569a8064e872c5fccb86cc5c0ab5b4f1ce160e Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Fri, 25 Jun 2021 10:50:19 -0700 Subject: [PATCH 11/55] fix typo in tip4p_fb water charge --- mdgo/data/water/water_tip4p_fb.lmp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mdgo/data/water/water_tip4p_fb.lmp b/mdgo/data/water/water_tip4p_fb.lmp index ad2a7b63..7ca4111c 100644 --- a/mdgo/data/water/water_tip4p_fb.lmp +++ b/mdgo/data/water/water_tip4p_fb.lmp @@ -40,7 +40,7 @@ Angle Coeffs #harmonic Atoms - 1 1 2 -1.05740 1.55000 1.55000 1.50000 + 1 1 2 -1.05174 1.55000 1.55000 1.50000 2 1 1 0.52587 1.55000 2.36649 2.07736 3 1 1 0.52587 1.55000 0.73351 2.07736 From 19d81dd3ddc834a37bf4ebe190b97d57364083b5 Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Fri, 16 Jul 2021 15:38:48 -0700 Subject: [PATCH 12/55] fix ion conversion mistake; add Na+ --- mdgo/data/ion/merz/tip4pfb/Cl-.lmp | 7 +++++-- mdgo/data/ion/merz/tip4pfb/Na+.lmp | 31 +++++++++++++++++++++++++++++ mdgo/data/ion/merz/tip4pfb/Zn++.lmp | 8 ++++++-- 3 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 mdgo/data/ion/merz/tip4pfb/Na+.lmp diff --git a/mdgo/data/ion/merz/tip4pfb/Cl-.lmp b/mdgo/data/ion/merz/tip4pfb/Cl-.lmp index 7af53b08..92d24e52 100644 --- a/mdgo/data/ion/merz/tip4pfb/Cl-.lmp +++ b/mdgo/data/ion/merz/tip4pfb/Cl-.lmp @@ -6,6 +6,9 @@ Cl- # the TIP4P-FB water model # all values in 'real' units (kcal/mol and Angstrom) +# Note that LAMMPS requires the value sigma (the distance at which the potential equals +# zero, rather than Rmin/2 which is reported in the paper. To convert, use +# sigma = Rmin/2 * 2^(5/6) 1 atoms @@ -19,9 +22,9 @@ Masses 1 35.453 -Pair Coeffs #lj/cut/coul/long +Pair Coeffs - 1 0.53486081 2.166 + 1 0.53486081 3.8594 Atoms diff --git a/mdgo/data/ion/merz/tip4pfb/Na+.lmp b/mdgo/data/ion/merz/tip4pfb/Na+.lmp new file mode 100644 index 00000000..ed4a062d --- /dev/null +++ b/mdgo/data/ion/merz/tip4pfb/Na+.lmp @@ -0,0 +1,31 @@ +Na+ +# Sengupta et al. Parameterization of Monovalent Ions for the OPC3, OPC, TIP3P-FB, and +# TIP4P-FB Water Models. J. Chem. Information Modeling 61(2), 2021. +# https://pubs.acs.org/doi/10.1021/acs.jcim.0c01390 +# This set of values is optimized for reproducing ion-oxygen distance (Table 3) using +# the TIP4P-FB water model +# all values in 'real' units (kcal/mol and Angstrom) + +# Note that LAMMPS requires the value sigma (the distance at which the potential equals +# zero, rather than Rmin/2 which is reported in the paper. To convert, use +# sigma = Rmin/2 * 2^(5/6) + + 1 atoms + + 1 atom types + + 0.0 1.0 xlo xhi + 0.0 1.0 ylo yhi + 0.0 1.0 zlo zhi + +Masses + + 1 22.9898 + +Pair Coeffs + + 1 0.02545423 2.5836 + +Atoms + + 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/merz/tip4pfb/Zn++.lmp b/mdgo/data/ion/merz/tip4pfb/Zn++.lmp index 279e11d8..c8c15eac 100644 --- a/mdgo/data/ion/merz/tip4pfb/Zn++.lmp +++ b/mdgo/data/ion/merz/tip4pfb/Zn++.lmp @@ -6,6 +6,10 @@ Zn++ # the TIP4P-FB water model # all values in 'real' units (kcal/mol and Angstrom) +# Note that LAMMPS requires the value sigma (the distance at which the potential equals +# zero, rather than Rmin/2 which is reported in the paper. To convert, use +# sigma = Rmin/2 * 2^(5/6) + 1 atoms 1 atom types @@ -18,9 +22,9 @@ Masses 1 64.929 -Pair Coeffs #lj/cut/coul/long +Pair Coeffs #lj/cut/tip4p/long 2 1 1 1 0.10527 9.0 7.0 - 1 0.01314367 1.383 + 1 0.01314367 2.4642 Atoms From 8e3a47d2f2b3b6ed56d7100c34d204c257095bab Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Wed, 21 Jul 2021 16:33:44 -0700 Subject: [PATCH 13/55] correct units of epsilon in tip4pfb; add tip3pfb reported as kJ/mol; need to convert to kcal/mol --- mdgo/data/water/water_tip3p_fb.lmp | 54 ++++++++++++++++++++++++++++++ mdgo/data/water/water_tip4p_fb.lmp | 2 +- 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 mdgo/data/water/water_tip3p_fb.lmp diff --git a/mdgo/data/water/water_tip3p_fb.lmp b/mdgo/data/water/water_tip3p_fb.lmp new file mode 100644 index 00000000..3f9f7776 --- /dev/null +++ b/mdgo/data/water/water_tip3p_fb.lmp @@ -0,0 +1,54 @@ +Optimized TIP3P-FB parameters for water +# Original model from Wang et al., Building Force Fields: An Automatic, +# Systematic, and Reproducible Approach, J. Phys. Chem. Letters 5(11), 2014. +# https://pubs.acs.org/doi/10.1021/jz500737m +# real units (kcal/mol, Angstrom) +# Command 'fix shake' is needed. +# LJ and couloumb cutoffs of 9 and 7 angstroms were used in the original work +# Bond and angle coefficients of 1000 are added to keep the water molecule together +# during e.g. energy minimization in LAMMPS when `fix shake` is not active. + + 3 atoms + 2 bonds + 1 angles + + 2 atom types + 1 bond types + 1 angle types + + 0.0 3.1 xlo xhi + 0.0 3.1 ylo yhi + 0.0 3.1 zlo zhi + +Masses + + 1 1.00794 + 2 15.9994 + +Pair Coeffs #lj/cut/coul/long 9.0 7.0 + + 1 0.000 0.000 + 2 0.15587 3.1780 + +Bond Coeffs #harmonic + + 1 1000 1.0118 + +Angle Coeffs #harmonic + + 1 1000 108.15 + +Atoms + + 1 1 2 -0.84844 1.55000 1.55000 1.50000 + 2 1 1 0.42422 1.55000 2.36649 2.07736 + 3 1 1 0.42422 1.55000 0.73351 2.07736 + +Bonds + + 1 1 1 2 + 2 1 1 3 + +Angles + + 1 1 2 1 3 diff --git a/mdgo/data/water/water_tip4p_fb.lmp b/mdgo/data/water/water_tip4p_fb.lmp index 7ca4111c..d5aee0a8 100644 --- a/mdgo/data/water/water_tip4p_fb.lmp +++ b/mdgo/data/water/water_tip4p_fb.lmp @@ -28,7 +28,7 @@ Masses Pair Coeffs #lj/cut/tip4p/long 2 1 1 1 0.10527 9.0 7.0 1 0.000 0.000 - 2 0.74928 3.1655 + 2 0.17908 3.1655 Bond Coeffs #harmonic From c789aab59f059d24fcceb5b0a07bf69d9718f394 Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Wed, 21 Jul 2021 17:15:16 -0700 Subject: [PATCH 14/55] overhaul ion parameter sets -Went back to original papers -checked and converted all values -cross-checked previous data entry -moved ion parameters into an .xlsx file instead of text files -reworked call signature of get_ion In the future it would be preferable to store the ion data as a .json instead of .xlsx. However pandas read_json does not support MultiIndex very well. --- docs/source/aqueous.rst | 136 ++++++++++++++++++++++++++++ mdgo/data/ion_lj_data.xlsx | Bin 0 -> 10920 bytes mdgo/forcefield.py | 179 ++++++++++++++++++++++++++----------- 3 files changed, 265 insertions(+), 50 deletions(-) create mode 100644 docs/source/aqueous.rst create mode 100644 mdgo/data/ion_lj_data.xlsx diff --git a/docs/source/aqueous.rst b/docs/source/aqueous.rst new file mode 100644 index 00000000..4dda720a --- /dev/null +++ b/docs/source/aqueous.rst @@ -0,0 +1,136 @@ + +================================ +Force Fields for Aqueous Systems +================================ + +The Aqueous module provides tools for setting up molecular dynamics simulations +involving water and ions. + +Water Models +============ + +`mdgo` contains parameters for several popular water models. This section lists +a brief description and literature reference to the available models. + +SPC +--- + +TIP3P-EW +-------- + +TIP3P-FB +-------- + +Wang, L., Martinez, T. J., Pande, V.S., Building Force Fields: An Automatic, Systematic, +and Reproducible Approach. J. Phys. Chem. Lett. 2014, 5, 11, 1885–1891. +https://pubs.acs.org/doi/abs/10.1021/jz500737m + +Parameters are given in Supporting Table 1. Note that the epsilon for Oxygen must be converted +from kJ/mol to kcal/mol. + +TIP4P-EW +-------- + +TIP4P-FB +-------- + +Wang, L., Martinez, T. J., Pande, V.S., Building Force Fields: An Automatic, Systematic, +and Reproducible Approach. J. Phys. Chem. Lett. 2014, 5, 11, 1885–1891. +https://pubs.acs.org/doi/abs/10.1021/jz500737m + +Parameters are given in Supporting Table 1. Note that the epsilon for Oxygen must be converted +from kJ/mol to kcal/mol. + +TIP4P-2005 +---------- + +OPC? +---- + +OPC3? +----- + + +Ion Parameter Sets +================== + +``mdgo`` contains a compilation of several sets of Lennard Jones +paramters for ions in water. All values are reported as :math:`\sigma_i` +and :math:`\epsilon_i` in the equation + +.. math:: + + E = 4 \\epsilon_i \\left[ \\left( \\frac{\sigma_i}{r} \\right)^{12} - \\left( \\frac{\sigma_i}{r} \\right)^{6} \\right] + +Values of :math:`\sigma_i` and :math:`\epsilon_i` are given in Angstrom +and kcal/mol, respectively, corresponding to the ‘real’ units system in +LAMMPS. + +Aqvist (aq) +----------- + +Aqvist, J. Ion-Water Interaction Potentials Derived from Free Energy +Perturbation Slmulations J. Phys. Chem. 1990, 94, 8021– 8024. +https://pubs.acs.org/doi/10.1021/j100384a009 + +Values were parameterized to the SPC water model and are reported in +Table I and II as :math:`A_i` and :math:`B_i` coefficients in the +following form of the Lennard-Jones potential: + +.. math:: + + + E = \left[ \left( \frac{A_i^2}{r} \right)^{12} - \left( \frac{B_i^2}{r} \right)^{6} \right] + +This parameter set is a work in progress! + +Jensen and Jorgensen (jj) +------------------------- + +Jensen, K. P. and Jorgensen, W. L., Halide, Ammonium, and Alkali Metal +Ion Parameters for Modeling Aqueous Solutions. J. Chem. Theory Comput. +2006, 2, 6, 1499–1509. https://pubs.acs.org/doi/abs/10.1021/ct600252r + +Values were parameterized to the TIP4P water model using geometric +combining rules and are reported directly as sigma_i and epsilon_i in +Table 2. + +Joung-Cheatham (jc) +------------------- + +Joung, and Thomas E. Cheatham, Thomas E. III, Determination of Alkali +and Halide Monovalent Ion Parameters for Use in Explicitly Solvated +Biomolecular Simulations. J. Phys. Chem. B 2008, 112, 30, 9020–9041. +https://pubs.acs.org/doi/10.1021/jp8001614 + +Values were parameterized for the SPC/E, TIP3P, and TIP4P_EW water +models using Lorentz-Berthelot combinging rules (LAMMPS: ‘arithmetic’) +and are reported in Table 5 as :math:`R_{min}`/2 and epsilon_i. R_min/2 +values are converted to :math:`\sigma_i` values using +:math:`\sigma_i = R_{min}/2 * 2^(5/6)` + +Li and Merz group (lm) +---------------------- + +Sengupta et al. Parameterization of Monovalent Ions for the OPC3, OPC, +TIP3P-FB, and TIP4P-FB Water Models. J. Chem. Information Modeling +61(2), 2021. https://pubs.acs.org/doi/10.1021/acs.jcim.0c01390 + +Li et al. Systematic Parametrization of Divalent Metal Ions for the +OPC3, OPC, TIP3P-FB, and TIP4P-FB Water Models. J. Chem. Theory and +Computation 16(7), 2020. +https://pubs.acs.org/doi/10.1021/acs.jctc.0c00194 + +Li et al. Parametrization of Trivalent and Tetravalent Metal Ions for +the OPC3, OPC, TIP3P-FB, and TIP4P-FB Water Models. J. Chem. Theory and +Computation 17(4), 2021. +https://pubs.acs.org/doi/10.1021/acs.jctc.0c01320 + +Values were parameterized for the OPC, OPC3, TIP3P-FB, and TIP4P-FB +water models using Lorentz-Berthelot combinging rules (LAMMPS: +‘arithmetic’) and are reported in Table 3 as :math:`R_{min}`/2 and +epsilon_i. R_min/2 values are converted to :math:`\sigma_i` values using +:math:`\sigma_i = R_{min}/2 * 2^(5/6)`. This set of values is optimized +for reproducing ion-oxygen distance. An alternate set of values optimized for +hydration free energies is available in the original papers. + diff --git a/mdgo/data/ion_lj_data.xlsx b/mdgo/data/ion_lj_data.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..a174b8cd038f1d46aafd8564de4e6a769981dd5d GIT binary patch literal 10920 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 literal 0 HcmV?d00001 diff --git a/mdgo/forcefield.py b/mdgo/forcefield.py index 86c7c955..34ddcc44 100644 --- a/mdgo/forcefield.py +++ b/mdgo/forcefield.py @@ -24,16 +24,19 @@ """ import time import os +import pandas as pd import re import shutil import signal import subprocess -from typing import Optional +from typing import Optional, Union from string import Template from urllib.parse import quote import numpy as np import pubchempy as pcp -from pymatgen.io.lammps.data import LammpsData +from pymatgen.core import Lattice, Structure +from pymatgen.core.ion import Ion +from pymatgen.io.lammps.data import LammpsData, ForceField, Topology, lattice_2_lmpbox from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait @@ -64,20 +67,11 @@ "spc": "water_spc.lmp", "spce": "water_spce.lmp", "tip3pew": "water_tip3p_ew.lmp", + "tip3pfb": "water_tip3p_fb.lmp", "tip4p2005": "water_tip4p_2005.lmp", "tip4pew": "water_tip4p_ew.lmp", - "tip4pfb": "water_tip4p_fb.lmp" + "tip4pfb": "water_tip4p_fb.lmp", }, - "ion": { - "aq": ["default"], - "aqvist": ["default"], - "jj": ["default"], - "jensen_jorgensen": ["default"], - "jc": ["spce", "tip3p", "tip4pew"], - "joung_cheatham": ["spce", "tip3p", "tip4pew"], - "merz": ["tip4pfb"], - }, - "alias": {"aq": "aqvist", "jj": "jensen_jorgensen", "jc": "joung_cheatham"}, } @@ -566,6 +560,22 @@ class Aqueous: """ A class for retreiving water and ion force field parameters. + Available water models are: + 1. SPC + 2. SPC/E + 3. TIP3P-EW + 4. TIP3P-FB + 5. TIP4P-EW + 6. TIP4P-2005 + 7. TIP4P-FB + + Multiple sets of Lennard Jones parameters for ions are available as well. + Not every set is available for every water model. The parameter sets included + are: + 1. Jensen and Jorgensen, 2006 (abbreviation 'jj') + 2. Joung and Cheatham, 2008 (abbreviation 'jc') + 3. Li and Merz group, 2020 (abbreviation, 'lm') + Examples: Retreive SPC/E water model: >>> spce_data = Aqueous.get_water() @@ -576,64 +586,133 @@ class Aqueous: """ @staticmethod - def get_water(model: str = "spce") -> Optional[LammpsData]: + def get_water(model: str = "spce") -> LammpsData: """ Retrieve water model parameters. Args: model: Water model to use. Valid choices are "spc", "spce", - "tip3pew", "tip4p2005", and "tip4pew". (Default: "spce") + "tip3pew", "tip3pfb", "tip4p2005", "tip4pew", and "tip4pfb". + (Default: "spce") Returns: LammpsData: Force field parameters for the chosen water model. If you specify an invalid water model, None is returned. """ - data_path = DATA_DIR signature = "".join(re.split(r"[\W|_]+", model)).lower() if DATA_MODELS["water"].get(signature): - return LammpsData.from_file(os.path.join(data_path, "water", DATA_MODELS["water"].get(signature))) - print("Water model not found. Please specify a customized data path or try another water model.\n") - return None + return LammpsData.from_file(os.path.join(DATA_DIR, "water", DATA_MODELS["water"].get(signature))) + raise ValueError("Water model not found. Please specify a customized data path or try another water model.\n") @staticmethod - def get_ion(model: str = "jensen_jorgensen", water: str = "default", ion: str = "li+") -> Optional[LammpsData]: + def get_ion( + ion: Union[Ion, str] = "li+", + water_model: str = "spce", + parameter_set: Optional[str] = None, + ) -> LammpsData: """ Retrieve force field parameters for an ion in water. Args: - model: Force field to use. Valid choices are "aqvist" (or "aq"), - "jensen_jorgensen" (or "jj"), ""joung_cheatham" (or "jc"). - water: Water model to use. For the jensen_jorgensen and aqvist - models, the only choice is 'default'. For the joung_cheatham - model, valid choices are "spce", "tip3p", and "tip4pew". - ion: Formula of the ion (e.g., "Li+"). + ion: Formula of the ion (e.g., "Li+"). Not case sensitive. May be + passed as either a string or an Ion object. + water_model: Water model to use. Models must be given as a string + (not case sensitive). "-" and "/" are ignored. Hence "tip3pfb" + and "TIP3P-FB" are both valid inputs for the TIP3P-FB water model. + Available water models are: + 1. SPC + 2. SPC/E + 3. TIP3P-EW + 4. TIP3P-FB + 5. TIP4P-EW + 6. TIP4P-2005 + 7. TIP4P-FB + The default water model is TIP4P-FB, the reparameterized TIP4P of + Wang, Martinez, and Pande (2014). See documentation. + parameter_set: Force field parameters to use for ions. + Valid choices are: + 1. "jj" for the Jensen and Jorgensen parameters (2006)" + 2. "jc" for Joung-Cheatham parameters (2008) + 3. "lm" for the Li and Merz group parameters (2020-2021)" + If None (default), then the parameter set is automatically set + to the recommended choice for the given water model. Recommended + choices are based on the water models originally used to parameterize + the ion parameters, but other combinations are possible at your own + risk. Returns: Force field parameters for the chosen water model. - If the desired combination of force field and water model - for the given ion is not available, None is returned. """ - data_path = DATA_DIR - alias = DATA_MODELS.get("alias", {}) - signature = model.lower() - if signature in alias: - signature = alias.get(model) - ion_type = ion.capitalize() - for key in DATA_MODELS["ion"]: - if key.startswith(signature): - ion_model = DATA_MODELS["ion"].get(key) - if water in ion_model: - if water == "default": - file_path = os.path.join(data_path, "ion", key, ion_type + ".lmp") - else: - file_path = os.path.join(data_path, "ion", key, water, ion_type + ".lmp") - if os.path.exists(file_path): - return LammpsData.from_file(file_path) - print("Ion not found. Please try another ion.\n") - return None - print("Water model not found. Please try another water model.\n") - return None - print("Ion model not found. Please try another ion model.\n") - return None + alias = {"aq": "aqvist", "jj": "jensen_jorgensen", "jc": "joung_cheatham", "lm": "li_merz"} + default_sets = { + "spc": None, + "spce": "jc", + "tip3p": "jc", + "tip3pew": None, + "tip3pfb": "lm", + "tip4p2005": None, + "tip4p": "jj", + "tip4pew": "jc", + "tip4pfb": "lm", + } + water_model = water_model.replace("-", "").replace("/", "").lower() + if parameter_set: + parameter_set = parameter_set.lower() + parameter_set = alias.get(parameter_set) + else: + parameter_set = default_sets.get(water_model) + + # Make the Ion object to get mass and charge + if isinstance(ion, Ion): + ion_obj = ion + else: + ion_obj = Ion.from_formula(ion.capitalize()) + + # load ion data + # ion_data = pd.read_json(os.path.join(DATA_DIR, "ion_lj_data.json")) + ion_data = pd.read_excel( + "/Users/ryan/miniconda3/envs/md/code/mdgo/mdgo/data/ion_lj_data.xlsx", header=[0, 1, 2], index_col=0 + ) + + # make sure the ion is in the DataFrame + key = ion_obj.reduced_formula + if key not in ion_data.index: + raise ValueError(f"Ion {key} not found in database. Please try a different ion.") + + # make sure the parameter set is in the DataFrame + key = ion_obj.reduced_formula + if parameter_set not in ion_data.columns.levels[0]: + raise ValueError( + f"Parameter set {parameter_set} not found in database. Please try a different parameter set." + ) + + # make sure the water model is in the DataFrame + key = ion_obj.reduced_formula + if water_model not in ion_data.columns.levels[1]: + raise ValueError(f"Water model {water_model} not found in database. Please try a different water model.") + + # we only consider monatomic ions at present + # construct a cubic LammpsBox from a lattice + lat = Lattice([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + box = lattice_2_lmpbox(lat)[0] + # put it in the center of a cubic Structure + struct = Structure(lat, ion_obj, [[0.5, 0.5, 0.5]]) + # construct Topology with the ion centered in the box + topo = Topology(struct, charges=[ion_obj.charge]) + + # retrieve Lennard-Jones parameters + # values may be np.nan if selected combination is not available + sigma = ion_data[parameter_set][water_model].loc[key, "σ (Å)"] + epsilon = ion_data[parameter_set][water_model].loc[key, "ε(kcal/mol)"] + if np.isfinite(sigma) and np.isfinite(epsilon): + # construct ForceField object + ff = ForceField([(str(e), e) for e in ion_obj.elements], nonbond_coeffs=[[epsilon, sigma]]) + + return LammpsData.from_ff_and_topologies(box, ff, [topo], atom_style="full") + + else: + raise ValueError( + f"No {parameter_set} ion parameters for water model {water_model}. See documentation and try a different combination." + ) class ChargeWriter: From 17057cd48ddadcaa8ab5d98c24a3d75cb64d37e8 Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Wed, 21 Jul 2021 17:22:36 -0700 Subject: [PATCH 15/55] organize imports --- mdgo/forcefield.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/mdgo/forcefield.py b/mdgo/forcefield.py index 34ddcc44..c78144c0 100644 --- a/mdgo/forcefield.py +++ b/mdgo/forcefield.py @@ -22,34 +22,34 @@ https://www.schrodinger.com/kb/1842 for details. """ -import time import os -import pandas as pd import re import shutil import signal import subprocess -from typing import Optional, Union +import time from string import Template +from typing import Optional, Union from urllib.parse import quote + import numpy as np +import pandas as pd import pubchempy as pcp from pymatgen.core import Lattice, Structure from pymatgen.core.ion import Ion -from pymatgen.io.lammps.data import LammpsData, ForceField, Topology, lattice_2_lmpbox +from pymatgen.io.lammps.data import ForceField, LammpsData, Topology, lattice_2_lmpbox from selenium import webdriver -from selenium.webdriver.common.by import By -from selenium.webdriver.support.ui import WebDriverWait -from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import ( - TimeoutException, NoSuchElementException, + TimeoutException, WebDriverException, ) +from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.ui import WebDriverWait from typing_extensions import Final -from mdgo.util import lmp_mass_to_name, ff_parser, sdf_to_pdb - +from mdgo.util import ff_parser, lmp_mass_to_name, sdf_to_pdb __author__ = "Tingzheng Hou" __version__ = "1.0" From 33b8d7002e4fbc0fe20f929e490bccc4d3c312aa Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Tue, 12 Oct 2021 22:45:49 -0700 Subject: [PATCH 16/55] linting --- mdgo/forcefield.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mdgo/forcefield.py b/mdgo/forcefield.py index c78144c0..0faabc5e 100644 --- a/mdgo/forcefield.py +++ b/mdgo/forcefield.py @@ -657,9 +657,9 @@ def get_ion( water_model = water_model.replace("-", "").replace("/", "").lower() if parameter_set: parameter_set = parameter_set.lower() - parameter_set = alias.get(parameter_set) else: parameter_set = default_sets.get(water_model) + parameter_set = alias.get(parameter_set) # Make the Ion object to get mass and charge if isinstance(ion, Ion): @@ -709,10 +709,10 @@ def get_ion( return LammpsData.from_ff_and_topologies(box, ff, [topo], atom_style="full") - else: - raise ValueError( - f"No {parameter_set} ion parameters for water model {water_model}. See documentation and try a different combination." - ) + raise ValueError( + f"No {parameter_set} ion parameters for water model {water_model}. " + "See documentation and try a different combination." + ) class ChargeWriter: From 9f6632a0331d52fe732820335ce2a54768679bb2 Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Tue, 12 Oct 2021 22:35:00 -0700 Subject: [PATCH 17/55] Packmol: overhaul and add tests --- mdgo/mdgopackmol.py | 156 +++++++++++++++++-------- tests/test_mdgopackmol.py | 232 +++++++++++++++++++++++++++++++++++++- 2 files changed, 332 insertions(+), 56 deletions(-) diff --git a/mdgo/mdgopackmol.py b/mdgo/mdgopackmol.py index 51ee0c04..a53c0c2a 100644 --- a/mdgo/mdgopackmol.py +++ b/mdgo/mdgopackmol.py @@ -13,21 +13,26 @@ set the folder of the packmol executable to the PATH environment variable. """ -import subprocess import os +import subprocess +from pathlib import Path +from typing import Dict, List, Optional, Union + +from pymatgen.core import Molecule -# import tempfile -from typing import Optional, List, Dict +# from pymatgen.io.core import InputFile, InputSet, InputGenerator -# from subprocess import PIPE, Popen +from mdgo.volume import molecular_volume -__author__ = "Tingzheng Hou" +__author__ = "Tingzheng Hou, Ryan Kingsbury" __version__ = "1.0" __maintainer__ = "Tingzheng Hou" __email__ = "tingzheng_hou@berkeley.edu" -__date__ = "Feb 9, 2021" +__date__ = "Feb - Oct, 2021" +# TODO - inherit from InputSet +# consider adding a generator class PackmolWrapper: """ Wrapper for the Packmol software that can be used to pack various types of @@ -35,10 +40,11 @@ class PackmolWrapper: Examples: - >>> structures = [{"name": "structure_name", "file": "/path/to/xyz"}] + >>> molecules = [{"name": "EMC", + "number": 2, + "coords": "/Users/th/Downloads/test_selenium/EMC.lmp.xyz"}] >>> pw = PackmolWrapper("/path/to/work/dir", - ... structures, - ... {"structure_name": 2}, + ... molecules, ... [0., 0., 0., 10., 10., 10.] ... ) >>> pw.make_packmol_input() @@ -48,31 +54,34 @@ class PackmolWrapper: def __init__( self, path: str, - structures: List[dict], - numbers: Dict[str, int], - box: List[float], - tolerance: Optional[float] = 2.0, - seed: Optional[int] = 1, - inputfile: str = "packmol.inp", - outputfile: str = "output.xyz", + molecules: List[Dict], + box: Optional[List[float]] = None, + tolerance: float = 2.0, + seed: int = 1, + control_params: Optional[Dict] = None, + inputfile: Union[str, Path] = "packmol.inp", + outputfile: Union[str, Path] = "packmol_out.xyz", ): """ Args: path: The path to the directory for file i/o. Note that the path cannot contain any spaces. - structures: A list of dict containing information about molecules. - Each dict requires two keys, "name", the structure name, - and "file", the path to the structure file, e.g. - {"name": "water", - "file": "/path/to/water.xyz"} - numbers: A dict of the numbers of each molecule. Each dict must have - keys corresponding to 'name' keys in 'structures', and integer - values representing the number of that molecule to pack into the - box, e.g. - {"water": 20} - box: A list of xlo, ylo, zlo, xhi, yhi, zhi, in Å. - tolerance: Tolerance for packmol. - seed: Random seed for packmol. + molecules: A list of dict containing information about molecules to pack + into the box. Each dict requires three keys: + 1. "name" - the structure name + 2. "number" - the number of that molecule to pack into the box + 3. "coords" - Coordinates in the form of either a Molecule object or + a path to a file. + Example: + {"name": "water", + "number": 500, + "coords": "/path/to/input/file.xyz"} + box: A list of box dimensions xlo, ylo, zlo, xhi, yhi, zhi, in Å. If set to None + (default), mdgo will estimate the required box size based on the volumes of + the provided molecules using mdgo.volume.molecular_volume() + tolerance: Tolerance for packmol, in Å. + seed: Random seed for packmol. Use a value of 1 (default) for deterministic + output, or -1 to generate a new random seed from the current time. inputfile: Path to the input file. Default to 'packmol.inp'. outputfile: Path to the output file. Default to 'output.xyz'. """ @@ -80,58 +89,105 @@ def __init__( self.input = os.path.join(self.path, inputfile) self.output = os.path.join(self.path, outputfile) self.screen = os.path.join(self.path, "packmol.stdout") - self.structures = structures - self.numbers = numbers + self.molecules = molecules + self.control_params = control_params if control_params else {} self.box = box self.tolerance = tolerance self.seed = seed - def run_packmol(self): - """Run packmol and write out the packed structure.""" + def run_packmol(self, timeout=30): + """Run packmol and write out the packed structure. + Args: + timeout: Timeout in seconds. + Raises: + ValueError if packmol does not succeed in packing the box. + TimeoutExpiredError if packmold does not finish within the timeout. + """ try: p = subprocess.run( "packmol < '{}'".format(self.input), check=True, shell=True, + timeout=timeout, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) + # this workaround is needed because packmol can fail to find + # a solution but still return a zero exit code + # see https://github.com/m3g/packmol/issues/28 + if "ERROR" in p.stdout.decode(): + msg = p.stdout.decode().split("ERROR")[-1] + raise ValueError(f"Packmol failed with return code 0 and stdout: {msg}") except subprocess.CalledProcessError as e: raise ValueError("Packmol failed with errorcode {} and stderr: {}".format(e.returncode, e.stderr)) from e else: with open(self.screen, "w") as out: out.write(p.stdout.decode()) + # TODO - should be in InputSet.get_inputs() or Inputfile.get_string() + # maybe don't define an Inputfile class, just keep internal to + # InputSet def make_packmol_input(self): """Make a Packmol usable input file.""" + if self.box: + box_list = " ".join(str(i) for i in self.box) + else: + # estimate the total volume of all molecules + net_volume = 0.0 + for idx, d in enumerate(self.molecules): + if not isinstance(d["coords"], Molecule): + mol = Molecule.from_file(d["coords"]) + else: + mol = d["coords"] + # molecular volume in cubic Å + vol = molecular_volume(mol, radii_type="pymatgen", molar_volume=False) + # pad the calculated length by an amount related to the tolerance parameter + # the amount to add was determined arbitrarily + vol *= self.tolerance + net_volume += vol * d["number"] + + box_length = net_volume ** (1.0 / 3.0) + print(f"Auto determined box size is {box_length:.1f} Å per side.") + box_list = "0.0 0.0 0.0 {:.1f} {:.1f} {:.1f}".format(box_length, box_length, box_length) + with open(self.input, "w") as out: - out.write( - "# " - + " + ".join( - str(self.numbers[structure["name"]]) + " " + structure["name"] for structure in self.structures - ) - + "\n" - ) + out.write("# " + " + ".join(str(d["number"]) + " " + d["name"] for d in self.molecules) + "\n") out.write("# Packmol input generated by mdgo.\n") + for k, v in self.control_params.items(): + if isinstance(v, list): + out.write("{} {}\n".format(k, " ".join(str(x) for x in v))) + else: + out.write("{} {}\n".format(k, str(v))) out.write("seed {}\n".format(self.seed)) out.write("tolerance {}\n\n".format(self.tolerance)) - out.write("filetype xyz\n\n") - out.write("output {}\n\n".format(self.output)) - for structure in self.structures: - out.write("structure {}\n".format(structure["file"])) - out.write(" number {}\n".format(str(self.numbers[structure["name"]]))) - out.write(" inside box {}\n".format(" ".join(str(i) for i in self.box))) + out.write("filetype xyz\n\n") + # NOTE - output filename MUST be enclosed in double quotes in order to work + # when there are spaces in the filename. Single quotes will not work. + out.write(f'output "{self.output}"\n\n') + + for i, d in enumerate(self.molecules): + if isinstance(d["coords"], str): + out.write("structure {}\n".format(d["coords"])) + elif isinstance(d["coords"], Path): + out.write(f'structure "{str(d["coords"])}"\n') + elif isinstance(d["coords"], Molecule): + fname = os.path.join(self.path, f"packmol_{d['name']}.xyz") + d["coords"].to(filename=fname) + out.write(f'structure "{fname}"\n') + out.write(" number {}\n".format(str(d["number"]))) + out.write(" inside box {}\n".format(box_list)) out.write("end structure\n\n") if __name__ == "__main__": """ - structures = [{"name": "EMC", - "file": "/Users/th/Downloads/test_selenium/EMC.lmp.xyz"}] - pw = PackmolWrapper("/Users/th/Downloads/test_selenium/", structures, - {"EMC": '2'}, [0., 0., 0., 10., 10., 10.]) + molecules = [{"name": "EMC", + "number": 2, + "coords": "/Users/th/Downloads/test_selenium/EMC.lmp.xyz"}] + pw = PackmolWrapper("/Users/th/Downloads/test_selenium/", molecules, + [0., 0., 0., 10., 10., 10.]) pw.make_packmol_input() pw.run_packmol() """ diff --git a/tests/test_mdgopackmol.py b/tests/test_mdgopackmol.py index d6cfbef8..770e62f7 100644 --- a/tests/test_mdgopackmol.py +++ b/tests/test_mdgopackmol.py @@ -1,11 +1,231 @@ import os -import unittest +import tempfile +from pathlib import Path +from subprocess import TimeoutExpired +import pytest +from pymatgen.analysis.molecule_matcher import MoleculeMatcher +from pymatgen.core import Molecule -class MyTestCase(unittest.TestCase): - def test_something(self): - self.assertEqual(True, True) +from mdgo.mdgopackmol import PackmolWrapper +test_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "test_files") -if __name__ == "__main__": - unittest.main() + +@pytest.fixture +def ethanol(): + """ + Returns a Molecule of ethanol + """ + ethanol_coords = [ + [0.00720, -0.56870, 0.00000], + [-1.28540, 0.24990, 0.00000], + [1.13040, 0.31470, 0.00000], + [0.03920, -1.19720, 0.89000], + [0.03920, -1.19720, -0.89000], + [-1.31750, 0.87840, 0.89000], + [-1.31750, 0.87840, -0.89000], + [-2.14220, -0.42390, -0.00000], + [1.98570, -0.13650, -0.00000], + ] + ethanol_atoms = ["C", "C", "O", "H", "H", "H", "H", "H", "H"] + + return Molecule(ethanol_atoms, ethanol_coords) + + +@pytest.fixture +def water(): + """ + Returns a Molecule of water + """ + water_coords = [ + [9.626, 6.787, 12.673], + [9.626, 8.420, 12.673], + [10.203, 7.604, 12.673], + ] + water_atoms = ["H", "H", "O"] + + return Molecule(water_atoms, water_coords) + + +class TestPackmolWrapper: + def test_packmol_with_molecule(self, water, ethanol): + """ + Test coords input as Molecule + """ + with tempfile.TemporaryDirectory() as scratch_dir: + pw = PackmolWrapper( + scratch_dir, + molecules=[ + {"name": "water", "number": 10, "coords": water}, + {"name": "ethanol", "number": 20, "coords": ethanol}, + ], + ) + pw.make_packmol_input() + pw.run_packmol() + assert os.path.exists(os.path.join(scratch_dir, "packmol_out.xyz")) + out = Molecule.from_file(os.path.join(scratch_dir, "packmol_out.xyz")) + assert out.composition.num_atoms == 10 * 3 + 20 * 9 + + def test_packmol_with_str(self): + """ + Test coords input as strings + """ + with tempfile.TemporaryDirectory() as scratch_dir: + pw = PackmolWrapper( + scratch_dir, + molecules=[ + {"name": "EMC", "number": 10, "coords": os.path.join(test_dir, "EMC.xyz")}, + {"name": "LiTFSi", "number": 20, "coords": os.path.join(test_dir, "LiTFSi.xyz")}, + ], + ) + pw.make_packmol_input() + pw.run_packmol() + assert os.path.exists(os.path.join(scratch_dir, "packmol_out.xyz")) + out = Molecule.from_file(os.path.join(scratch_dir, "packmol_out.xyz")) + assert out.composition.num_atoms == 10 * 15 + 20 * 16 + + def test_packmol_with_path(self): + """ + Test coords input as Path + """ + p1 = Path(os.path.join(test_dir, "EMC.xyz")) + p2 = Path(os.path.join(test_dir, "LiTFSi.xyz")) + with tempfile.TemporaryDirectory() as scratch_dir: + pw = PackmolWrapper( + scratch_dir, + molecules=[ + {"name": "EMC", "number": 10, "coords": p1}, + {"name": "LiTFSi", "number": 20, "coords": p2}, + ], + ) + pw.make_packmol_input() + pw.run_packmol() + assert os.path.exists(os.path.join(scratch_dir, "packmol_out.xyz")) + out = Molecule.from_file(os.path.join(scratch_dir, "packmol_out.xyz")) + assert out.composition.num_atoms == 10 * 15 + 20 * 16 + + def test_control_params(self, water, ethanol): + """ + Check that custom control_params work and that ValueError + is raised when 'ERROR' appears in stdout (even if return code is 0) + """ + with tempfile.TemporaryDirectory() as scratch_dir: + pw = PackmolWrapper( + scratch_dir, + molecules=[ + {"name": "water", "number": 1000, "coords": water}, + {"name": "ethanol", "number": 2000, "coords": ethanol}, + ], + control_params={"maxit": 0, "nloop": 0}, + ) + pw.make_packmol_input() + with open(os.path.join(scratch_dir, "packmol.inp"), "r") as f: + input_string = f.read() + assert "maxit 0" in input_string + assert "nloop 0" in input_string + with pytest.raises(ValueError): + pw.run_packmol() + + def test_timeout(self, water, ethanol): + """ + Check that the timeout works + """ + with tempfile.TemporaryDirectory() as scratch_dir: + pw = PackmolWrapper( + scratch_dir, + molecules=[ + {"name": "water", "number": 1000, "coords": water}, + {"name": "ethanol", "number": 2000, "coords": ethanol}, + ], + ) + pw.make_packmol_input() + with pytest.raises(TimeoutExpired): + pw.run_packmol(1) + + def test_no_return_and_box(self, water, ethanol): + """ + Make sure the code raises an error if packmol doesn't + exit cleanly. Also verify the box arg works properly. + """ + with tempfile.TemporaryDirectory() as scratch_dir: + pw = PackmolWrapper( + scratch_dir, + molecules=[ + {"name": "water", "number": 1000, "coords": water}, + {"name": "ethanol", "number": 2000, "coords": ethanol}, + ], + box=[0, 0, 0, 2, 2, 2], + ) + pw.make_packmol_input() + with open(os.path.join(scratch_dir, "packmol.inp"), "r") as f: + input_string = f.read() + assert "inside box 0 0 0 2 2 2" in input_string + with pytest.raises(ValueError): + pw.run_packmol() + + def test_random_seed(self, water, ethanol): + """ + Confirm that seed = -1 generates random structures + while seed = 1 is deterministic + """ + mm = MoleculeMatcher() + + # deterministic output + with tempfile.TemporaryDirectory() as scratch_dir: + pw = PackmolWrapper( + scratch_dir, + molecules=[ + {"name": "water", "number": 10, "coords": water}, + {"name": "ethanol", "number": 20, "coords": ethanol}, + ], + seed=1, + inputfile="input.in", + outputfile="output.xyz", + ) + pw.make_packmol_input() + pw.run_packmol() + out1 = Molecule.from_file(os.path.join(scratch_dir, "output.xyz")) + pw.run_packmol() + out2 = Molecule.from_file(os.path.join(scratch_dir, "output.xyz")) + assert mm.fit(out1, out2) + + # randomly generated structures + with tempfile.TemporaryDirectory() as scratch_dir: + pw = PackmolWrapper( + scratch_dir, + molecules=[ + {"name": "water", "number": 10, "coords": water}, + {"name": "ethanol", "number": 20, "coords": ethanol}, + ], + seed=-1, + inputfile="input.in", + outputfile="output.xyz", + ) + pw.make_packmol_input() + pw.run_packmol() + out1 = Molecule.from_file(os.path.join(scratch_dir, "output.xyz")) + pw.run_packmol() + out2 = Molecule.from_file(os.path.join(scratch_dir, "output.xyz")) + assert not mm.fit(out1, out2) + + def test_arbitrary_filenames(self, water, ethanol): + """ + Make sure custom input and output filenames work + """ + with tempfile.TemporaryDirectory() as scratch_dir: + pw = PackmolWrapper( + scratch_dir, + molecules=[ + {"name": "water", "number": 10, "coords": water}, + {"name": "ethanol", "number": 20, "coords": ethanol}, + ], + inputfile="input.in", + outputfile="output.xyz", + ) + pw.make_packmol_input() + assert os.path.exists(os.path.join(scratch_dir, "input.in")) + pw.run_packmol() + assert os.path.exists(os.path.join(scratch_dir, "output.xyz")) + out = Molecule.from_file(os.path.join(scratch_dir, "output.xyz")) + assert out.composition.num_atoms == 10 * 3 + 20 * 9 From 770e805eab6c32ed674cd6feb8e5184a77daaf46 Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Wed, 13 Oct 2021 09:50:28 -0700 Subject: [PATCH 18/55] add'l tests and fix for spaces in path name --- mdgo/mdgopackmol.py | 2 +- tests/test_mdgopackmol.py | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/mdgo/mdgopackmol.py b/mdgo/mdgopackmol.py index a53c0c2a..2b44dea3 100644 --- a/mdgo/mdgopackmol.py +++ b/mdgo/mdgopackmol.py @@ -169,7 +169,7 @@ def make_packmol_input(self): for i, d in enumerate(self.molecules): if isinstance(d["coords"], str): - out.write("structure {}\n".format(d["coords"])) + out.write(f'structure "{d["coords"]}"\n') elif isinstance(d["coords"], Path): out.write(f'structure "{str(d["coords"])}"\n') elif isinstance(d["coords"], Molecule): diff --git a/tests/test_mdgopackmol.py b/tests/test_mdgopackmol.py index 770e62f7..d2627505 100644 --- a/tests/test_mdgopackmol.py +++ b/tests/test_mdgopackmol.py @@ -75,7 +75,7 @@ def test_packmol_with_str(self): pw = PackmolWrapper( scratch_dir, molecules=[ - {"name": "EMC", "number": 10, "coords": os.path.join(test_dir, "EMC.xyz")}, + {"name": "EMC", "number": 10, "coords": os.path.join(test_dir, "subdir with spaces", "EMC.xyz")}, {"name": "LiTFSi", "number": 20, "coords": os.path.join(test_dir, "LiTFSi.xyz")}, ], ) @@ -87,9 +87,9 @@ def test_packmol_with_str(self): def test_packmol_with_path(self): """ - Test coords input as Path + Test coords input as Path. Use a subdirectory with spaces. """ - p1 = Path(os.path.join(test_dir, "EMC.xyz")) + p1 = Path(os.path.join(test_dir, "subdir with spaces", "EMC.xyz")) p2 = Path(os.path.join(test_dir, "LiTFSi.xyz")) with tempfile.TemporaryDirectory() as scratch_dir: pw = PackmolWrapper( @@ -211,11 +211,13 @@ def test_random_seed(self, water, ethanol): def test_arbitrary_filenames(self, water, ethanol): """ - Make sure custom input and output filenames work + Make sure custom input and output filenames work. + Use a subdirectory with spaces. """ with tempfile.TemporaryDirectory() as scratch_dir: + os.mkdir(os.path.join(scratch_dir, "subdirectory with spaces")) pw = PackmolWrapper( - scratch_dir, + os.path.join(scratch_dir, "subdirectory with spaces"), molecules=[ {"name": "water", "number": 10, "coords": water}, {"name": "ethanol", "number": 20, "coords": ethanol}, @@ -224,8 +226,8 @@ def test_arbitrary_filenames(self, water, ethanol): outputfile="output.xyz", ) pw.make_packmol_input() - assert os.path.exists(os.path.join(scratch_dir, "input.in")) + assert os.path.exists(os.path.join(scratch_dir, "subdirectory with spaces", "input.in")) pw.run_packmol() - assert os.path.exists(os.path.join(scratch_dir, "output.xyz")) - out = Molecule.from_file(os.path.join(scratch_dir, "output.xyz")) + assert os.path.exists(os.path.join(scratch_dir, "subdirectory with spaces", "output.xyz")) + out = Molecule.from_file(os.path.join(scratch_dir, "subdirectory with spaces", "output.xyz")) assert out.composition.num_atoms == 10 * 3 + 20 * 9 From f5a0f4a980474bab4517ea68513f674ffd2f8934 Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Wed, 13 Oct 2021 10:01:12 -0700 Subject: [PATCH 19/55] add info message if packmol not installed --- mdgo/mdgopackmol.py | 9 +++++++++ tests/test_files/subdir with spaces/EMC.xyz | 17 +++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/test_files/subdir with spaces/EMC.xyz diff --git a/mdgo/mdgopackmol.py b/mdgo/mdgopackmol.py index 2b44dea3..400bb122 100644 --- a/mdgo/mdgopackmol.py +++ b/mdgo/mdgopackmol.py @@ -19,6 +19,7 @@ from typing import Dict, List, Optional, Union from pymatgen.core import Molecule +from monty.os.path import which # from pymatgen.io.core import InputFile, InputSet, InputGenerator @@ -103,6 +104,14 @@ def run_packmol(self, timeout=30): ValueError if packmol does not succeed in packing the box. TimeoutExpiredError if packmold does not finish within the timeout. """ + if not which("packmol"): + raise RuntimeError( + "PackmolWrapper requires the executable 'packmol' to be in " + "the path. Please download packmol from " + "https://github.com/leandromartinez98/packmol " + "and follow the instructions in the README to compile. " + "Don't forget to add the packmol binary to your path" + ) try: p = subprocess.run( "packmol < '{}'".format(self.input), diff --git a/tests/test_files/subdir with spaces/EMC.xyz b/tests/test_files/subdir with spaces/EMC.xyz new file mode 100644 index 00000000..758aab5f --- /dev/null +++ b/tests/test_files/subdir with spaces/EMC.xyz @@ -0,0 +1,17 @@ +15 + +C 0.18700 -1.22900 -0.00000 +O 1.37700 -1.84500 -0.00000 +O -0.76900 -2.17300 -0.00000 +O 0.00000 -0.03100 -0.00100 +C 2.53300 -0.96600 -0.00000 +C -2.11800 -1.66800 -0.00000 +C 3.76700 -1.84400 -0.00000 +H 2.48200 -0.32400 -0.88900 +H 2.48200 -0.32300 0.88800 +H -2.29900 -1.06000 0.89400 +H -2.75500 -2.55600 -0.00000 +H -2.29900 -1.06100 -0.89600 +H 4.66400 -1.20900 -0.00000 +H 3.79600 -2.48400 0.89100 +H 3.79600 -2.48400 -0.89200 From bda0f73ecc242f5cdeec4ed0bfccfaac0e703cb4 Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Wed, 27 Oct 2021 13:25:48 -0700 Subject: [PATCH 20/55] add OPC and OPC3 water models --- docs/source/aqueous.rst | 28 +++++++++++++---- mdgo/data/water/water_opc.lmp | 55 ++++++++++++++++++++++++++++++++++ mdgo/data/water/water_opc3.lmp | 53 ++++++++++++++++++++++++++++++++ mdgo/forcefield.py | 36 +++++++++++++++------- 4 files changed, 155 insertions(+), 17 deletions(-) create mode 100644 mdgo/data/water/water_opc.lmp create mode 100644 mdgo/data/water/water_opc3.lmp diff --git a/docs/source/aqueous.rst b/docs/source/aqueous.rst index 4dda720a..b5ccc760 100644 --- a/docs/source/aqueous.rst +++ b/docs/source/aqueous.rst @@ -31,6 +31,8 @@ from kJ/mol to kcal/mol. TIP4P-EW -------- +[Vega & de Miguel, J Chem Phys 126:154707 (2007), Vega et al, Faraday Discuss 141:251 (2009)]. + TIP4P-FB -------- @@ -38,17 +40,31 @@ Wang, L., Martinez, T. J., Pande, V.S., Building Force Fields: An Automatic, Sys and Reproducible Approach. J. Phys. Chem. Lett. 2014, 5, 11, 1885–1891. https://pubs.acs.org/doi/abs/10.1021/jz500737m -Parameters are given in Supporting Table 1. Note that the epsilon for Oxygen must be converted +Parameters are given in Supporting Table 1. Note that the epsilon for oxygen must be converted from kJ/mol to kcal/mol. TIP4P-2005 ---------- -OPC? +Abascal & Vega, J Chem Phys 123:234505 (2005) + +OPC +---- + +Izadi, Anandakrishnan, and Onufriev, Building Water Models: A Different Approach. +J. Phys. Chem. Lett. 2014, 5, 21, 3863–3871 https://doi.org/10.1021/jz501780a + +Parameters are given in Table 2. Note that the epsilon for oxygen must be converted +from kJ/mol to kcal/mol. + +OPC3 ---- -OPC3? ------ +Izadi and Onufriev, Accuracy limit of rigid 3-point water models +J. Chemical Physics 145, 074501, 2016. https://doi.org/10.1063/1.4960175 + +Parameters are given in Table II. Note that the epsilon for oxygen must be converted +from kJ/mol to kcal/mol. Ion Parameter Sets @@ -104,7 +120,7 @@ Biomolecular Simulations. J. Phys. Chem. B 2008, 112, 30, 9020–9041. https://pubs.acs.org/doi/10.1021/jp8001614 Values were parameterized for the SPC/E, TIP3P, and TIP4P_EW water -models using Lorentz-Berthelot combinging rules (LAMMPS: ‘arithmetic’) +models using Lorentz-Berthelot combining rules (LAMMPS: ‘arithmetic’) and are reported in Table 5 as :math:`R_{min}`/2 and epsilon_i. R_min/2 values are converted to :math:`\sigma_i` values using :math:`\sigma_i = R_{min}/2 * 2^(5/6)` @@ -127,7 +143,7 @@ Computation 17(4), 2021. https://pubs.acs.org/doi/10.1021/acs.jctc.0c01320 Values were parameterized for the OPC, OPC3, TIP3P-FB, and TIP4P-FB -water models using Lorentz-Berthelot combinging rules (LAMMPS: +water models using Lorentz-Berthelot combining rules (LAMMPS: ‘arithmetic’) and are reported in Table 3 as :math:`R_{min}`/2 and epsilon_i. R_min/2 values are converted to :math:`\sigma_i` values using :math:`\sigma_i = R_{min}/2 * 2^(5/6)`. This set of values is optimized diff --git a/mdgo/data/water/water_opc.lmp b/mdgo/data/water/water_opc.lmp new file mode 100644 index 00000000..dc5f34fd --- /dev/null +++ b/mdgo/data/water/water_opc.lmp @@ -0,0 +1,55 @@ +OPC3 water model +# Original model from Izadi, Anandakrishnan, and Onufriev, Building Water Models: +# A Different Approach. J. Phys. Chem. Lett. 2014, 5, 21, 3863–3871 +# https://doi.org/10.1021/jz501780a +# Table 2. +# real units (kcal/mol, Angstrom) +# Command 'fix shake' is needed. +# LJ and couloumb cutoffs of 9 and 7 angstroms are adopted from the TIP3B-FB paper +# Bond and angle coefficients of 1000 are added to keep the water molecule together +# during e.g. energy minimization in LAMMPS when `fix shake` is not active. + + 3 atoms + 2 bonds + 1 angles + + 2 atom types + 1 bond types + 1 angle types + + 0.0 3.1 xlo xhi + 0.0 3.1 ylo yhi + 0.0 3.1 zlo zhi + +Masses + + 1 1.00794 + 2 15.9994 + +Pair Coeffs #lj/cut/tip4p/long 2 1 1 1 0.1594 9.0 7.0 + + 1 0.0000 0.0000 + 2 0.21280 3.16655 + +Bond Coeffs #harmonic + + 1 1000 0.8724 + +Angle Coeffs #harmonic + + 1 1000 103.6 + +Atoms + + 1 1 2 -1.3582 1.55000 1.55000 1.50000 + 2 1 1 0.6791 1.55000 2.36649 2.07736 + 3 1 1 0.6791 1.55000 0.73351 2.07736 + +Bonds + + 1 1 1 2 + 2 1 1 3 + +Angles + + 1 1 2 1 3 diff --git a/mdgo/data/water/water_opc3.lmp b/mdgo/data/water/water_opc3.lmp new file mode 100644 index 00000000..5ff74ba1 --- /dev/null +++ b/mdgo/data/water/water_opc3.lmp @@ -0,0 +1,53 @@ +OPC3 water model +# Original model from Izadi and Onufriev, Accuracy limit of rigid 3-point water models +# J. Chemical Physics 145, 074501, 2016. https://doi.org/10.1063/1.4960175, Table II. +# real units (kcal/mol, Angstrom) +# Command 'fix shake' is needed. +# LJ and couloumb cutoffs of 9 and 7 angstroms are adopted from the TIP3B-FB paper +# Bond and angle coefficients of 1000 are added to keep the water molecule together +# during e.g. energy minimization in LAMMPS when `fix shake` is not active. + + 3 atoms + 2 bonds + 1 angles + + 2 atom types + 1 bond types + 1 angle types + + 0.0 3.1 xlo xhi + 0.0 3.1 ylo yhi + 0.0 3.1 zlo zhi + +Masses + + 1 1.00794 + 2 15.9994 + +Pair Coeffs #lj/cut/coul/long 9.0 7.0 + + 1 0.000 0.000 + 2 0.16340 3.17427 + +Bond Coeffs #harmonic + + 1 1000 0.97888 + +Angle Coeffs #harmonic + + 1 1000 109.47 + +Atoms + + 1 1 2 -0.89517 1.55000 1.55000 1.50000 + 2 1 1 0.447585 1.55000 2.36649 2.07736 + 3 1 1 0.447585 1.55000 0.73351 2.07736 + +Bonds + + 1 1 1 2 + 2 1 1 3 + +Angles + + 1 1 2 1 3 diff --git a/mdgo/forcefield.py b/mdgo/forcefield.py index 0faabc5e..804ebd07 100644 --- a/mdgo/forcefield.py +++ b/mdgo/forcefield.py @@ -68,9 +68,11 @@ "spce": "water_spce.lmp", "tip3pew": "water_tip3p_ew.lmp", "tip3pfb": "water_tip3p_fb.lmp", + "opc3": "water_opc3.lmp", "tip4p2005": "water_tip4p_2005.lmp", "tip4pew": "water_tip4p_ew.lmp", "tip4pfb": "water_tip4p_fb.lmp", + "opc": "water_opc.lmp", }, } @@ -565,9 +567,11 @@ class Aqueous: 2. SPC/E 3. TIP3P-EW 4. TIP3P-FB - 5. TIP4P-EW - 6. TIP4P-2005 - 7. TIP4P-FB + 5. OPC3 + 6. TIP4P-EW + 7. TIP4P-2005 + 8. TIP4P-FB + 9. OPC Multiple sets of Lennard Jones parameters for ions are available as well. Not every set is available for every water model. The parameter sets included @@ -591,8 +595,8 @@ def get_water(model: str = "spce") -> LammpsData: Retrieve water model parameters. Args: - model: Water model to use. Valid choices are "spc", "spce", - "tip3pew", "tip3pfb", "tip4p2005", "tip4pew", and "tip4pfb". + model: Water model to use. Valid choices are "spc", "spce", "opc3", + "tip3pew", "tip3pfb", "tip4p2005", "tip4pew", "tip4pfb", and "opc". (Default: "spce") Returns: LammpsData: Force field parameters for the chosen water model. @@ -623,11 +627,19 @@ def get_ion( 2. SPC/E 3. TIP3P-EW 4. TIP3P-FB - 5. TIP4P-EW - 6. TIP4P-2005 - 7. TIP4P-FB - The default water model is TIP4P-FB, the reparameterized TIP4P of - Wang, Martinez, and Pande (2014). See documentation. + 5. OPC3 + 6. TIP4P-EW + 7. TIP4P-2005 + 8. TIP4P-FB + 9. OPC + The default water model is SPC/E. See documentation. + + For a systematic comparison of the performance of different water models, refer to + + Sachini et al., Systematic Comparison of the Structural and Dynamic Properties of + Commonly Used Water Models for Molecular Dynamics Simulations. J. Chem. Inf. Model. + 2021, 61, 9, 4521–4536. https://doi.org/10.1021/acs.jcim.1c00794 + parameter_set: Force field parameters to use for ions. Valid choices are: 1. "jj" for the Jensen and Jorgensen parameters (2006)" @@ -649,10 +661,12 @@ def get_ion( "tip3p": "jc", "tip3pew": None, "tip3pfb": "lm", + "opc3": "lm", "tip4p2005": None, "tip4p": "jj", "tip4pew": "jc", "tip4pfb": "lm", + "opc": "lm", } water_model = water_model.replace("-", "").replace("/", "").lower() if parameter_set: @@ -711,7 +725,7 @@ def get_ion( raise ValueError( f"No {parameter_set} ion parameters for water model {water_model}. " - "See documentation and try a different combination." + "See documentation and try a different combination." ) From d4c286b82cb9bd691c0f5fd90dcf89e1d97ba97a Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Wed, 27 Oct 2021 14:52:13 -0700 Subject: [PATCH 21/55] change ion param storage; add tests --- mdgo/data/ion_lj_data.xlsx | Bin 10920 -> 0 bytes mdgo/data/ion_lj_params.json | 1 + mdgo/forcefield.py | 90 +++++++++++++++++++--------- tests/test_forcefield.py | 112 +++++++++++++++++------------------ 4 files changed, 117 insertions(+), 86 deletions(-) delete mode 100644 mdgo/data/ion_lj_data.xlsx create mode 100644 mdgo/data/ion_lj_params.json diff --git a/mdgo/data/ion_lj_data.xlsx b/mdgo/data/ion_lj_data.xlsx deleted file mode 100644 index a174b8cd038f1d46aafd8564de4e6a769981dd5d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10920 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 diff --git a/mdgo/data/ion_lj_params.json b/mdgo/data/ion_lj_params.json new file mode 100644 index 00000000..7602edec --- /dev/null +++ b/mdgo/data/ion_lj_params.json @@ -0,0 +1 @@ +[{"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Li[+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": 2.87, "epsilon": 0.0005}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Li[+]", "combining_rule": "LB", "water_model": "spce", "sigma": 1.4094017720980168, "epsilon": 0.3367344}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Li[+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": 1.8263423721876955, "epsilon": 0.0279896}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Li[+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": 1.4396923285147885, "epsilon": 0.1039884}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Li[+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.351972615890496, "epsilon": 0.00633615}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Li[+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.3537544133267763, "epsilon": 0.0064158}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Li[+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.327027451782566, "epsilon": 0.00530214}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Li[+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.3252456543462854, "epsilon": 0.00523385}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Na[+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": 4.07, "epsilon": 0.0005}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Na[+]", "combining_rule": "LB", "water_model": "spce", "sigma": 2.159538492772182, "epsilon": 0.3526418}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Na[+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": 2.439280690268249, "epsilon": 0.0874393}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Na[+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": 2.184483656880112, "epsilon": 0.1684375}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Na[+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.6014242569697905, "epsilon": 0.0278401}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Na[+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.6192422313325974, "epsilon": 0.0303831}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Na[+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.5836062826069837, "epsilon": 0.02545423}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Na[+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.565788308244177, "epsilon": 0.02322071}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "K[+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": 5.17, "epsilon": 0.0005}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "K[+]", "combining_rule": "LB", "water_model": "spce", "sigma": 2.8384033159951207, "epsilon": 0.4297054}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "K[+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": 3.037964628858557, "epsilon": 0.1936829}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "K[+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": 2.833057923686279, "epsilon": 0.2794651}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "K[+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 3.1021093365646615, "epsilon": 0.16721338}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "K[+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 3.105672931437223, "epsilon": 0.1686942}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "K[+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 3.0949821468195386, "epsilon": 0.16426906}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "K[+]", "combining_rule": "LB", "water_model": "opc", "sigma": 3.0967639442558195, "epsilon": 0.16500296}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Rb[+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": 5.6, "epsilon": 0.0005}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Rb[+]", "combining_rule": "LB", "water_model": "spce", "sigma": 3.0949821468195386, "epsilon": 0.4451036}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Rb[+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": 3.23039875197687, "epsilon": 0.3278219}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Rb[+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": 3.0450918186036797, "epsilon": 0.4331494}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Rb[+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 3.225053359668028, "epsilon": 0.22132374}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Rb[+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 3.225053359668028, "epsilon": 0.22132374}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Rb[+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 3.225053359668028, "epsilon": 0.22132374}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Rb[+]", "combining_rule": "LB", "water_model": "opc", "sigma": 3.210798980177783, "epsilon": 0.21475916}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Cs[+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": 6.2, "epsilon": 0.0005}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cs[+]", "combining_rule": "LB", "water_model": "spce", "sigma": 3.601012618723251, "epsilon": 0.0898565}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cs[+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": 3.5208317340906206, "epsilon": 0.4065394}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cs[+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": 3.364033559697921, "epsilon": 0.3944318}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cs[+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 3.542213303325989, "epsilon": 0.37853483}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cs[+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 3.5457768981985502, "epsilon": 0.38035199}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cs[+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 3.563594872561357, "epsilon": 0.3894325}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cs[+]", "combining_rule": "LB", "water_model": "opc", "sigma": 3.5457768981985502, "epsilon": 0.38035199}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "F2[2-]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": 3.05, "epsilon": 0.71}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "F2[2-]", "combining_rule": "LB", "water_model": "spce", "sigma": 4.0215168136854915, "epsilon": 0.0074005}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "F2[2-]", "combining_rule": "LB", "water_model": "tip3p", "sigma": 4.103479495754403, "epsilon": 0.003364}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "F2[2-]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": 4.522201893280362, "epsilon": 0.0015752}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "F2[2-]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 3.105672931437223, "epsilon": 0.1686942}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "F2[2-]", "combining_rule": "LB", "water_model": "opc3", "sigma": 3.0949821468195386, "epsilon": 0.16426906}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "F2[2-]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 3.1003275391283807, "epsilon": 0.16647513}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "F2[2-]", "combining_rule": "LB", "water_model": "opc", "sigma": 3.064691590402767, "epsilon": 0.15202035}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Cl2[2-]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": 4.02, "epsilon": 0.71}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cl2[2-]", "combining_rule": "LB", "water_model": "spce", "sigma": 4.830452849756919, "epsilon": 0.012785}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cl2[2-]", "combining_rule": "LB", "water_model": "tip3p", "sigma": 4.477656957373345, "epsilon": 0.035591}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cl2[2-]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": 4.917760924134672, "epsilon": 0.0116615}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cl2[2-]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 3.8593732469839495, "epsilon": 0.53486081}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cl2[2-]", "combining_rule": "LB", "water_model": "opc3", "sigma": 3.848682462366266, "epsilon": 0.52988504}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cl2[2-]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 3.8593732469839495, "epsilon": 0.53486081}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cl2[2-]", "combining_rule": "LB", "water_model": "opc", "sigma": 3.8308644880034586, "epsilon": 0.52153239}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Br[-]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": 4.28, "epsilon": 0.71}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Br[-]", "combining_rule": "LB", "water_model": "spce", "sigma": 4.901724747208147, "epsilon": 0.0269586}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Br[-]", "combining_rule": "LB", "water_model": "tip3p", "sigma": 4.64692771382001, "epsilon": 0.0586554}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Br[-]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": 4.932015303624918, "epsilon": 0.0303773}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Br[-]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 4.1515880265339815, "epsilon": 0.65885086}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Br[-]", "combining_rule": "LB", "water_model": "opc3", "sigma": 4.124861064989771, "epsilon": 0.64855145}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Br[-]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 4.169406000896788, "epsilon": 0.66559495}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Br[-]", "combining_rule": "LB", "water_model": "opc", "sigma": 4.1195156726809286, "epsilon": 0.64646527}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "I[-]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": 4.81, "epsilon": 0.71}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "I[-]", "combining_rule": "LB", "water_model": "spce", "sigma": 5.201066716503301, "epsilon": 0.0427845}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "I[-]", "combining_rule": "LB", "water_model": "tip3p", "sigma": 5.095940667762741, "epsilon": 0.0536816}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "I[-]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": 5.259866031900563, "epsilon": 0.0417082}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "I[-]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 4.627327942020922, "epsilon": 0.80596674}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "I[-]", "combining_rule": "LB", "water_model": "opc3", "sigma": 4.614855359966957, "epsilon": 0.80293907}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "I[-]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 4.611291765094396, "epsilon": 0.80206648}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "I[-]", "combining_rule": "LB", "water_model": "opc", "sigma": 4.584564803550186, "epsilon": 0.79541413}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "NH4[+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": 5.34, "epsilon": 0.0005}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "NH4[+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "NH4[+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "NH4[+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "NH4[+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "NH4[+]", "combining_rule": "LB", "water_model": "opc3", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "NH4[+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "NH4[+]", "combining_rule": "LB", "water_model": "opc", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Tl[+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Tl[+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Tl[+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Tl[+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Tl[+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 3.3230522186634657, "epsilon": 0.26807617}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Tl[+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 3.3248340160997465, "epsilon": 0.26894857}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Tl[+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 3.3141432314820625, "epsilon": 0.26372453}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Tl[+]", "combining_rule": "LB", "water_model": "opc", "sigma": 3.287416269937852, "epsilon": 0.25078}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Cu[+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cu[+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cu[+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cu[+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cu[+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.1631020876447438, "epsilon": 0.00139196}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cu[+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.1613202902084634, "epsilon": 0.00136949}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cu[+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.1524113030270597, "epsilon": 0.00126172}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cu[+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.139938720973095, "epsilon": 0.001123}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Ag[+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Ag[+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Ag[+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Ag[+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ag[+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.681605141602421, "epsilon": 0.04058327}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ag[+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.676259749293579, "epsilon": 0.03962711}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ag[+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.638842003131685, "epsilon": 0.03336723}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ag[+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.6530963826219307, "epsilon": 0.03566355}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Be[2+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Be[2+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Be[2+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Be[2+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Be[2+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.072230418394429, "epsilon": 0.00057544}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Be[2+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.0704486209581483, "epsilon": 0.00056491}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Be[2+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.0490670517227803, "epsilon": 0.00045105}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Be[2+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.0241218876148506, "epsilon": 0.00034392}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Cu[2+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cu[2+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cu[2+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cu[2+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cu[2+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.5176797774645987, "epsilon": 0.01791152}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cu[2+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.5176797774645987, "epsilon": 0.01791152}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cu[2+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.49451641079295, "epsilon": 0.01570749}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cu[2+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.478480233866424, "epsilon": 0.01430674}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Ni[2+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Ni[2+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Ni[2+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Ni[2+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ni[2+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.4464078800133717, "epsilon": 0.01179373}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ni[2+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.4464078800133717, "epsilon": 0.01179373}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ni[2+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.4196809184691617, "epsilon": 0.00997323}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ni[2+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.396517551797513, "epsilon": 0.00858042}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Zn[2+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Zn[2+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Zn[2+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Zn[2+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Zn[2+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.49451641079295, "epsilon": 0.01570749}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Zn[2+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.49451641079295, "epsilon": 0.01570749}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Zn[2+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.4642258543761786, "epsilon": 0.01314367}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Zn[2+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.4464078800133717, "epsilon": 0.01179373}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Co[2+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Co[2+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Co[2+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Co[2+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Co[2+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.505207195410634, "epsilon": 0.0166976}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Co[2+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.505207195410634, "epsilon": 0.0166976}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Co[2+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.480262031302704, "epsilon": 0.01445748}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Co[2+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.4624440569398978, "epsilon": 0.01300356}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Cr[2+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cr[2+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cr[2+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cr[2+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cr[2+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.478480233866424, "epsilon": 0.01430674}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cr[2+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.478480233866424, "epsilon": 0.01430674}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cr[2+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.449971474885933, "epsilon": 0.01205473}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cr[2+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.4303717030868457, "epsilon": 0.01067299}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Fe[2+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Fe[2+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Fe[2+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Fe[2+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Fe[2+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.5176797774645987, "epsilon": 0.01791152}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Fe[2+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.5176797774645987, "epsilon": 0.01430674}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Fe[2+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.49451641079295, "epsilon": 0.01570749}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Fe[2+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.478480233866424, "epsilon": 0.01430674}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Mg[2+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Mg[2+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Mg[2+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Mg[2+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Mg[2+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.49451641079295, "epsilon": 0.01570749}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Mg[2+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.49451641079295, "epsilon": 0.01570749}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Mg[2+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.4642258543761786, "epsilon": 0.01314367}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Mg[2+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.4464078800133717, "epsilon": 0.01179373}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "V[2+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "V[2+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "V[2+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "V[2+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "V[2+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.6370602056954042, "epsilon": 0.03308772}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "V[2+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.6370602056954042, "epsilon": 0.03308772}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "V[2+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.610333244151194, "epsilon": 0.02909167}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "V[2+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.5942970672246677, "epsilon": 0.02686716}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Mn[2+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Mn[2+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Mn[2+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Mn[2+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Mn[2+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.604987851842352, "epsilon": 0.02833599}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Mn[2+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.604987851842352, "epsilon": 0.02833599}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Mn[2+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.59964245953351, "epsilon": 0.02759452}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Mn[2+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.5729154979892996, "epsilon": 0.02409615}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Hg[2+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Hg[2+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Hg[2+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Hg[2+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Hg[2+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.822367139068595, "epsilon": 0.07163727}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Hg[2+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.822367139068595, "epsilon": 0.07163727}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Hg[2+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.8009855698332267, "epsilon": 0.06617338}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Hg[2+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.788512987779262, "epsilon": 0.06311131}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Cd[2+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cd[2+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cd[2+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cd[2+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cd[2+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.7083321031466316, "epsilon": 0.04560206}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cd[2+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.7190228877643157, "epsilon": 0.04772212}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cd[2+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.692295926220105, "epsilon": 0.04254294}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cd[2+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.683386939038702, "epsilon": 0.04090549}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Ca[2+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Ca[2+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Ca[2+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Ca[2+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ca[2+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.8811664544658573, "epsilon": 0.08806221}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ca[2+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.8811664544658573, "epsilon": 0.08806221}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ca[2+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.850875898049086, "epsilon": 0.07934493}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ca[2+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.833057923686279, "epsilon": 0.07447106}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Sn[2+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Sn[2+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Sn[2+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Sn[2+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Sn[2+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 3.1110183237460647, "epsilon": 0.17092614}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Sn[2+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 3.1110183237460647, "epsilon": 0.17092614}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Sn[2+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 3.0842913622018546, "epsilon": 0.1598965}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Sn[2+]", "combining_rule": "LB", "water_model": "opc", "sigma": 3.0557826032213637, "epsilon": 0.1485017}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Sr[2+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Sr[2+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Sr[2+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Sr[2+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Sr[2+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 3.1395270827265556, "epsilon": 0.183041}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Sr[2+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 3.1395270827265556, "epsilon": 0.183041}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Sr[2+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 3.1110183237460647, "epsilon": 0.17092614}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Sr[2+]", "combining_rule": "LB", "water_model": "opc", "sigma": 3.0842913622018546, "epsilon": 0.1598965}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Ba[2+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Ba[2+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Ba[2+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Ba[2+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ba[2+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 3.4174874827863415, "epsilon": 0.31509345}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ba[2+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 3.4174874827863415, "epsilon": 0.31509345}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ba[2+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 3.385415128933289, "epsilon": 0.29896986}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ba[2+]", "combining_rule": "LB", "water_model": "opc", "sigma": 3.3551245725165177, "epsilon": 0.28387745}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Al[3+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Al[3+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Al[3+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Al[3+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Al[3+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.2931733004932333, "epsilon": 0.00412163}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Al[3+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.2931733004932333, "epsilon": 0.00412163}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Al[3+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.2575373517676196, "epsilon": 0.00312065}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Al[3+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.2272467953508484, "epsilon": 0.00243637}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Fe[3+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Fe[3+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Fe[3+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Fe[3+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Fe[3+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.5283705620822827, "epsilon": 0.0190038}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Fe[3+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.5283705620822827, "epsilon": 0.0190038}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Fe[3+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.5016436005380727, "epsilon": 0.01636246}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Fe[3+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.49451641079295, "epsilon": 0.01570749}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Cr[3+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cr[3+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cr[3+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Cr[3+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cr[3+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.4303717030868457, "epsilon": 0.01067299}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cr[3+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.4303717030868457, "epsilon": 0.01067299}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cr[3+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.396517551797513, "epsilon": 0.00858042}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Cr[3+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.3804813748709868, "epsilon": 0.00770969}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "In[3+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "In[3+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "In[3+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "In[3+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "In[3+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.5746972954255805, "epsilon": 0.02431873}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "In[3+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.588951674915826, "epsilon": 0.02615377}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "In[3+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.5711337005530193, "epsilon": 0.02387506}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "In[3+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.565788308244177, "epsilon": 0.02322071}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Tl[3+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Tl[3+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Tl[3+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Tl[3+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Tl[3+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.665568964675895, "epsilon": 0.03776169}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Tl[3+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.665568964675895, "epsilon": 0.03776169}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Tl[3+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.6513145851856494, "epsilon": 0.03537062}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Tl[3+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.6424055980042462, "epsilon": 0.03393126}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Y[3+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Y[3+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Y[3+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Y[3+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Y[3+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.850875898049086, "epsilon": 0.07934493}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Y[3+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.850875898049086, "epsilon": 0.07934493}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Y[3+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.820585341632314, "epsilon": 0.07117158}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Y[3+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.8063309621420687, "epsilon": 0.06751391}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "La[3+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "La[3+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "La[3+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "La[3+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "La[3+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 3.0842913622018546, "epsilon": 0.1598965}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "La[3+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 3.0878549570744163, "epsilon": 0.16134811}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "La[3+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 3.0557826032213637, "epsilon": 0.1485017}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "La[3+]", "combining_rule": "LB", "water_model": "opc", "sigma": 3.0290556416771532, "epsilon": 0.13818331}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Ce[3+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Ce[3+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Ce[3+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Ce[3+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ce[3+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 3.1252727032363103, "epsilon": 0.17693975}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ce[3+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 3.1323998929814327, "epsilon": 0.1799796}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ce[3+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 3.0967639442558195, "epsilon": 0.16500296}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ce[3+]", "combining_rule": "LB", "water_model": "opc", "sigma": 3.0736005775841706, "epsilon": 0.15557763}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Pr[3+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Pr[3+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Pr[3+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Pr[3+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Pr[3+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 3.1110183237460647, "epsilon": 0.17092614}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Pr[3+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 3.1181455134911875, "epsilon": 0.17392181}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Pr[3+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 3.0842913622018546, "epsilon": 0.1598965}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Pr[3+]", "combining_rule": "LB", "water_model": "opc", "sigma": 3.0593461980939254, "epsilon": 0.14990448}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Nd[3+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Nd[3+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Nd[3+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Nd[3+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Nd[3+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 3.014801262186908, "epsilon": 0.13282966}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Nd[3+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 3.014801262186908, "epsilon": 0.13282966}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Nd[3+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.9845107057701368, "epsilon": 0.12180998}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Nd[3+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.9613473390984875, "epsilon": 0.11371963}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Sm[3+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Sm[3+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Sm[3+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Sm[3+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Sm[3+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.970256326279891, "epsilon": 0.11679623}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Sm[3+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.970256326279891, "epsilon": 0.11679623}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Sm[3+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.9399657698631194, "epsilon": 0.10651723}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Sm[3+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.9185842006277514, "epsilon": 0.09957472}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Eu[3+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Eu[3+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Eu[3+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Eu[3+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Eu[3+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.9845107057701368, "epsilon": 0.12180998}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Eu[3+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.9845107057701368, "epsilon": 0.12180998}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Eu[3+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.954220149353365, "epsilon": 0.11129023}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Eu[3+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.9328385801179966, "epsilon": 0.10417397}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Gd[3+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Gd[3+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Gd[3+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Gd[3+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Gd[3+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.8954208339561025, "epsilon": 0.09235154}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Gd[3+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.8954208339561025, "epsilon": 0.09235154}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Gd[3+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.8651302775393312, "epsilon": 0.08337961}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Gd[3+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.850875898049086, "epsilon": 0.07934493}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Tb[3+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Tb[3+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Tb[3+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Tb[3+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Tb[3+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.909675213446348, "epsilon": 0.09675968}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Tb[3+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.909675213446348, "epsilon": 0.09675968}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Tb[3+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.8811664544658573, "epsilon": 0.08806221}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Tb[3+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.8651302775393312, "epsilon": 0.08337961}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Dy[3+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Dy[3+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Dy[3+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Dy[3+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Dy[3+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.8651302775393312, "epsilon": 0.08337961}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Dy[3+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.8651302775393312, "epsilon": 0.08337961}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Dy[3+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.8366215185588404, "epsilon": 0.07543075}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Dy[3+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.820585341632314, "epsilon": 0.07117158}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Er[3+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Er[3+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Er[3+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Er[3+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Er[3+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.850875898049086, "epsilon": 0.07934493}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Er[3+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.850875898049086, "epsilon": 0.07934493}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Er[3+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.820585341632314, "epsilon": 0.07117158}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Er[3+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.8063309621420687, "epsilon": 0.06751391}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Tm[3+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Tm[3+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Tm[3+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Tm[3+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Tm[3+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.850875898049086, "epsilon": 0.07934493}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Tm[3+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.850875898049086, "epsilon": 0.07934493}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Tm[3+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.820585341632314, "epsilon": 0.07117158}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Tm[3+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.8063309621420687, "epsilon": 0.06751391}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Lu[3+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Lu[3+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Lu[3+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Lu[3+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Lu[3+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.820585341632314, "epsilon": 0.07117158}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Lu[3+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.820585341632314, "epsilon": 0.07117158}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Lu[3+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.792076582651823, "epsilon": 0.06397679}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Lu[3+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.7760404057252974, "epsilon": 0.06014121}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Hf[4+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Hf[4+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Hf[4+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Hf[4+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Hf[4+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.6530963826219307, "epsilon": 0.03566355}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Hf[4+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.6530963826219307, "epsilon": 0.03566355}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Hf[4+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.6138968390237554, "epsilon": 0.02960343}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Hf[4+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.6032060544060713, "epsilon": 0.02808726}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Zr[4+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Zr[4+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Zr[4+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Zr[4+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Zr[4+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.686950533911263, "epsilon": 0.04155519}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Zr[4+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.686950533911263, "epsilon": 0.04155519}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Zr[4+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.6637871672396147, "epsilon": 0.03745682}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Zr[4+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.6513145851856494, "epsilon": 0.03537062}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Ce[4+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Ce[4+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Ce[4+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Ce[4+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ce[4+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 3.037964628858557, "epsilon": 0.14158262}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ce[4+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 3.043310021167399, "epsilon": 0.1436416}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ce[4+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 3.014801262186908, "epsilon": 0.13282966}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Ce[4+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.998765085260382, "epsilon": 0.12693448}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "U[4+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "U[4+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "U[4+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "U[4+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "U[4+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 3.037964628858557, "epsilon": 0.14158262}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "U[4+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 3.043310021167399, "epsilon": 0.1436416}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "U[4+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 3.014801262186908, "epsilon": 0.13282966}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "U[4+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.998765085260382, "epsilon": 0.12693448}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Pu[4+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Pu[4+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Pu[4+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Pu[4+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Pu[4+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 2.996983287824101, "epsilon": 0.12628793}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Pu[4+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 2.996983287824101, "epsilon": 0.12628793}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Pu[4+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 2.970256326279891, "epsilon": 0.11679623}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Pu[4+]", "combining_rule": "LB", "water_model": "opc", "sigma": 2.954220149353365, "epsilon": 0.11129023}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "jensen_jorgensen", "formula": "Th[4+]", "combining_rule": "geometric", "water_model": "tip4p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Th[4+]", "combining_rule": "LB", "water_model": "spce", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Th[4+]", "combining_rule": "LB", "water_model": "tip3p", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "joung_cheatham", "formula": "Th[4+]", "combining_rule": "LB", "water_model": "tip4pew", "sigma": NaN, "epsilon": NaN}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Th[4+]", "combining_rule": "LB", "water_model": "tip3pfb", "sigma": 3.0611279955302058, "epsilon": 0.15060822}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Th[4+]", "combining_rule": "LB", "water_model": "opc3", "sigma": 3.0664733878390478, "epsilon": 0.15272873}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Th[4+]", "combining_rule": "LB", "water_model": "tip4pfb", "sigma": 3.0450918186036797, "epsilon": 0.14433113}, {"@module": "mdgo.forcefield", "@class": "IonLJData", "@version": null, "name": "li_merz", "formula": "Th[4+]", "combining_rule": "LB", "water_model": "opc", "sigma": 3.036182831422276, "epsilon": 0.14089951}] \ No newline at end of file diff --git a/mdgo/forcefield.py b/mdgo/forcefield.py index 804ebd07..820b3722 100644 --- a/mdgo/forcefield.py +++ b/mdgo/forcefield.py @@ -28,13 +28,15 @@ import signal import subprocess import time +from dataclasses import dataclass from string import Template -from typing import Optional, Union +from typing import Literal, Optional, Union from urllib.parse import quote import numpy as np -import pandas as pd import pubchempy as pcp +from monty.json import MSONable +from monty.serialization import loadfn from pymatgen.core import Lattice, Structure from pymatgen.core.ion import Ion from pymatgen.io.lammps.data import ForceField, LammpsData, Topology, lattice_2_lmpbox @@ -558,6 +560,43 @@ def _obtain_entry_api(self, search_text, name, output_format) -> Optional[str]: return cid +@dataclass +class IonLJData(MSONable): + """ + A lightweight dataclass for storing ion force field parameters. The data + file ion_lj_params.json distributed with mdgo is a serialized list of these + objects. + + Attributes: + name: The name of the parameter set + formula: formula of the ion, e.g. 'Li+' + combining_rule: the method used to compute pairwise interaction parameters + from single atom parameters. 'geometric' or 'LB' for Lorentz-Berthelot + water_model: The water model for which the ion parameters were optimized. + sigma: The Lennard Jones sigma value, in Å + epsilon: The Lennard Jones epsilon value, in kcal/mol + """ + + name: Literal["jensen_jorgensen", "joung_cheatham", "li_merz"] + formula: str + combining_rule: Literal["geometric", "LB"] + water_model: Literal[ + "spc", + "spce", + "tip3p", + "tip3pew", + "tip3pfb", + "opc3", + "tip4p2005", + "tip4p", + "tip4pew", + "tip4pfb", + "opc", + ] + sigma: float + epsilon: float + + class Aqueous: """ A class for retreiving water and ion force field parameters. @@ -673,7 +712,8 @@ def get_ion( parameter_set = parameter_set.lower() else: parameter_set = default_sets.get(water_model) - parameter_set = alias.get(parameter_set) + if parameter_set: + parameter_set = alias.get(parameter_set, parameter_set) # Make the Ion object to get mass and charge if isinstance(ion, Ion): @@ -681,28 +721,27 @@ def get_ion( else: ion_obj = Ion.from_formula(ion.capitalize()) - # load ion data - # ion_data = pd.read_json(os.path.join(DATA_DIR, "ion_lj_data.json")) - ion_data = pd.read_excel( - "/Users/ryan/miniconda3/envs/md/code/mdgo/mdgo/data/ion_lj_data.xlsx", header=[0, 1, 2], index_col=0 - ) + # load ion data as a list of IonLJData objects + ion_data = loadfn(os.path.join(DATA_DIR, "ion_lj_params.json")) # make sure the ion is in the DataFrame key = ion_obj.reduced_formula - if key not in ion_data.index: + filtered_data = [d for d in ion_data if d.formula == key] + if len(filtered_data) == 0: raise ValueError(f"Ion {key} not found in database. Please try a different ion.") # make sure the parameter set is in the DataFrame - key = ion_obj.reduced_formula - if parameter_set not in ion_data.columns.levels[0]: + filtered_data = [d for d in filtered_data if d.name == parameter_set and d.water_model == water_model] + if len(filtered_data) == 0: raise ValueError( - f"Parameter set {parameter_set} not found in database. Please try a different parameter set." + f"No {parameter_set} parameters for water model {water_model} for ion {key}. " + "See documentation and try a different combination." ) - # make sure the water model is in the DataFrame - key = ion_obj.reduced_formula - if water_model not in ion_data.columns.levels[1]: - raise ValueError(f"Water model {water_model} not found in database. Please try a different water model.") + if len(filtered_data) != 1: + raise ValueError( + f"Something is wrong: multiple ion data entries for {key}, {parameter_set}, and {water_model}" + ) # we only consider monatomic ions at present # construct a cubic LammpsBox from a lattice @@ -714,19 +753,12 @@ def get_ion( topo = Topology(struct, charges=[ion_obj.charge]) # retrieve Lennard-Jones parameters - # values may be np.nan if selected combination is not available - sigma = ion_data[parameter_set][water_model].loc[key, "σ (Å)"] - epsilon = ion_data[parameter_set][water_model].loc[key, "ε(kcal/mol)"] - if np.isfinite(sigma) and np.isfinite(epsilon): - # construct ForceField object - ff = ForceField([(str(e), e) for e in ion_obj.elements], nonbond_coeffs=[[epsilon, sigma]]) - - return LammpsData.from_ff_and_topologies(box, ff, [topo], atom_style="full") - - raise ValueError( - f"No {parameter_set} ion parameters for water model {water_model}. " - "See documentation and try a different combination." - ) + # construct ForceField object + sigma = filtered_data[0].sigma + epsilon = filtered_data[0].epsilon + ff = ForceField([(str(e), e) for e in ion_obj.elements], nonbond_coeffs=[[epsilon, sigma]]) + + return LammpsData.from_ff_and_topologies(box, ff, [topo], atom_style="full") class ChargeWriter: diff --git a/tests/test_forcefield.py b/tests/test_forcefield.py index 52ade358..2e66ecd7 100644 --- a/tests/test_forcefield.py +++ b/tests/test_forcefield.py @@ -1,71 +1,69 @@ import os import sys import tempfile -from io import StringIO import unittest +from io import StringIO + +import pytest + from mdgo.forcefield import * test_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "test_files") -class FFcrawlerTest(unittest.TestCase): - def test_chrome(self) -> None: - with open(os.path.join(test_dir, "EMC.lmp")) as f: - pdf = f.readlines() - with open(os.path.join(test_dir, "CCOC(=O)OC.lmp")) as f: - smiles = f.readlines() - with open(os.path.join(test_dir, "EMC.lmp.xyz")) as f: - xyz = f.readlines() - with open(os.path.join(test_dir, "EMC.gro")) as f: - gro = f.readlines() - with open(os.path.join(test_dir, "EMC.itp")) as f: - itp = f.readlines() +class AqueousTest(unittest.TestCase): + def test_get_ion(self): + """ + Some unit tests for get_ion + """ + # string input, all lowercase + cation_ff = Aqueous.get_ion(parameter_set="lm", water_model="opc3", ion="li+") + assert isinstance(cation_ff, LammpsData) + assert np.allclose(cation_ff.force_field["Pair Coeffs"]["coeff2"].item(), 2.354, atol=0.001) + assert np.allclose(cation_ff.force_field["Pair Coeffs"]["coeff1"].item(), 0.0064158, atol=0.0000001) + + # string input, using the default ion parameter set for the water model + cation_ff = Aqueous.get_ion(parameter_set=None, water_model="opc3", ion="li+") + assert isinstance(cation_ff, LammpsData) + assert np.allclose(cation_ff.force_field["Pair Coeffs"]["coeff2"].item(), 2.354, atol=0.001) + assert np.allclose(cation_ff.force_field["Pair Coeffs"]["coeff1"].item(), 0.0064158, atol=0.0000001) + + # Ion object input, all lowercase + li = Ion.from_formula('Li+') + cation_ff = Aqueous.get_ion(parameter_set="jc", water_model="spce", ion=li) + assert isinstance(cation_ff, LammpsData) + assert np.allclose(cation_ff.force_field["Pair Coeffs"]["coeff2"].item(), 1.409, atol=0.001) + assert np.allclose(cation_ff.force_field["Pair Coeffs"]["coeff1"].item(), 0.3367344, atol=0.0000001) + + # anion + anion_ff = Aqueous.get_ion(parameter_set="jj", water_model="tip4p", ion="F-") + assert isinstance(anion_ff, LammpsData) + assert np.allclose(anion_ff.force_field["Pair Coeffs"]["coeff2"].item(), 3.05, atol=0.001) + assert np.allclose(anion_ff.force_field["Pair Coeffs"]["coeff1"].item(), 0.71, atol=0.0000001) + + # divalent, uppercase water model with hyphen + cation_ff = Aqueous.get_ion(parameter_set="lm", water_model="TIP3P-FB", ion="Zn+2") + assert isinstance(cation_ff, LammpsData) + assert np.allclose(cation_ff.force_field["Pair Coeffs"]["coeff2"].item(), 2.495, atol=0.001) + assert np.allclose(cation_ff.force_field["Pair Coeffs"]["coeff1"].item(), 0.01570749, atol=0.0000001) + + # trivalent, with brackets in ion name + cation_ff = Aqueous.get_ion(parameter_set="lm", water_model="tip4p-fb", ion="La[3+]") + assert isinstance(cation_ff, LammpsData) + assert np.allclose(cation_ff.force_field["Pair Coeffs"]["coeff2"].item(), 3.056, atol=0.001) + assert np.allclose(cation_ff.force_field["Pair Coeffs"]["coeff1"].item(), 0.1485017, atol=0.0000001) + + # ion not found + with pytest.raises(ValueError, match="not found in database"): + cation_ff = Aqueous.get_ion(parameter_set="jj", water_model="opc3", ion="Cu+3") - saved_stdout = sys.stdout - download_dir = tempfile.mkdtemp() - try: - out = StringIO() - sys.stdout = out + # parameter set not found + with pytest.raises(ValueError, match="No jensen_jorgensen parameters for water model opc3 for ion"): + cation_ff = Aqueous.get_ion(parameter_set="jj", water_model="opc3", ion="Cu+") - lpg = FFcrawler(download_dir, xyz=True, gromacs=True) - lpg.data_from_pdb(os.path.join(test_dir, "EMC.pdb")) - self.assertEqual( - out.getvalue(), - "LigParGen server connected.\n" - "Structure info uploaded. Rendering force field...\n" - "Force field file downloaded.\n" - ".xyz file saved.\n" - "Force field file saved.\n", - ) - self.assertTrue(os.path.exists(os.path.join(download_dir, "EMC.lmp"))) - self.assertTrue(os.path.exists(os.path.join(download_dir, "EMC.lmp.xyz"))) - self.assertTrue(os.path.exists(os.path.join(download_dir, "EMC.gro"))) - self.assertTrue(os.path.exists(os.path.join(download_dir, "EMC.itp"))) - with open(os.path.join(download_dir, "EMC.lmp")) as f: - pdf_actual = f.readlines() - self.assertListEqual(pdf, pdf_actual) - with open(os.path.join(download_dir, "EMC.lmp.xyz")) as f: - xyz_actual = f.readlines() - self.assertListEqual(xyz, xyz_actual) - with open(os.path.join(download_dir, "EMC.gro")) as f: - gro_actual = f.readlines() - self.assertListEqual(gro, gro_actual) - with open(os.path.join(download_dir, "EMC.itp")) as f: - itp_actual = f.readlines() - self.assertListEqual(itp, itp_actual) - lpg = FFcrawler(download_dir) - lpg.data_from_smiles("CCOC(=O)OC") - with open(os.path.join(download_dir, "CCOC(=O)OC.lmp")) as f: - smiles_actual = f.readlines() - self.assertListEqual(smiles[:13], smiles_actual[:13]) - self.assertListEqual(smiles[18:131], smiles_actual[18:131]) - self.assertEqual(" 1 1 1 -0.28", smiles_actual[131][:26]) - self.assertEqual(" 2 1 2 0.01", smiles_actual[132][:25]) - self.assertEqual(" 15 1 15 0.10", smiles_actual[145][:25]) - self.assertListEqual(smiles_actual[146:], smiles[146:]) - finally: - sys.stdout = saved_stdout - shutil.rmtree(download_dir) + # water model not found + with pytest.raises(ValueError, match="No ryan parameters for water model tip8p for ion"): + cation_ff = Aqueous.get_ion(parameter_set="ryan", water_model="tip8p", ion="Cu+") if __name__ == "__main__": From 010d69983ec048bfb648c13742630b40ecbec004 Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Wed, 27 Oct 2021 14:54:54 -0700 Subject: [PATCH 22/55] restore FFCrawlerTest --- tests/test_forcefield.py | 61 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/tests/test_forcefield.py b/tests/test_forcefield.py index 2e66ecd7..aa752129 100644 --- a/tests/test_forcefield.py +++ b/tests/test_forcefield.py @@ -4,6 +4,7 @@ import unittest from io import StringIO +import numpy as np import pytest from mdgo.forcefield import * @@ -11,6 +12,66 @@ test_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "test_files") +class FFcrawlerTest(unittest.TestCase): + def test_chrome(self) -> None: + with open(os.path.join(test_dir, "EMC.lmp")) as f: + pdf = f.readlines() + with open(os.path.join(test_dir, "CCOC(=O)OC.lmp")) as f: + smiles = f.readlines() + with open(os.path.join(test_dir, "EMC.lmp.xyz")) as f: + xyz = f.readlines() + with open(os.path.join(test_dir, "EMC.gro")) as f: + gro = f.readlines() + with open(os.path.join(test_dir, "EMC.itp")) as f: + itp = f.readlines() + + saved_stdout = sys.stdout + download_dir = tempfile.mkdtemp() + try: + out = StringIO() + sys.stdout = out + + lpg = FFcrawler(download_dir, xyz=True, gromacs=True) + lpg.data_from_pdb(os.path.join(test_dir, "EMC.pdb")) + self.assertEqual( + out.getvalue(), + "LigParGen server connected.\n" + "Structure info uploaded. Rendering force field...\n" + "Force field file downloaded.\n" + ".xyz file saved.\n" + "Force field file saved.\n", + ) + self.assertTrue(os.path.exists(os.path.join(download_dir, "EMC.lmp"))) + self.assertTrue(os.path.exists(os.path.join(download_dir, "EMC.lmp.xyz"))) + self.assertTrue(os.path.exists(os.path.join(download_dir, "EMC.gro"))) + self.assertTrue(os.path.exists(os.path.join(download_dir, "EMC.itp"))) + with open(os.path.join(download_dir, "EMC.lmp")) as f: + pdf_actual = f.readlines() + self.assertListEqual(pdf, pdf_actual) + with open(os.path.join(download_dir, "EMC.lmp.xyz")) as f: + xyz_actual = f.readlines() + self.assertListEqual(xyz, xyz_actual) + with open(os.path.join(download_dir, "EMC.gro")) as f: + gro_actual = f.readlines() + self.assertListEqual(gro, gro_actual) + with open(os.path.join(download_dir, "EMC.itp")) as f: + itp_actual = f.readlines() + self.assertListEqual(itp, itp_actual) + lpg = FFcrawler(download_dir) + lpg.data_from_smiles("CCOC(=O)OC") + with open(os.path.join(download_dir, "CCOC(=O)OC.lmp")) as f: + smiles_actual = f.readlines() + self.assertListEqual(smiles[:13], smiles_actual[:13]) + self.assertListEqual(smiles[18:131], smiles_actual[18:131]) + self.assertEqual(" 1 1 1 -0.28", smiles_actual[131][:26]) + self.assertEqual(" 2 1 2 0.01", smiles_actual[132][:25]) + self.assertEqual(" 15 1 15 0.10", smiles_actual[145][:25]) + self.assertListEqual(smiles_actual[146:], smiles[146:]) + finally: + sys.stdout = saved_stdout + shutil.rmtree(download_dir) + + class AqueousTest(unittest.TestCase): def test_get_ion(self): """ From 715eaab8dec765800bc7b2e7df294f2d6ea8316e Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Wed, 27 Oct 2021 15:14:52 -0700 Subject: [PATCH 23/55] rm text files for ion parameters --- mdgo/data/ion/aqvist/Ba++.lmp | 22 ------------- mdgo/data/ion/aqvist/Ca++.lmp | 22 ------------- mdgo/data/ion/aqvist/Cs+.lmp | 22 ------------- mdgo/data/ion/aqvist/K+.lmp | 22 ------------- mdgo/data/ion/aqvist/Li+.lmp | 22 ------------- mdgo/data/ion/aqvist/Mg++.lmp | 22 ------------- mdgo/data/ion/aqvist/Na+.lmp | 22 ------------- mdgo/data/ion/aqvist/Rb+.lmp | 22 ------------- mdgo/data/ion/aqvist/Sr++.lmp | 22 ------------- mdgo/data/ion/jensen_jorgensen/Br-.lmp | 22 ------------- mdgo/data/ion/jensen_jorgensen/Cl-.lmp | 22 ------------- mdgo/data/ion/jensen_jorgensen/Cs+.lmp | 22 ------------- mdgo/data/ion/jensen_jorgensen/F-.lmp | 22 ------------- mdgo/data/ion/jensen_jorgensen/I-.lmp | 22 ------------- mdgo/data/ion/jensen_jorgensen/K+.lmp | 22 ------------- mdgo/data/ion/jensen_jorgensen/Li+.lmp | 22 ------------- mdgo/data/ion/jensen_jorgensen/NH4+.lmp | 22 ------------- mdgo/data/ion/jensen_jorgensen/Na+.lmp | 22 ------------- mdgo/data/ion/jensen_jorgensen/Rb+.lmp | 22 ------------- .../data/ion/joung_cheatham/spce/Br-.lmp.data | 22 ------------- mdgo/data/ion/joung_cheatham/spce/Cl-.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/spce/Cs+.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/spce/F-.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/spce/I-.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/spce/K+.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/spce/Li+.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/spce/Na+.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/spce/Rb+.lmp | 22 ------------- .../ion/joung_cheatham/tip3p/Br-.lmp.data | 22 ------------- mdgo/data/ion/joung_cheatham/tip3p/Cl-.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/tip3p/Cs+.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/tip3p/F-.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/tip3p/I-.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/tip3p/K+.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/tip3p/Li+.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/tip3p/Na+.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/tip3p/Rb+.lmp | 22 ------------- .../ion/joung_cheatham/tip4pew/Br-.lmp.data | 22 ------------- mdgo/data/ion/joung_cheatham/tip4pew/Cl-.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/tip4pew/Cs+.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/tip4pew/F-.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/tip4pew/I-.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/tip4pew/K+.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/tip4pew/Li+.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/tip4pew/Na+.lmp | 22 ------------- mdgo/data/ion/joung_cheatham/tip4pew/Rb+.lmp | 22 ------------- mdgo/data/ion/merz/tip4pfb/Cl-.lmp | 31 ------------------- mdgo/data/ion/merz/tip4pfb/Na+.lmp | 31 ------------------- mdgo/data/ion/merz/tip4pfb/Zn++.lmp | 31 ------------------- 49 files changed, 1105 deletions(-) delete mode 100644 mdgo/data/ion/aqvist/Ba++.lmp delete mode 100644 mdgo/data/ion/aqvist/Ca++.lmp delete mode 100644 mdgo/data/ion/aqvist/Cs+.lmp delete mode 100644 mdgo/data/ion/aqvist/K+.lmp delete mode 100644 mdgo/data/ion/aqvist/Li+.lmp delete mode 100644 mdgo/data/ion/aqvist/Mg++.lmp delete mode 100644 mdgo/data/ion/aqvist/Na+.lmp delete mode 100644 mdgo/data/ion/aqvist/Rb+.lmp delete mode 100644 mdgo/data/ion/aqvist/Sr++.lmp delete mode 100644 mdgo/data/ion/jensen_jorgensen/Br-.lmp delete mode 100644 mdgo/data/ion/jensen_jorgensen/Cl-.lmp delete mode 100644 mdgo/data/ion/jensen_jorgensen/Cs+.lmp delete mode 100644 mdgo/data/ion/jensen_jorgensen/F-.lmp delete mode 100644 mdgo/data/ion/jensen_jorgensen/I-.lmp delete mode 100644 mdgo/data/ion/jensen_jorgensen/K+.lmp delete mode 100644 mdgo/data/ion/jensen_jorgensen/Li+.lmp delete mode 100644 mdgo/data/ion/jensen_jorgensen/NH4+.lmp delete mode 100644 mdgo/data/ion/jensen_jorgensen/Na+.lmp delete mode 100644 mdgo/data/ion/jensen_jorgensen/Rb+.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/spce/Br-.lmp.data delete mode 100644 mdgo/data/ion/joung_cheatham/spce/Cl-.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/spce/Cs+.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/spce/F-.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/spce/I-.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/spce/K+.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/spce/Li+.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/spce/Na+.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/spce/Rb+.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/tip3p/Br-.lmp.data delete mode 100644 mdgo/data/ion/joung_cheatham/tip3p/Cl-.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/tip3p/Cs+.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/tip3p/F-.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/tip3p/I-.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/tip3p/K+.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/tip3p/Li+.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/tip3p/Na+.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/tip3p/Rb+.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/tip4pew/Br-.lmp.data delete mode 100644 mdgo/data/ion/joung_cheatham/tip4pew/Cl-.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/tip4pew/Cs+.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/tip4pew/F-.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/tip4pew/I-.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/tip4pew/K+.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/tip4pew/Li+.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/tip4pew/Na+.lmp delete mode 100644 mdgo/data/ion/joung_cheatham/tip4pew/Rb+.lmp delete mode 100644 mdgo/data/ion/merz/tip4pfb/Cl-.lmp delete mode 100644 mdgo/data/ion/merz/tip4pfb/Na+.lmp delete mode 100644 mdgo/data/ion/merz/tip4pfb/Zn++.lmp diff --git a/mdgo/data/ion/aqvist/Ba++.lmp b/mdgo/data/ion/aqvist/Ba++.lmp deleted file mode 100644 index baa174d8..00000000 --- a/mdgo/data/ion/aqvist/Ba++.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Ba++ -# Aqvist, J. Ion-Water Interaction Potentials Derived from Free Energy Perturbation Slmulations J. Phys. Chem. 1990, 94, 8021– 8024 - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 137.327 - -Pair Coeffs #lj/cut/coul/long - - 1 0.047096 3.816610 - -Atoms - - 1 1 1 2.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/aqvist/Ca++.lmp b/mdgo/data/ion/aqvist/Ca++.lmp deleted file mode 100644 index 877c9ccf..00000000 --- a/mdgo/data/ion/aqvist/Ca++.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Ca++ -# Aqvist, J. Ion-Water Interaction Potentials Derived from Free Energy Perturbation Slmulations J. Phys. Chem. 1990, 94, 8021– 8024 - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 40.078 - -Pair Coeffs #lj/cut/coul/long - - 1 0.449657 2.412031 - -Atoms - - 1 1 1 2.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/aqvist/Cs+.lmp b/mdgo/data/ion/aqvist/Cs+.lmp deleted file mode 100644 index eef404dc..00000000 --- a/mdgo/data/ion/aqvist/Cs+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Cs+ -# Aqvist, J. Ion-Water Interaction Potentials Derived from Free Energy Perturbation Slmulations J. Phys. Chem. 1990, 94, 8021– 8024 - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 132.905 - -Pair Coeffs #lj/cut/coul/long - - 1 0.000081 6.715999 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/aqvist/K+.lmp b/mdgo/data/ion/aqvist/K+.lmp deleted file mode 100644 index a75632b7..00000000 --- a/mdgo/data/ion/aqvist/K+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -K+ -# Aqvist, J. Ion-Water Interaction Potentials Derived from Free Energy Perturbation Slmulations J. Phys. Chem. 1990, 94, 8021– 8024 - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 39.0983 - -Pair Coeffs #lj/cut/coul/long - - 1 0.000328 4.934628 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/aqvist/Li+.lmp b/mdgo/data/ion/aqvist/Li+.lmp deleted file mode 100644 index be22826e..00000000 --- a/mdgo/data/ion/aqvist/Li+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Li+ -# Aqvist, J. Ion-Water Interaction Potentials Derived from Free Energy Perturbation Slmulations J. Phys. Chem. 1990, 94, 8021– 8024 - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 6.940 - -Pair Coeffs #lj/cut/coul/long - - 1 0.018279 2.126452 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/aqvist/Mg++.lmp b/mdgo/data/ion/aqvist/Mg++.lmp deleted file mode 100644 index e99230e4..00000000 --- a/mdgo/data/ion/aqvist/Mg++.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Mg++ -# Aqvist, J. Ion-Water Interaction Potentials Derived from Free Energy Perturbation Slmulations J. Phys. Chem. 1990, 94, 8021– 8024 - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 24.305 - -Pair Coeffs #lj/cut/coul/long - - 1 0.875044 1.644471 - -Atoms - - 1 1 1 2.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/aqvist/Na+.lmp b/mdgo/data/ion/aqvist/Na+.lmp deleted file mode 100644 index 4c85ad3b..00000000 --- a/mdgo/data/ion/aqvist/Na+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Na+ -# Aqvist, J. Ion-Water Interaction Potentials Derived from Free Energy Perturbation Slmulations J. Phys. Chem. 1990, 94, 8021– 8024 - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 22.990 - -Pair Coeffs #lj/cut/coul/long - - 1 0.002772 3.330445 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/aqvist/Rb+.lmp b/mdgo/data/ion/aqvist/Rb+.lmp deleted file mode 100644 index 599e579f..00000000 --- a/mdgo/data/ion/aqvist/Rb+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Rb+ -# Aqvist, J. Ion-Water Interaction Potentials Derived from Free Energy Perturbation Slmulations J. Phys. Chem. 1990, 94, 8021– 8024 - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 85.4678 - -Pair Coeffs #lj/cut/coul/long - - 1 0.000171 5.621773 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/aqvist/Sr++.lmp b/mdgo/data/ion/aqvist/Sr++.lmp deleted file mode 100644 index e549ac46..00000000 --- a/mdgo/data/ion/aqvist/Sr++.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Sr++ -# Aqvist, J. Ion-Water Interaction Potentials Derived from Free Energy Perturbation Slmulations J. Phys. Chem. 1990, 94, 8021– 8024 - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 87.62 - -Pair Coeffs #lj/cut/coul/long - - 1 0.118226 3.102688 - -Atoms - - 1 1 1 2.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/jensen_jorgensen/Br-.lmp b/mdgo/data/ion/jensen_jorgensen/Br-.lmp deleted file mode 100644 index cf1a7c22..00000000 --- a/mdgo/data/ion/jensen_jorgensen/Br-.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Br- -# Kasper P. Jensen and William L. Jorgensen, J. Chem. Theory Comput. 2006, 2, 6, 1499–1509. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 79.904 - -Pair Coeffs #lj/cut/coul/long - - 1 0.71 4.28 - -Atoms - - 1 1 1 -1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/jensen_jorgensen/Cl-.lmp b/mdgo/data/ion/jensen_jorgensen/Cl-.lmp deleted file mode 100644 index aa287353..00000000 --- a/mdgo/data/ion/jensen_jorgensen/Cl-.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Cl- -# Kasper P. Jensen and William L. Jorgensen, J. Chem. Theory Comput. 2006, 2, 6, 1499–1509. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 35.453 - -Pair Coeffs #lj/cut/coul/long - - 1 0.71 4.02 - -Atoms - - 1 1 1 -1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/jensen_jorgensen/Cs+.lmp b/mdgo/data/ion/jensen_jorgensen/Cs+.lmp deleted file mode 100644 index feda650f..00000000 --- a/mdgo/data/ion/jensen_jorgensen/Cs+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Cs+ -# Kasper P. Jensen and William L. Jorgensen, J. Chem. Theory Comput. 2006, 2, 6, 1499–1509. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 132.905 - -Pair Coeffs #lj/cut/coul/long - - 1 0.0005 6.20 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/jensen_jorgensen/F-.lmp b/mdgo/data/ion/jensen_jorgensen/F-.lmp deleted file mode 100644 index 85d4a202..00000000 --- a/mdgo/data/ion/jensen_jorgensen/F-.lmp +++ /dev/null @@ -1,22 +0,0 @@ -F- -# Kasper P. Jensen and William L. Jorgensen, J. Chem. Theory Comput. 2006, 2, 6, 1499–1509. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 18.998 - -Pair Coeffs #lj/cut/coul/long - - 1 0.71 3.05 - -Atoms - - 1 1 1 -1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/jensen_jorgensen/I-.lmp b/mdgo/data/ion/jensen_jorgensen/I-.lmp deleted file mode 100644 index b2ef7c48..00000000 --- a/mdgo/data/ion/jensen_jorgensen/I-.lmp +++ /dev/null @@ -1,22 +0,0 @@ -I- -# Kasper P. Jensen and William L. Jorgensen, J. Chem. Theory Comput. 2006, 2, 6, 1499–1509. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 126.90 - -Pair Coeffs #lj/cut/coul/long - - 1 0.71 4.81 - -Atoms - - 1 1 1 -1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/jensen_jorgensen/K+.lmp b/mdgo/data/ion/jensen_jorgensen/K+.lmp deleted file mode 100644 index cfeae7e2..00000000 --- a/mdgo/data/ion/jensen_jorgensen/K+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -K+ -# Kasper P. Jensen and William L. Jorgensen, J. Chem. Theory Comput. 2006, 2, 6, 1499–1509. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 39.0983 - -Pair Coeffs #lj/cut/coul/long - - 1 0.0005 5.17 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/jensen_jorgensen/Li+.lmp b/mdgo/data/ion/jensen_jorgensen/Li+.lmp deleted file mode 100644 index 80466706..00000000 --- a/mdgo/data/ion/jensen_jorgensen/Li+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Li+ -# Kasper P. Jensen and William L. Jorgensen, J. Chem. Theory Comput. 2006, 2, 6, 1499–1509. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 6.940 - -Pair Coeffs #lj/cut/coul/long - - 1 0.0005 2.87 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/jensen_jorgensen/NH4+.lmp b/mdgo/data/ion/jensen_jorgensen/NH4+.lmp deleted file mode 100644 index 9d77ee57..00000000 --- a/mdgo/data/ion/jensen_jorgensen/NH4+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -NH4+ united-atiom parameter -# Kasper P. Jensen and William L. Jorgensen, J. Chem. Theory Comput. 2006, 2, 6, 1499–1509. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 18.038 - -Pair Coeffs #lj/cut/coul/long - - 1 0.0005 5.34 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/jensen_jorgensen/Na+.lmp b/mdgo/data/ion/jensen_jorgensen/Na+.lmp deleted file mode 100644 index 1780909d..00000000 --- a/mdgo/data/ion/jensen_jorgensen/Na+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Na+ -# Kasper P. Jensen and William L. Jorgensen, J. Chem. Theory Comput. 2006, 2, 6, 1499–1509. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 22.990 - -Pair Coeffs #lj/cut/coul/long - - 1 0.0005 4.07 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/jensen_jorgensen/Rb+.lmp b/mdgo/data/ion/jensen_jorgensen/Rb+.lmp deleted file mode 100644 index 171d8692..00000000 --- a/mdgo/data/ion/jensen_jorgensen/Rb+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Rb+ -# Kasper P. Jensen and William L. Jorgensen, J. Chem. Theory Comput. 2006, 2, 6, 1499–1509. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 85.4678 - -Pair Coeffs #lj/cut/coul/long - - 1 0.0005 5.60 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/spce/Br-.lmp.data b/mdgo/data/ion/joung_cheatham/spce/Br-.lmp.data deleted file mode 100644 index 59129416..00000000 --- a/mdgo/data/ion/joung_cheatham/spce/Br-.lmp.data +++ /dev/null @@ -1,22 +0,0 @@ -Br- optimized for SPC/E water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 79.904 - -Pair Coeffs #lj/cut/coul/long - - 1 0.027 5.144 - -Atoms - - 1 1 1 -1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/spce/Cl-.lmp b/mdgo/data/ion/joung_cheatham/spce/Cl-.lmp deleted file mode 100644 index 296d34ec..00000000 --- a/mdgo/data/ion/joung_cheatham/spce/Cl-.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Cl- optimized for SPC/E water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 35.453 - -Pair Coeffs #lj/cut/coul/long - - 1 0.013 5.053 - -Atoms - - 1 1 1 -1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/spce/Cs+.lmp b/mdgo/data/ion/joung_cheatham/spce/Cs+.lmp deleted file mode 100644 index ded2e690..00000000 --- a/mdgo/data/ion/joung_cheatham/spce/Cs+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Cs+ optimized for SPC/E water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 132.905 - -Pair Coeffs #lj/cut/coul/long - - 1 0.090 3.617 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/spce/F-.lmp b/mdgo/data/ion/joung_cheatham/spce/F-.lmp deleted file mode 100644 index b5cae983..00000000 --- a/mdgo/data/ion/joung_cheatham/spce/F-.lmp +++ /dev/null @@ -1,22 +0,0 @@ -F- optimized for SPC/E water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 18.998 - -Pair Coeffs #lj/cut/coul/long - - 1 0.007 4.081 - -Atoms - - 1 1 1 -1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/spce/I-.lmp b/mdgo/data/ion/joung_cheatham/spce/I-.lmp deleted file mode 100644 index b291ff1e..00000000 --- a/mdgo/data/ion/joung_cheatham/spce/I-.lmp +++ /dev/null @@ -1,22 +0,0 @@ -I- optimized for SPC/E water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 126.90 - -Pair Coeffs #lj/cut/coul/long - - 1 0.043 5.533 - -Atoms - - 1 1 1 -1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/spce/K+.lmp b/mdgo/data/ion/joung_cheatham/spce/K+.lmp deleted file mode 100644 index 464d8fa7..00000000 --- a/mdgo/data/ion/joung_cheatham/spce/K+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -K+ optimized for SPC/E water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 39.0983 - -Pair Coeffs #lj/cut/coul/long - - 1 0.430 2.846 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/spce/Li+.lmp b/mdgo/data/ion/joung_cheatham/spce/Li+.lmp deleted file mode 100644 index 3035e2c9..00000000 --- a/mdgo/data/ion/joung_cheatham/spce/Li+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Li+ optimized for SPC/E water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 6.940 - -Pair Coeffs #lj/cut/coul/long - - 1 0.337 1.651 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/spce/Na+.lmp b/mdgo/data/ion/joung_cheatham/spce/Na+.lmp deleted file mode 100644 index a0c5f9be..00000000 --- a/mdgo/data/ion/joung_cheatham/spce/Na+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Na+ optimized for SPC/E water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 22.990 - -Pair Coeffs #lj/cut/coul/long - - 1 0.353 2.238 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/spce/Rb+.lmp b/mdgo/data/ion/joung_cheatham/spce/Rb+.lmp deleted file mode 100644 index 4bb2839e..00000000 --- a/mdgo/data/ion/joung_cheatham/spce/Rb+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Rb+ optimized for SPC/E water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 85.4678 - -Pair Coeffs #lj/cut/coul/long - - 1 0.445 3.095 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/tip3p/Br-.lmp.data b/mdgo/data/ion/joung_cheatham/tip3p/Br-.lmp.data deleted file mode 100644 index fd92edd4..00000000 --- a/mdgo/data/ion/joung_cheatham/tip3p/Br-.lmp.data +++ /dev/null @@ -1,22 +0,0 @@ -Br- optimized for TIP3P water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 79.904 - -Pair Coeffs #lj/cut/coul/long - - 1 0.059 4.824 - -Atoms - - 1 1 1 -1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/tip3p/Cl-.lmp b/mdgo/data/ion/joung_cheatham/tip3p/Cl-.lmp deleted file mode 100644 index aab4afd2..00000000 --- a/mdgo/data/ion/joung_cheatham/tip3p/Cl-.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Cl- optimized for TIP3P water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 35.453 - -Pair Coeffs #lj/cut/coul/long - - 1 0.036 4.617 - -Atoms - - 1 1 1 -1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/tip3p/Cs+.lmp b/mdgo/data/ion/joung_cheatham/tip3p/Cs+.lmp deleted file mode 100644 index 5df55535..00000000 --- a/mdgo/data/ion/joung_cheatham/tip3p/Cs+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Cs+ optimized for TIP3P water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 132.905 - -Pair Coeffs #lj/cut/coul/long - - 1 0.407 3.532 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/tip3p/F-.lmp b/mdgo/data/ion/joung_cheatham/tip3p/F-.lmp deleted file mode 100644 index bf0d2293..00000000 --- a/mdgo/data/ion/joung_cheatham/tip3p/F-.lmp +++ /dev/null @@ -1,22 +0,0 @@ -F- optimized for TIP3P water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 18.998 - -Pair Coeffs #lj/cut/coul/long - - 1 0.003 4.175 - -Atoms - - 1 1 1 -1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/tip3p/I-.lmp b/mdgo/data/ion/joung_cheatham/tip3p/I-.lmp deleted file mode 100644 index 1252121e..00000000 --- a/mdgo/data/ion/joung_cheatham/tip3p/I-.lmp +++ /dev/null @@ -1,22 +0,0 @@ -I- optimized for TIP3P water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 126.90 - -Pair Coeffs #lj/cut/coul/long - - 1 0.054 5.395 - -Atoms - - 1 1 1 -1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/tip3p/K+.lmp b/mdgo/data/ion/joung_cheatham/tip3p/K+.lmp deleted file mode 100644 index b79e821c..00000000 --- a/mdgo/data/ion/joung_cheatham/tip3p/K+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -K+ optimized for TIP3P water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 39.0983 - -Pair Coeffs #lj/cut/coul/long - - 1 0.194 3.039 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/tip3p/Li+.lmp b/mdgo/data/ion/joung_cheatham/tip3p/Li+.lmp deleted file mode 100644 index 935fdbed..00000000 --- a/mdgo/data/ion/joung_cheatham/tip3p/Li+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Li+ optimized for TIP3P water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 6.940 - -Pair Coeffs #lj/cut/coul/long - - 1 0.028 1.966 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/tip3p/Na+.lmp b/mdgo/data/ion/joung_cheatham/tip3p/Na+.lmp deleted file mode 100644 index bffc1028..00000000 --- a/mdgo/data/ion/joung_cheatham/tip3p/Na+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Na+ optimized for TIP3P water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 22.990 - -Pair Coeffs #lj/cut/coul/long - - 1 0.087 2.480 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/tip3p/Rb+.lmp b/mdgo/data/ion/joung_cheatham/tip3p/Rb+.lmp deleted file mode 100644 index 943d4f30..00000000 --- a/mdgo/data/ion/joung_cheatham/tip3p/Rb+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Rb+ optimized for TIP3P water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 85.4678 - -Pair Coeffs #lj/cut/coul/long - - 1 0.328 3.231 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/tip4pew/Br-.lmp.data b/mdgo/data/ion/joung_cheatham/tip4pew/Br-.lmp.data deleted file mode 100644 index 43be2d0c..00000000 --- a/mdgo/data/ion/joung_cheatham/tip4pew/Br-.lmp.data +++ /dev/null @@ -1,22 +0,0 @@ -Br- optimized for TIP4P_EW water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 79.904 - -Pair Coeffs #lj/cut/coul/long - - 1 0.030 5.183 - -Atoms - - 1 1 1 -1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/tip4pew/Cl-.lmp b/mdgo/data/ion/joung_cheatham/tip4pew/Cl-.lmp deleted file mode 100644 index 2ae45ca3..00000000 --- a/mdgo/data/ion/joung_cheatham/tip4pew/Cl-.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Cl- optimized for TIP4P_EW water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 35.453 - -Pair Coeffs #lj/cut/coul/long - - 1 0.012 5.164 - -Atoms - - 1 1 1 -1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/tip4pew/Cs+.lmp b/mdgo/data/ion/joung_cheatham/tip4pew/Cs+.lmp deleted file mode 100644 index 40c8973d..00000000 --- a/mdgo/data/ion/joung_cheatham/tip4pew/Cs+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Cs+ optimized for TIP4P_EW water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 132.905 - -Pair Coeffs #lj/cut/coul/long - - 1 0.394 3.368 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/tip4pew/F-.lmp b/mdgo/data/ion/joung_cheatham/tip4pew/F-.lmp deleted file mode 100644 index 9a6d2b3b..00000000 --- a/mdgo/data/ion/joung_cheatham/tip4pew/F-.lmp +++ /dev/null @@ -1,22 +0,0 @@ -F- optimized for TIP4P_EW water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 18.998 - -Pair Coeffs #lj/cut/coul/long - - 1 0.002 4.671 - -Atoms - - 1 1 1 -1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/tip4pew/I-.lmp b/mdgo/data/ion/joung_cheatham/tip4pew/I-.lmp deleted file mode 100644 index 660eaba4..00000000 --- a/mdgo/data/ion/joung_cheatham/tip4pew/I-.lmp +++ /dev/null @@ -1,22 +0,0 @@ -I- optimized for TIP4P_EW water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 126.90 - -Pair Coeffs #lj/cut/coul/long - - 1 0.042 5.612 - -Atoms - - 1 1 1 -1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/tip4pew/K+.lmp b/mdgo/data/ion/joung_cheatham/tip4pew/K+.lmp deleted file mode 100644 index 24b783ba..00000000 --- a/mdgo/data/ion/joung_cheatham/tip4pew/K+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -K+ optimized for TIP4P_EW water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 39.0983 - -Pair Coeffs #lj/cut/coul/long - - 1 0.279 2.841 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/tip4pew/Li+.lmp b/mdgo/data/ion/joung_cheatham/tip4pew/Li+.lmp deleted file mode 100644 index 246e15bc..00000000 --- a/mdgo/data/ion/joung_cheatham/tip4pew/Li+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Li+ optimized for TIP4P_EW water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 6.940 - -Pair Coeffs #lj/cut/coul/long - - 1 0.104 1.673 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/tip4pew/Na+.lmp b/mdgo/data/ion/joung_cheatham/tip4pew/Na+.lmp deleted file mode 100644 index f9556f56..00000000 --- a/mdgo/data/ion/joung_cheatham/tip4pew/Na+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Na+ optimized for TIP4P_EW water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 22.990 - -Pair Coeffs #lj/cut/coul/long - - 1 0.168 2.259 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/joung_cheatham/tip4pew/Rb+.lmp b/mdgo/data/ion/joung_cheatham/tip4pew/Rb+.lmp deleted file mode 100644 index e1995153..00000000 --- a/mdgo/data/ion/joung_cheatham/tip4pew/Rb+.lmp +++ /dev/null @@ -1,22 +0,0 @@ -Rb+ optimized for TIP4P_EW water model -# In Suk Joung and Thomas E. Cheatham III, J. Phys. Chem. B 2008, 112, 30, 9020–9041. - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 85.4678 - -Pair Coeffs #lj/cut/coul/long - - 1 0.433 3.046 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/merz/tip4pfb/Cl-.lmp b/mdgo/data/ion/merz/tip4pfb/Cl-.lmp deleted file mode 100644 index 92d24e52..00000000 --- a/mdgo/data/ion/merz/tip4pfb/Cl-.lmp +++ /dev/null @@ -1,31 +0,0 @@ -Cl- -# Sengupta et al. Parameterization of Monovalent Ions for the OPC3, OPC, TIP3P-FB, and -# TIP4P-FB Water Models. J. Chem. Information Modeling 61(2), 2021. -# https://pubs.acs.org/doi/10.1021/acs.jcim.0c01390 -# This set of values is optimized for reproducing ion-oxygen distance (Table 3) using -# the TIP4P-FB water model -# all values in 'real' units (kcal/mol and Angstrom) - -# Note that LAMMPS requires the value sigma (the distance at which the potential equals -# zero, rather than Rmin/2 which is reported in the paper. To convert, use -# sigma = Rmin/2 * 2^(5/6) - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 35.453 - -Pair Coeffs - - 1 0.53486081 3.8594 - -Atoms - - 1 1 1 -1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/merz/tip4pfb/Na+.lmp b/mdgo/data/ion/merz/tip4pfb/Na+.lmp deleted file mode 100644 index ed4a062d..00000000 --- a/mdgo/data/ion/merz/tip4pfb/Na+.lmp +++ /dev/null @@ -1,31 +0,0 @@ -Na+ -# Sengupta et al. Parameterization of Monovalent Ions for the OPC3, OPC, TIP3P-FB, and -# TIP4P-FB Water Models. J. Chem. Information Modeling 61(2), 2021. -# https://pubs.acs.org/doi/10.1021/acs.jcim.0c01390 -# This set of values is optimized for reproducing ion-oxygen distance (Table 3) using -# the TIP4P-FB water model -# all values in 'real' units (kcal/mol and Angstrom) - -# Note that LAMMPS requires the value sigma (the distance at which the potential equals -# zero, rather than Rmin/2 which is reported in the paper. To convert, use -# sigma = Rmin/2 * 2^(5/6) - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 22.9898 - -Pair Coeffs - - 1 0.02545423 2.5836 - -Atoms - - 1 1 1 1.0 0.50000 0.50000 0.50000 diff --git a/mdgo/data/ion/merz/tip4pfb/Zn++.lmp b/mdgo/data/ion/merz/tip4pfb/Zn++.lmp deleted file mode 100644 index c8c15eac..00000000 --- a/mdgo/data/ion/merz/tip4pfb/Zn++.lmp +++ /dev/null @@ -1,31 +0,0 @@ -Zn++ -# Li et al. Systematic Parametrization of Divalent Metal Ions for the OPC3, OPC, -# TIP3P-FB, and TIP4P-FB Water Models. J. Chem. Theory and Computation 16(7), 2020. -# https://pubs.acs.org/doi/10.1021/acs.jctc.0c00194 -# This set of values is optimized for reproducing ion-oxygen distance (Table 3) using -# the TIP4P-FB water model -# all values in 'real' units (kcal/mol and Angstrom) - -# Note that LAMMPS requires the value sigma (the distance at which the potential equals -# zero, rather than Rmin/2 which is reported in the paper. To convert, use -# sigma = Rmin/2 * 2^(5/6) - - 1 atoms - - 1 atom types - - 0.0 1.0 xlo xhi - 0.0 1.0 ylo yhi - 0.0 1.0 zlo zhi - -Masses - - 1 64.929 - -Pair Coeffs #lj/cut/tip4p/long 2 1 1 1 0.10527 9.0 7.0 - - 1 0.01314367 2.4642 - -Atoms - - 1 1 1 2.0 0.50000 0.50000 0.50000 From c6bc1dca633160ff80c75dda841fbaa339ba75ec Mon Sep 17 00:00:00 2001 From: Tingzheng Hou Date: Wed, 10 Nov 2021 18:30:10 -0800 Subject: [PATCH 24/55] add packmol --- .github/workflows/test.yml | 5 + tests/packmol/.gitignore | 5 + tests/packmol/AUTHORS | 11 + tests/packmol/CMakeLists.txt | 57 + tests/packmol/LICENSE | 21 + tests/packmol/Makefile | 196 + tests/packmol/README.md | 36 + tests/packmol/ahestetic.f90 | 21 + tests/packmol/cenmass.f90 | 103 + tests/packmol/checkpoint.f90 | 116 + tests/packmol/comparegrad.f90 | 98 + tests/packmol/compile_cmake.sh | 26 + tests/packmol/comprest.f90 | 168 + tests/packmol/compute_data.f90 | 63 + tests/packmol/computef.f90 | 220 + tests/packmol/computeg.f90 | 309 ++ tests/packmol/configure | 52 + tests/packmol/data_types.f90 | 10 + tests/packmol/flashmod.f90 | 21 + tests/packmol/flashsort.f90 | 95 + tests/packmol/fparc.f90 | 77 + tests/packmol/gencan.f | 6006 +++++++++++++++++++++++++ tests/packmol/getinp.f90 | 1108 +++++ tests/packmol/gparc.f90 | 87 + tests/packmol/gwalls.f90 | 264 ++ tests/packmol/header | 5 + tests/packmol/heuristics.f90 | 151 + tests/packmol/initial.f90 | 590 +++ tests/packmol/input.f90 | 80 + tests/packmol/jacobi.f90 | 106 + tests/packmol/output.f90 | 797 ++++ tests/packmol/packmol.f90 | 942 ++++ tests/packmol/pgencan.f90 | 98 + tests/packmol/polartocart.f90 | 106 + tests/packmol/random.f90 | 50 + tests/packmol/release.sh | 69 + tests/packmol/resetboxes.f90 | 30 + tests/packmol/restmol.f90 | 86 + tests/packmol/setibox.f90 | 30 + tests/packmol/setijk.f90 | 46 + tests/packmol/setsizes.f90 | 363 ++ tests/packmol/sizes.f90 | 31 + tests/packmol/solvate.tcl | 7625 ++++++++++++++++++++++++++++++++ tests/packmol/strlength.f90 | 96 + tests/packmol/swaptype.f90 | 89 + tests/packmol/swaptypemod.f90 | 16 + tests/packmol/title.f90 | 19 + tests/packmol/tobar.f90 | 42 + tests/packmol/usegencan.f90 | 18 + tests/packmol/writesuccess.f90 | 46 + 50 files changed, 20706 insertions(+) create mode 100644 tests/packmol/.gitignore create mode 100644 tests/packmol/AUTHORS create mode 100644 tests/packmol/CMakeLists.txt create mode 100644 tests/packmol/LICENSE create mode 100644 tests/packmol/Makefile create mode 100644 tests/packmol/README.md create mode 100644 tests/packmol/ahestetic.f90 create mode 100644 tests/packmol/cenmass.f90 create mode 100644 tests/packmol/checkpoint.f90 create mode 100644 tests/packmol/comparegrad.f90 create mode 100644 tests/packmol/compile_cmake.sh create mode 100644 tests/packmol/comprest.f90 create mode 100644 tests/packmol/compute_data.f90 create mode 100644 tests/packmol/computef.f90 create mode 100644 tests/packmol/computeg.f90 create mode 100755 tests/packmol/configure create mode 100644 tests/packmol/data_types.f90 create mode 100644 tests/packmol/flashmod.f90 create mode 100644 tests/packmol/flashsort.f90 create mode 100644 tests/packmol/fparc.f90 create mode 100644 tests/packmol/gencan.f create mode 100644 tests/packmol/getinp.f90 create mode 100644 tests/packmol/gparc.f90 create mode 100644 tests/packmol/gwalls.f90 create mode 100644 tests/packmol/header create mode 100644 tests/packmol/heuristics.f90 create mode 100644 tests/packmol/initial.f90 create mode 100644 tests/packmol/input.f90 create mode 100644 tests/packmol/jacobi.f90 create mode 100644 tests/packmol/output.f90 create mode 100644 tests/packmol/packmol.f90 create mode 100644 tests/packmol/pgencan.f90 create mode 100644 tests/packmol/polartocart.f90 create mode 100644 tests/packmol/random.f90 create mode 100755 tests/packmol/release.sh create mode 100644 tests/packmol/resetboxes.f90 create mode 100644 tests/packmol/restmol.f90 create mode 100644 tests/packmol/setibox.f90 create mode 100644 tests/packmol/setijk.f90 create mode 100644 tests/packmol/setsizes.f90 create mode 100644 tests/packmol/sizes.f90 create mode 100755 tests/packmol/solvate.tcl create mode 100644 tests/packmol/strlength.f90 create mode 100644 tests/packmol/swaptype.f90 create mode 100644 tests/packmol/swaptypemod.f90 create mode 100644 tests/packmol/title.f90 create mode 100644 tests/packmol/tobar.f90 create mode 100644 tests/packmol/usegencan.f90 create mode 100644 tests/packmol/writesuccess.f90 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 47542fde..a7bd1419 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -50,6 +50,11 @@ jobs: pip install -r requirements.txt pip install -r requirements-dev.txt pip install -e . + - name: Prepare Packmol + run: | + make + echo "$HOME/tests/packmol" >> $GITHUB_PATH + working-directory: dart_project - name: Prepare Selenium # https://github.com/marketplace/actions/setup-chromedriver uses: nanasess/setup-chromedriver@master diff --git a/tests/packmol/.gitignore b/tests/packmol/.gitignore new file mode 100644 index 00000000..ac61ebf0 --- /dev/null +++ b/tests/packmol/.gitignore @@ -0,0 +1,5 @@ +build/ +*.mod +*.o +*.swp +packmol diff --git a/tests/packmol/AUTHORS b/tests/packmol/AUTHORS new file mode 100644 index 00000000..59bd0d16 --- /dev/null +++ b/tests/packmol/AUTHORS @@ -0,0 +1,11 @@ +L. Martinez, R. Andrade, E. G. Birgin, J. M. Martinez. Packmol: A +package for building initial configurations for molecular dynamics +simulations. Journal of Computational Chemistry, 30(13):2157-2164, +2009. + +J. M. Martinez and L. Martinez. Packing optimization for automated +generation of complex system's initial configurations for molecular +dynamics and docking. Journal of Computational Chemistry, 24(7):819-825, +2003. + +Home-Page: http://m3g.iqm.unicamp.br/packmol diff --git a/tests/packmol/CMakeLists.txt b/tests/packmol/CMakeLists.txt new file mode 100644 index 00000000..4da22e01 --- /dev/null +++ b/tests/packmol/CMakeLists.txt @@ -0,0 +1,57 @@ +cmake_minimum_required(VERSION 2.6) +project(packmol Fortran) + + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif(NOT CMAKE_BUILD_TYPE) + +if(CMAKE_Fortran_COMPILER_ID MATCHES GNU) + add_compile_options( + -Wall "$<$:-Werror>" + ) +endif() + +# Build the executable +add_executable(packmol + cenmass.f90 + gencan.f + pgencan.f90 + initial.f90 + title.f90 + setsizes.f90 + getinp.f90 + strlength.f90 + output.f90 + checkpoint.f90 + writesuccess.f90 + fparc.f90 + gparc.f90 + gwalls.f90 + comprest.f90 + comparegrad.f90 + packmol.f90 + polartocart.f90 + resetboxes.f90 + tobar.f90 + setijk.f90 + setibox.f90 + restmol.f90 + swaptype.f90 + swaptypemod.f90 + ahestetic.f90 + heuristics.f90 + flashsort.f90 + jacobi.f90 + random.f90 + sizes.f90 + usegencan.f90 + compute_data.f90 + flashmod.f90 + computef.f90 + computeg.f90 + input.f90 +) + +# Installation directive +install(TARGETS packmol DESTINATION bin) diff --git a/tests/packmol/LICENSE b/tests/packmol/LICENSE new file mode 100644 index 00000000..8db8be26 --- /dev/null +++ b/tests/packmol/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2009-2018 Leandro Martínez, José Mario Martínez, Ernesto Birgin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/tests/packmol/Makefile b/tests/packmol/Makefile new file mode 100644 index 00000000..b3765df7 --- /dev/null +++ b/tests/packmol/Makefile @@ -0,0 +1,196 @@ +# +# Makefile for Packmol: Read the comments if you have some +# problem while compiling. +# +# You may use the ./configure script to search automatically for +# some fortran compiler. +# +# This make file will try to compile packmol with the default +# fortran compiler, defined by the FC directive. For doing this, +# just type +# +# make +# +# If you want to compile with some specific fortran compiler, you must +# change the line below to the path of your fortran compiler. +# +FORTRAN=/usr/bin/gfortran +# +# Change the flags of the compilation if you want: +# +FLAGS= -O3 --fast-math + +################################################################### +# # +# Generally no modifications are required after this. # +# # +################################################################### +# +# Flags for compiling development version +# +GENCANFLAGS := $(FLAGS) +ifeq ($(MAKECMDGOALS),devel) +FLAGS = -Wall -fcheck=bounds -g -fbacktrace -ffpe-trap=zero,overflow,underflow +GENCANFLAGS = -fcheck=bounds -g -fbacktrace -ffpe-trap=zero,overflow,underflow +endif +ifeq ($(MAKECMDGOALS),perf) +FLAGS = -g -pg +GENCANFLAGS = -g -pg +endif +# +# Files required +# +oall = cenmass.o \ + gencan.o \ + pgencan.o \ + initial.o \ + title.o \ + setsizes.o \ + getinp.o \ + strlength.o \ + output.o \ + checkpoint.o \ + writesuccess.o \ + fparc.o \ + gparc.o \ + gwalls.o \ + comprest.o \ + comparegrad.o \ + packmol.o \ + polartocart.o \ + resetboxes.o \ + tobar.o \ + setijk.o \ + setibox.o \ + restmol.o \ + swaptype.o \ + swaptypemod.o \ + ahestetic.o \ + heuristics.o \ + flashsort.o \ + jacobi.o \ + random.o \ + sizes.o \ + usegencan.o \ + compute_data.o \ + flashmod.o \ + computef.o \ + computeg.o \ + input.o +# +# Linking +# +all : $(oall) + @echo " ------------------------------------------------------ " + @echo " Compiling packmol with $(FORTRAN) " + @echo " Flags: $(FLAGS) " + @echo " ------------------------------------------------------ " + @$(FORTRAN) -o packmol $(oall) $(FLAGS) + @\rm -f *.mod *.o + @echo " ------------------------------------------------------ " + @echo " Packmol succesfully built." + @echo " ------------------------------------------------------ " +# +# Compiling with flags for development +# +perf : devel +devel : $(oall) + @echo " ------------------------------------------------------ " + @echo " Compiling packmol with $(FORTRAN) " + @echo " Flags: $(FLAGS)" + @echo " ------------------------------------------------------ " + @$(FORTRAN) -o packmol $(oall) $(FLAGS) + @echo " ------------------------------------------------------ " + @echo " Packmol succesfully built. " + @echo " ------------------------------------------------------ " +# +# Modules +# +modules = sizes.o compute_data.o usegencan.o input.o flashmod.o swaptypemod.o ahestetic.o +sizes.o : sizes.f90 + @$(FORTRAN) $(FLAGS) -c sizes.f90 +compute_data.o : compute_data.f90 sizes.o + @$(FORTRAN) $(FLAGS) -c compute_data.f90 +input.o : input.f90 sizes.o + @$(FORTRAN) $(FLAGS) -c input.f90 +flashmod.o : flashmod.f90 sizes.o + @$(FORTRAN) $(FLAGS) -c flashmod.f90 +usegencan.o : usegencan.f90 sizes.o + @$(FORTRAN) $(FLAGS) -c usegencan.f90 +swaptypemod.o : swaptypemod.f90 + @$(FORTRAN) $(FLAGS) -c swaptypemod.f90 +ahestetic.o : ahestetic.f90 + @$(FORTRAN) $(FLAGS) -c ahestetic.f90 +# +# Code compiled only for all versions +# +cenmass.o : cenmass.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c cenmass.f90 +initial.o : initial.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c initial.f90 +title.o : title.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c title.f90 +setsizes.o : setsizes.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c setsizes.f90 +getinp.o : getinp.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c getinp.f90 +strlength.o : strlength.f90 + @$(FORTRAN) $(FLAGS) -c strlength.f90 +output.o : output.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c output.f90 +checkpoint.o : checkpoint.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c checkpoint.f90 +writesuccess.o : writesuccess.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c writesuccess.f90 +fparc.o : fparc.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c fparc.f90 +gparc.o : gparc.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c gparc.f90 +gwalls.o : gwalls.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c gwalls.f90 +comprest.o : comprest.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c comprest.f90 +comparegrad.o : comparegrad.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c comparegrad.f90 +packmol.o : packmol.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c packmol.f90 +polartocart.o : polartocart.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c polartocart.f90 +resetboxes.o : resetboxes.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c resetboxes.f90 +tobar.o : tobar.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c tobar.f90 +setijk.o : setijk.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c setijk.f90 +setibox.o : setibox.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c setibox.f90 +restmol.o : restmol.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c restmol.f90 +swaptype.o : swaptype.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c swaptype.f90 +heuristics.o : heuristics.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c heuristics.f90 +flashsort.o : flashsort.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c flashsort.f90 +jacobi.o : jacobi.f90 + @$(FORTRAN) $(FLAGS) -c jacobi.f90 +pgencan.o : pgencan.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c pgencan.f90 +gencan.o : gencan.f + @$(FORTRAN) $(GENCANFLAGS) -c gencan.f +random.o : random.f90 + @$(FORTRAN) $(FLAGS) -c random.f90 +computef.o : computef.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c computef.f90 +computeg.o : computeg.f90 $(modules) + @$(FORTRAN) $(FLAGS) -c computeg.f90 +# +# Clean build files +# +clean: + @\rm -f ./*.o ./*.mod +# +# Remove all build and executable files to upload to git +# +cleanall: + @\rm -f ./packmol ./*.o ./*.mod diff --git a/tests/packmol/README.md b/tests/packmol/README.md new file mode 100644 index 00000000..5e88317d --- /dev/null +++ b/tests/packmol/README.md @@ -0,0 +1,36 @@ +Packmol +======= + +Packmol - Creates Initial Configurations for Molecular Dynamics Simulations + +This page contains the version history of Packmol. You can download packmol from this page, but give preference to the official Packmol page: + +http://m3g.iqm.unicamp.br/packmol + +Detailed installation and usage instructions are available at this home-page. + +What is Packmol +--------------- + +Packmol creates an initial point for molecular dynamics simulations by packing molecules in defined regions of space. The packing guarantees that short range repulsive interactions do not disrupt the simulations. + +The great variety of types of spatial constraints that can be attributed to the molecules, or atoms within the molecules, makes it easy to create ordered systems, such as lamellar, spherical or tubular lipid layers. + +The user must provide only the coordinates of one molecule of each type, the number of molecules of each type and the spatial constraints that each type of molecule must satisfy. + +The package is compatible with input files of PDB, TINKER, XYZ and MOLDY formats. + +See http://m3g.iqm.unicamp.br/packmol for more information. + +References +---------- + +Please always cite one of the following references in publications for which Packmol was useful: + +L Martinez, R Andrade, EG Birgin, JM Martinez, Packmol: A package for building initial configurations for molecular dynamics simulations. Journal of Computational Chemistry, 30, 2157-2164, 2009. (http://www3.interscience.wiley.com/journal/122210103/abstract) + +JM Martinez, L Martinez, Packing optimization for the automated generation of complex system's initial configurations for molecular dynamics and docking. Journal of Computational Chemistry, 24, 819-825, 2003. +(http://www3.interscience.wiley.com/journal/104086246/abstract) + + + diff --git a/tests/packmol/ahestetic.f90 b/tests/packmol/ahestetic.f90 new file mode 100644 index 00000000..ed231f68 --- /dev/null +++ b/tests/packmol/ahestetic.f90 @@ -0,0 +1,21 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Module that contains some ahestetic output definitions +! +module ahestetic + + character(len=13), parameter :: dash1_line = "( 80('-') )",& + dash2_line = "(/,80('-') )",& + dash3_line = "(/,80('-'),/)" + + character(len=13), parameter :: hash1_line = "( 80('#') )",& + hash2_line = "(/,80('#') )",& + hash3_line = "(/,80('#'),/)" + + character(len=31), parameter :: prog1_line = "(' Packing:|0 ',tr60,'100%|' )",& + prog2_line = "(' Moving:|0 ',tr60,'100%|' )" + +end module ahestetic diff --git a/tests/packmol/cenmass.f90 b/tests/packmol/cenmass.f90 new file mode 100644 index 00000000..00bb7302 --- /dev/null +++ b/tests/packmol/cenmass.f90 @@ -0,0 +1,103 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Subroutine cenmass +! +! Computes the center of mass of free molecules and +! for fixed molecules, if required. +! +subroutine cenmass() + + use sizes + use compute_data, only : ntype, coor, idfirst, natoms + use input, only : keyword, amass, nlines, linestrut + + implicit none + integer :: k, iline + integer :: itype, iatom, idatom + double precision, allocatable :: cm(:,:), totm(:) + logical, allocatable :: domass(:) + + ! Allocate local vectors + + allocate(cm(ntype,3),totm(ntype),domass(ntype)) + + ! Setting the molecules for which the center of mass is computed + + do itype = 1, ntype + domass(itype) = .true. + end do + + do iline = 1, nlines + if(keyword(iline,1).eq.'fixed') then + do itype = 1, ntype + if(iline.gt.linestrut(itype,1).and. & + iline.lt.linestrut(itype,2)) then + domass(itype) = .false. + end if + end do + end if + end do + + do iline = 1, nlines + if(keyword(iline,1).eq.'centerofmass'.or. & + keyword(iline,1).eq.'center') then + do itype = 1, ntype + if(iline.gt.linestrut(itype,1).and. & + iline.lt.linestrut(itype,2)) then + domass(itype) = .true. + end if + end do + end if + end do + + ! Computing the center of mass + + do itype = 1, ntype + do k = 1, 3 + cm(itype, k) = 0.d0 + end do + end do + + do itype = 1, ntype + totm(itype) = 0.d0 + idatom = idfirst(itype) - 1 + do iatom = 1, natoms(itype) + idatom = idatom + 1 + totm(itype) = totm(itype) + amass(idatom) + end do + end do + + do itype = 1, ntype + idatom = idfirst(itype) - 1 + do iatom = 1, natoms(itype) + idatom = idatom + 1 + do k = 1, 3 + cm(itype, k) = cm(itype, k) + coor(idatom, k)*amass(idatom) + end do + end do + do k = 1, 3 + cm(itype, k) = cm(itype, k) / totm(itype) + end do + end do + + ! Putting molecules in their center of mass + + do itype = 1, ntype + if(domass(itype)) then + idatom = idfirst(itype) - 1 + do iatom = 1, natoms(itype) + idatom = idatom + 1 + do k = 1, 3 + coor(idatom, k) = coor(idatom, k) - cm(itype, k) + end do + end do + end if + end do + + deallocate(cm,totm,domass) + + return +end subroutine cenmass diff --git a/tests/packmol/checkpoint.f90 b/tests/packmol/checkpoint.f90 new file mode 100644 index 00000000..a40b6251 --- /dev/null +++ b/tests/packmol/checkpoint.f90 @@ -0,0 +1,116 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! + +! +! Subroutine that writes the last point obtained when +! a solution was not found +! + +subroutine checkpoint(n,x) + + use sizes + use compute_data + use input + use usegencan + use ahestetic + + implicit none + integer :: i + integer :: n + double precision :: x(n) + double precision :: fx + logical :: movebadprint + character(len=strl) :: xyzout_forced + + ! All molecules are important + + do i = 1, ntfix + comptype(i) = .true. + end do + + ! Call the subroutine that computes de function value + + call computef(n,x,fx) + + write(*,dash3_line) + write(*,"(& + &' Packmol was not able to find a solution to your',/,& + &' packing problem with the desired distance tolerance.',/,/,& + &' First of all, be sure if the molecules fit in the',/,& + &' regions specified and if the constraints were set',/,& + &' correctly. ',/,/,& + &' Secondly, try simply running it again with a different ',/,& + &' seed for the random number generator of the initial ',/,& + &' point. This is done by adding the keyword seed to the',/,& + &' input file, as in: ',/,/,& + &' seed 192911 ',/,/,& + &' The best configuration found has a function value of',/,& + &' f = ', e14.7,/,/,& + &' IMPORTANT: ',/,& + &' If the number of molecules and the restraints are',/,& + &' correct, it is still very likely that the current point',/,& + &' fits your needs if your purpose is to run a MD',/,& + &' simulation.',/,& + &' Therefore, we recommend to minimize the energy of the',/,& + &' solution found, equilibrate it and run with it as well.',/& + &)") fx + write(*,dash3_line) + + call output(n,x) + + write(*,*) ' The solution with the best function value was ' + write(*,*) ' written to the output file: ', trim(adjustl(xyzout)) + if ( crd ) write(*,*) ' ... and to CRD file: ', trim(adjustl(crdfile)) + write(*,dash1_line) + write(*,*) ' Forcing the solution to fit the constraints...' + + ! CALL GENCAN + + init1 = .true. + do i = 1, nloop + iprint1 = 0 + iprint2 = 0 + call pgencan(n,x,fx) + movebadprint = .false. + call movebad(n,x,fx,movebadprint) + end do + init1 = .false. + + write(*,*) + write(*,dash1_line) + xyzout_forced = trim(adjustl(xyzout))//'_FORCED' + call output(n,x) + + write(*,*) ' The forced point was writen to the ' + write(*,*) ' output file: ', trim(adjustl(xyzout_forced)) + if ( crd ) write(*,*) ' ... and to CRD file: ', trim(adjustl(crdfile)) + write(*,*) + write(*,*) ' If you want that the packing procedure continues' + write(*,*) ' for a longer time, add the following keyword ' + write(*,*) ' to the input file: ' + write(*,*) + write(*,*) ' nloop [integer] (ex: nloop 200) ' + write(*,*) + write(*,*) ' The default nloop value is 50 for each molecule.' + write(*,*) + + write(*,hash1_line) + write(*,*) ' ENDED WITHOUT PERFECT PACKING: ' + write(*,*) ' The output file:' + write(*,*) + write(*,*) ' ', trim(adjustl(xyzout)) + if ( crd ) write(*,*) ' (... and to CRD file: ', trim(adjustl(crdfile)), ')' + write(*,*) + write(*,*) ' contains the best solution found. ' + write(*,*) + write(*,*) ' Very likely, if the input data was correct, ' + write(*,*) ' it is a reasonable starting configuration.' + write(*,*) ' Check commentaries above for more details. ' + write(*,hash1_line) + + return +end subroutine checkpoint + diff --git a/tests/packmol/comparegrad.f90 b/tests/packmol/comparegrad.f90 new file mode 100644 index 00000000..19c6fdb5 --- /dev/null +++ b/tests/packmol/comparegrad.f90 @@ -0,0 +1,98 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! + +! +! Subroutine that performs finite difference and analytical gradient +! comparision. Used only for test purpouses +! + +subroutine comparegrad(n,x) + + use sizes + implicit none + + integer :: n, i, iworst + double precision :: x(n), fx, step, gcomp, gbest, eworst, & + error, steperror, stepbest + double precision, allocatable :: g(:) + real :: time0, tarray(2), etime + + ! Allocate local array + + allocate(g(nn)) + + write(*,*) + write(*,*) ' Comparing analytical and finite-difference ' + write(*,*) ' gradients... may take a while. ' + write(*,*) + write(*,*) ' Five first center of masses and angles of tested point: ' + do i = 1, 15, 3 + write(*,"( i4,6(tr2,f8.3) )") (i+2)/3, x(i), x(i+1), x(i+2), x(n/2+i),& + x(n/2+i+1),x(n/2+i+2) + end do + write(*,*) + write(*,*) ' Computing gradient ... ' + + call computef(n,x,fx) + write(*,*) ' Function value on test point: ', fx + open(98, file = 'chkgrad.log',status='unknown') + write(98, *)'Function Value = ', fx + call computeg(n,x,g) + + write(98,"( t2,'Component',t16,'Analytical',t33,'Discrete', & + &t51,'Error',t62,'Best step' )") + time0 = etime(tarray) + eworst = 0.d0 + do i = 1, n + if(etime(tarray)-time0.gt.10.) then + time0 = etime(tarray) + write(*,*) ' Computing the ',i,'th of ',n,' components. Worst error: ', eworst + end if + error = 1.d20 + step = 1.d-2 + do while(error.gt.1.d-6.and.step.ge.1.d-20) + call discret(i,n,x,gcomp,step) + if(dmin1(abs(g(i)),abs(gcomp)).gt.1.d-10) then + steperror = abs( ( gcomp - g(i) ) / g(i) ) + else + steperror = abs( gcomp - g(i) ) + end if + if( steperror .lt. error ) then + error = steperror + gbest = gcomp + stepbest = step + end if + step = step / 10.d0 + end do + write(98,"(i10,5(tr2,d13.7))") i, g(i), gbest, error, stepbest + if(error.gt.eworst) then + iworst = i + eworst = error + end if + end do + write(98,*) 'Maximum difference = ', iworst,' Error= ', eworst + write(*,*) ' Done. ' + stop + +end subroutine comparegrad + +subroutine discret(icomp,n,x,gcomp,step) + + implicit none + integer :: n, icomp + double precision :: save, step, x(n), fplus, fminus, gcomp + + save = x(icomp) + x(icomp) = save + step + call computef(n,x,fplus) + x(icomp) = save - step + call computef(n,x,fminus) + gcomp = (fplus - fminus) / (2.d0 * step) + x(icomp) = save + + return +end subroutine discret + diff --git a/tests/packmol/compile_cmake.sh b/tests/packmol/compile_cmake.sh new file mode 100644 index 00000000..ecdd92a6 --- /dev/null +++ b/tests/packmol/compile_cmake.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Fortran compiler to use +export FC=gfortran +# Compiler flags to use +export FFLAGS="-g -O2 -Wall" +#export FFLAGS="-g -O2 -Wall -fbounds-check" +#export FFLAGS="-g -O0 -Wall -fbounds-check" + +# Installation directory +export target=$(pwd) # this installs packmol under bin/ in the present directory + +# Number of parallel processes in build +export npar=4 + +# No changes should be necessary hereafter. +if [[ ! -d objdir ]]; then + mkdir objdir +fi +cd objdir +cmake .. \ + -DCMAKE_INSTALL_PREFIX=${target} \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_Fortran_FLAGS_RELEASE:STRING="-DNDEBUG" +make -j ${npar} install VERBOSE=1 +cd .. diff --git a/tests/packmol/comprest.f90 b/tests/packmol/comprest.f90 new file mode 100644 index 00000000..72addb37 --- /dev/null +++ b/tests/packmol/comprest.f90 @@ -0,0 +1,168 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! +! Subroutine comprest: Compute the function value relative to +! to the restrictions for one atom +! + +subroutine comprest(icart,f) + + use sizes + use compute_data, only : xcart, restpars, scale, scale2, nratom, ityperest, iratom + + implicit none + integer :: iratcount, irest, icart + double precision :: xmin, ymin, zmin, clength, a1, a2, a3, a4, w, b1, b2, b3, d, a5, a6 + double precision :: f + double precision :: xmax, ymax, zmax + double precision :: v1, v2, v3 + double precision :: vnorm + + f = 0.d0 + do iratcount = 1, nratom(icart) + irest = iratom(icart,iratcount) + if(ityperest(irest).eq.2) then + clength = restpars(irest,4) + xmin = restpars(irest,1) + ymin = restpars(irest,2) + zmin = restpars(irest,3) + xmax = restpars(irest,1) + clength + ymax = restpars(irest,2) + clength + zmax = restpars(irest,3) + clength + a1 = dmin1(xcart(icart,1) - xmin, 0.d0) + a2 = dmin1(xcart(icart,2) - ymin, 0.d0) + a3 = dmin1(xcart(icart,3) - zmin, 0.d0) + f = f + scale*(a1 * a1 + a2 * a2 + a3 * a3) + a1 = dmax1(xcart(icart,1) - xmax, 0.d0) + a2 = dmax1(xcart(icart,2) - ymax, 0.d0) + a3 = dmax1(xcart(icart,3) - zmax, 0.d0) + f = f + scale*(a1 * a1 + a2 * a2 + a3 * a3) + else if(ityperest(irest).eq.3) then + xmin = restpars(irest,1) + ymin = restpars(irest,2) + zmin = restpars(irest,3) + xmax = restpars(irest,4) + ymax = restpars(irest,5) + zmax = restpars(irest,6) + a1 = dmin1(xcart(icart,1) - xmin, 0.d0) + a2 = dmin1(xcart(icart,2) - ymin, 0.d0) + a3 = dmin1(xcart(icart,3) - zmin, 0.d0) + f = f + scale*(a1 * a1 + a2 * a2 + a3 * a3) + a1 = dmax1(xcart(icart,1) - xmax, 0.d0) + a2 = dmax1(xcart(icart,2) - ymax, 0.d0) + a3 = dmax1(xcart(icart,3) - zmax, 0.d0) + f = f + scale*(a1 * a1 + a2 * a2 + a3 * a3) + else if(ityperest(irest).eq.4) then + w = (xcart(icart,1)-restpars(irest,1))**2 + & + (xcart(icart,2)-restpars(irest,2))**2 + & + (xcart(icart,3)-restpars(irest,3))**2 - & + restpars(irest,4)**2 + a1 = dmax1(w,0.d0) + f = f + scale2*a1*a1 + else if(ityperest(irest).eq.5) then + a1 = (xcart(icart,1)-restpars(irest,1))**2 / restpars(irest,4)**2 + a2 = (xcart(icart,2)-restpars(irest,2))**2 / restpars(irest,5)**2 + a3 = (xcart(icart,3)-restpars(irest,3))**2 / restpars(irest,6)**2 + a4 = restpars(irest,7)**2 + w = a1 + a2 + a3 - a4 + a1 = dmax1(w,0.d0) + f = f + scale2*a1*a1 + else if(ityperest(irest).eq.6) then + xmin = restpars(irest,1) + ymin = restpars(irest,2) + zmin = restpars(irest,3) + xmax = restpars(irest,1) + restpars(irest,4) + ymax = restpars(irest,2) + restpars(irest,4) + zmax = restpars(irest,3) + restpars(irest,4) + a1 = dmax1(xcart(icart,1) - xmin,0.d0) + a2 = dmax1(xcart(icart,2) - ymin,0.d0) + a3 = dmax1(xcart(icart,3) - zmin,0.d0) + a4 = dmax1(xmax - xcart(icart,1),0.d0) + a5 = dmax1(ymax - xcart(icart,2),0.d0) + a6 = dmax1(zmax - xcart(icart,3),0.d0) + f = f + a1*a2*a3*a4*a5*a6 + else if(ityperest(irest).eq.7) then + xmin = restpars(irest,1) + ymin = restpars(irest,2) + zmin = restpars(irest,3) + xmax = restpars(irest,4) + ymax = restpars(irest,5) + zmax = restpars(irest,6) + a1 = dmax1(xcart(icart,1) - xmin,0.d0) + a2 = dmax1(xcart(icart,2) - ymin,0.d0) + a3 = dmax1(xcart(icart,3) - zmin,0.d0) + a4 = dmax1(xmax - xcart(icart,1),0.d0) + a5 = dmax1(ymax - xcart(icart,2),0.d0) + a6 = dmax1(zmax - xcart(icart,3),0.d0) + f = f + a1*a2*a3*a4*a5*a6 + else if(ityperest(irest).eq.8) then + w = (xcart(icart,1)-restpars(irest,1))**2 + & + (xcart(icart,2)-restpars(irest,2))**2 + & + (xcart(icart,3)-restpars(irest,3))**2 - & + restpars(irest,4)**2 + a1 = dmin1(w,0.d0) + f = f + scale2*a1*a1 + else if(ityperest(irest).eq.9) then + a1 = (xcart(icart,1)-restpars(irest,1))**2 / restpars(irest,4)**2 + a2 = (xcart(icart,2)-restpars(irest,2))**2 / restpars(irest,5)**2 + a3 = (xcart(icart,3)-restpars(irest,3))**2 / restpars(irest,6)**2 + a4 = restpars(irest,7)**2 + w = a1 + a2 + a3 - a4 + a1 = dmin1(w,0.d0) + f = f + a1*a1 + else if(ityperest(irest).eq.10) then + w = restpars(irest,1)*xcart(icart,1) + & + restpars(irest,2)*xcart(icart,2) + & + restpars(irest,3)*xcart(icart,3) - & + restpars(irest,4) + a1 = dmin1(w,0.d0) + f = f + scale * a1*a1 + else if(ityperest(irest).eq.11) then + w = restpars(irest,1)*xcart(icart,1) + & + restpars(irest,2)*xcart(icart,2) + & + restpars(irest,3)*xcart(icart,3) - & + restpars(irest,4) + a1 = dmax1(w,0.d0) + f = f + scale * a1*a1 + else if(ityperest(irest).eq.12) then + a1 = xcart(icart,1) - restpars(irest,1) + a2 = xcart(icart,2) - restpars(irest,2) + a3 = xcart(icart,3) - restpars(irest,3) + vnorm = sqrt(restpars(irest,4)**2 + restpars(irest,5)**2 + restpars(irest,6)**2) + v1 = restpars(irest,4)/vnorm + v2 = restpars(irest,5)/vnorm + v3 = restpars(irest,6)/vnorm + b1 = v1 * a1 + b2 = v2 * a2 + b3 = v3 * a3 + w = b1 + b2 + b3 + d = ( a1 - v1*w )**2 + ( a2 - v2*w )**2 + ( a3 - v3*w )**2 + f = f + scale2 * ( & + dmax1(-w , 0.d0)**2 + & + dmax1(w - restpars(irest,9), 0.d0)**2 + & + dmax1(d - restpars(irest,7)**2 , 0.d0 )**2 ) + else if(ityperest(irest).eq.13) then + a1 = xcart(icart,1) - restpars(irest,1) + a2 = xcart(icart,2) - restpars(irest,2) + a3 = xcart(icart,3) - restpars(irest,3) + vnorm = sqrt(restpars(irest,4)**2 + restpars(irest,5)**2 + restpars(irest,6)**2) + v1 = restpars(irest,4)/vnorm + v2 = restpars(irest,5)/vnorm + v3 = restpars(irest,6)/vnorm + b1 = v1 * a1 + b2 = v2 * a2 + b3 = v3 * a3 + w = b1 + b2 + b3 + d = ( a1 - v1*w )**2 +( a2 - v2*w )**2 + ( a3 - v3*w )**2 + f = f + scale2 * ( & + dmin1(-w , 0.d0)**2 * & + dmin1(w - restpars(irest,9), 0.d0)**2 * & + dmin1(d - restpars(irest,7)**2 , 0.d0 )**2 ) + end if + end do + return +end subroutine comprest + diff --git a/tests/packmol/compute_data.f90 b/tests/packmol/compute_data.f90 new file mode 100644 index 00000000..655dc631 --- /dev/null +++ b/tests/packmol/compute_data.f90 @@ -0,0 +1,63 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +module compute_data + + use sizes + + integer :: ntotmol, ntype, natfix, ntotat + integer :: nboxes(3), nb2(3) + + integer, allocatable :: nmols(:) ! (ntype) + integer, allocatable :: natoms(:) ! (ntype) + integer, allocatable :: idfirst(:) ! (ntype) + integer, allocatable :: nratom(:) ! (ntotat) + integer, allocatable :: iratom(:,:) ! (ntotat,mrperatom) + integer, allocatable :: ityperest(:) ! (maxrest) + integer, allocatable :: ibmol(:) ! (ntotat) + integer, allocatable :: ibtype(:) ! (ntotat) + + double precision :: scale, scale2 + double precision :: fdist, frest + double precision :: sizemin(3), sizemax(3) + double precision :: boxl(3) + + double precision, allocatable :: xcart(:,:) ! (ntotat,3) + double precision, allocatable :: coor(:,:) ! (ntotat,3) + double precision, allocatable :: restpars(:,:) ! (maxrest,9) + double precision, allocatable :: rot_bound(:,:,:) ! (ntype,3,2) + double precision, allocatable :: radius(:), radius_ini(:), fscale(:) ! (ntotat) + double precision, allocatable :: short_radius(:), short_radius_scale(:) ! ntotat + double precision, allocatable :: gxcar(:,:) ! (ntotat,3) + + double precision, allocatable :: fdist_atom(:), frest_atom(:) ! (ntotat) + double precision, allocatable :: dmax(:) ! (ntype) + double precision, allocatable :: cmxmin(:), cmymin(:), cmzmin(:) ! (ntype) + double precision, allocatable :: cmxmax(:), cmymax(:), cmzmax(:) ! (ntype) + + logical, allocatable :: constrain_rot(:,:) ! (ntype,3) + logical, allocatable :: comptype(:) ! (ntype) + logical, allocatable :: fixedatom(:) ! (ntotat) + logical, allocatable :: use_short_radius(:) ! ntotat + logical :: init1, move + + ! For linked lists + integer, allocatable :: latomnext(:) ! (ntotat) + integer, allocatable :: latomfirst(:,:,:) ! (0:nbp+1,0:nbp+1,0:nbp+1) + integer, allocatable :: latomfix(:,:,:) ! (0:nbp+1,0:nbp+1,0:nbp+1) + + ! For movebad + double precision, allocatable :: fmol(:), radiuswork(:) ! (ntotat) + + ! For restmol + double precision, allocatable :: xmol(:) ! (nn) + logical, allocatable :: compsafe(:) ! (ntype) + + ! For boxes with atoms linked lists + integer :: lboxfirst + integer, allocatable :: lboxnext(:) ! ((nbp+2)**3) + logical, allocatable :: hasfree(:,:,:) ! (0:nbp+1,0:nbp+1,0:nbp+1) + +end module compute_data diff --git a/tests/packmol/computef.f90 b/tests/packmol/computef.f90 new file mode 100644 index 00000000..e01890ba --- /dev/null +++ b/tests/packmol/computef.f90 @@ -0,0 +1,220 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Subroutine that computes the function value +! + +subroutine computef(n,x,f) + + use sizes + use compute_data + use input, only : fix + implicit none + + integer :: n, i, j, k, ibox + integer :: ilugan, ilubar, icart, itype, imol, iatom, idatom, & + iboxx, iboxy, iboxz + + double precision :: v1(3), v2(3), v3(3) + double precision :: x(n) + double precision :: f,fparc,fplus + double precision :: xtemp, ytemp, ztemp + double precision :: xbar, ybar, zbar + double precision :: beta, gama, teta + + ! Reset function value + + f = 0.d0 + frest = 0.d0 + fdist = 0.d0 + + ! Reset boxes + + if(.not.init1) call resetboxes() + + ! Transform baricenter and angles into cartesian coordinates + ! Computes cartesian coordinates from vector x and coor + + ilubar = 0 + ilugan = ntotmol*3 + icart = 0 + + do itype = 1, ntype + if(.not.comptype(itype)) then + icart = icart + nmols(itype)*natoms(itype) + else + do imol = 1, nmols(itype) + + xbar = x(ilubar+1) + ybar = x(ilubar+2) + zbar = x(ilubar+3) + + ! Computing the rotation matrix + + beta = x(ilugan+1) + gama = x(ilugan+2) + teta = x(ilugan+3) + + call eulerrmat(beta,gama,teta,v1,v2,v3) + + ! Looping over the atoms of this molecule + + idatom = idfirst(itype) - 1 + do iatom = 1, natoms(itype) + + icart = icart + 1 + idatom = idatom + 1 + + ! Computing the cartesian coordinates for this atom + + call compcart(icart,xbar,ybar,zbar, & + coor(idatom,1),coor(idatom,2),coor(idatom,3), & + v1,v2,v3) + + ! Adding to f the value relative to constraints for this atom + + call comprest(icart,fplus) + f = f + fplus + frest = dmax1(frest,fplus) + if(move) frest_atom(icart) = frest_atom(icart) + fplus + + ! Putting atoms in their boxes + + if(.not.init1) then + + xtemp = xcart(icart,1) - sizemin(1) + ytemp = xcart(icart,2) - sizemin(2) + ztemp = xcart(icart,3) - sizemin(3) + + iboxx = int(xtemp/boxl(1)) + 1 + iboxy = int(ytemp/boxl(2)) + 1 + iboxz = int(ztemp/boxl(3)) + 1 + + if(xtemp.le.0) iboxx = 1 + if(ytemp.le.0) iboxy = 1 + if(ztemp.le.0) iboxz = 1 + if(iboxx.gt.nboxes(1)) iboxx = nboxes(1) + if(iboxy.gt.nboxes(2)) iboxy = nboxes(2) + if(iboxz.gt.nboxes(3)) iboxz = nboxes(3) + + ! Atom linked list + + latomnext(icart) = latomfirst(iboxx,iboxy,iboxz) + latomfirst(iboxx,iboxy,iboxz) = icart + + ! Box with atoms linked list + + if ( .not. hasfree(iboxx,iboxy,iboxz) ) then + hasfree(iboxx,iboxy,iboxz) = .true. + call ijk_to_ibox(iboxx,iboxy,iboxz,ibox) + lboxnext(ibox) = lboxfirst + lboxfirst = ibox + + ! Add boxes with fixed atoms which are vicinal to this box, and + ! are behind + + if ( fix ) then + + call add_box_behind(iboxx-1,iboxy,iboxz) + call add_box_behind(iboxx,iboxy-1,iboxz) + call add_box_behind(iboxx,iboxy,iboxz-1) + + call add_box_behind(iboxx,iboxy-1,iboxz+1) + call add_box_behind(iboxx,iboxy-1,iboxz-1) + call add_box_behind(iboxx-1,iboxy+1,iboxz) + call add_box_behind(iboxx-1,iboxy,iboxz+1) + call add_box_behind(iboxx-1,iboxy-1,iboxz) + call add_box_behind(iboxx-1,iboxy,iboxz-1) + + call add_box_behind(iboxx-1,iboxy+1,iboxz+1) + call add_box_behind(iboxx-1,iboxy+1,iboxz-1) + call add_box_behind(iboxx-1,iboxy-1,iboxz+1) + call add_box_behind(iboxx-1,iboxy-1,iboxz-1) + + end if + + end if + + ibtype(icart) = itype + ibmol(icart) = imol + + end if + + end do + + ilugan = ilugan + 3 + ilubar = ilubar + 3 + + end do + end if + end do + + if(init1) return + + ! Minimum distance function evaluation + + ibox = lboxfirst + do while( ibox > 0 ) + + call ibox_to_ijk(ibox,i,j,k) + + icart = latomfirst(i,j,k) + do while( icart > 0 ) + + if(comptype(ibtype(icart))) then + + ! Interactions inside box + + f = f + fparc(icart,latomnext(icart)) + + ! Interactions of boxes that share faces + + f = f + fparc(icart,latomfirst(i+1,j,k)) + f = f + fparc(icart,latomfirst(i,j+1,k)) + f = f + fparc(icart,latomfirst(i,j,k+1)) + + ! Interactions of boxes that share axes + + f = f + fparc(icart,latomfirst(i+1,j+1,k)) + f = f + fparc(icart,latomfirst(i+1,j,k+1)) + f = f + fparc(icart,latomfirst(i+1,j-1,k)) + f = f + fparc(icart,latomfirst(i+1,j,k-1)) + f = f + fparc(icart,latomfirst(i,j+1,k+1)) + f = f + fparc(icart,latomfirst(i,j+1,k-1)) + + ! Interactions of boxes that share vertices + + f = f + fparc(icart,latomfirst(i+1,j+1,k+1)) + f = f + fparc(icart,latomfirst(i+1,j+1,k-1)) + f = f + fparc(icart,latomfirst(i+1,j-1,k+1)) + f = f + fparc(icart,latomfirst(i+1,j-1,k-1)) + + end if + + icart = latomnext(icart) + end do + + ibox = lboxnext(ibox) + end do + + return +end subroutine computef + +subroutine add_box_behind(i,j,k) + + use sizes + use compute_data + implicit none + integer :: ibox, i, j, k + + if ( .not. hasfree(i,j,k) .and. latomfix(i,j,k) /= 0 ) then + hasfree(i,j,k) = .true. + call ijk_to_ibox(i,j,k,ibox) + lboxnext(ibox) = lboxfirst + lboxfirst = ibox + end if + +end subroutine add_box_behind + diff --git a/tests/packmol/computeg.f90 b/tests/packmol/computeg.f90 new file mode 100644 index 00000000..91391836 --- /dev/null +++ b/tests/packmol/computeg.f90 @@ -0,0 +1,309 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Subroutine that computes the analytical derivatives +! + +subroutine computeg(n,x,g) + + use sizes + use compute_data + use input, only : fix + implicit none + + integer :: n + integer :: idatom, iatom, irest + integer :: i, j, k, ilubar, ilugan, icart, itype, imol + integer :: ibox, iboxx, iboxy, iboxz + integer :: k1, k2 + integer :: iratcount + + double precision :: x(n), g(n) + double precision :: dv1beta(3), dv1gama(3), dv1teta(3),& + dv2beta(3), dv2gama(3), dv2teta(3),& + dv3beta(3), dv3gama(3), dv3teta(3) + double precision :: v1(3), v2(3), v3(3) + double precision :: xbar, ybar, zbar + double precision :: xtemp, ytemp, ztemp + double precision :: beta, gama, teta, cb, sb, cg, sg, ct, st + + ! Reset gradients + + do i = 1, ntotat + do j = 1, 3 + gxcar(i,j) = 0.d0 + end do + end do + + ! Reset boxes + + if(.not.init1) call resetboxes() + + ! Transform baricenter and angles into cartesian coordinates + + ! Computes cartesian coordinates from vector x and coor + + ilubar = 0 + ilugan = ntotmol*3 + icart = 0 + + do itype = 1, ntype + + if(.not.comptype(itype)) then + icart = icart + nmols(itype)*natoms(itype) + else + do imol = 1, nmols(itype) + + xbar = x(ilubar + 1) + ybar = x(ilubar + 2) + zbar = x(ilubar + 3) + + ! Compute the rotation matrix + + beta = x(ilugan + 1) + gama = x(ilugan + 2) + teta = x(ilugan + 3) + + call eulerrmat(beta,gama,teta,v1,v2,v3) + + idatom = idfirst(itype) - 1 + do iatom = 1, natoms(itype) + + icart = icart + 1 + idatom = idatom + 1 + + call compcart(icart,xbar,ybar,zbar, & + coor(idatom,1),coor(idatom,2),coor(idatom,3), & + v1,v2,v3) + + ! Gradient relative to the wall distace + + do iratcount = 1, nratom(icart) + irest = iratom(icart,iratcount) + call gwalls(icart,irest) + end do + + if(.not.init1) then + xtemp = xcart(icart,1) - sizemin(1) + ytemp = xcart(icart,2) - sizemin(2) + ztemp = xcart(icart,3) - sizemin(3) + + iboxx = int(xtemp/boxl(1)) + 1 + iboxy = int(ytemp/boxl(2)) + 1 + iboxz = int(ztemp/boxl(3)) + 1 + + if(xtemp.le.0) iboxx = 1 + if(ytemp.le.0) iboxy = 1 + if(ztemp.le.0) iboxz = 1 + if(iboxx.gt.nboxes(1)) iboxx = nboxes(1) + if(iboxy.gt.nboxes(2)) iboxy = nboxes(2) + if(iboxz.gt.nboxes(3)) iboxz = nboxes(3) + + ! Atom linked list + + latomnext(icart) = latomfirst(iboxx,iboxy,iboxz) + latomfirst(iboxx,iboxy,iboxz) = icart + + ! Box with atoms linked list + + if ( .not. hasfree(iboxx,iboxy,iboxz) ) then + hasfree(iboxx,iboxy,iboxz) = .true. + call ijk_to_ibox(iboxx,iboxy,iboxz,ibox) + lboxnext(ibox) = lboxfirst + lboxfirst = ibox + + ! Add boxes with fixed atoms which are vicinal to this box, and + ! are behind + + if ( fix ) then + + call add_box_behind(iboxx-1,iboxy,iboxz) + call add_box_behind(iboxx,iboxy-1,iboxz) + call add_box_behind(iboxx,iboxy,iboxz-1) + + call add_box_behind(iboxx,iboxy-1,iboxz+1) + call add_box_behind(iboxx,iboxy-1,iboxz-1) + call add_box_behind(iboxx-1,iboxy+1,iboxz) + call add_box_behind(iboxx-1,iboxy,iboxz+1) + call add_box_behind(iboxx-1,iboxy-1,iboxz) + call add_box_behind(iboxx-1,iboxy,iboxz-1) + + call add_box_behind(iboxx-1,iboxy+1,iboxz+1) + call add_box_behind(iboxx-1,iboxy+1,iboxz-1) + call add_box_behind(iboxx-1,iboxy-1,iboxz+1) + call add_box_behind(iboxx-1,iboxy-1,iboxz-1) + + end if + + end if + + ibtype(icart) = itype + ibmol(icart) = imol + end if + + end do + ilugan = ilugan + 3 + ilubar = ilubar + 3 + end do + end if + end do + + if( .not. init1 ) then + + ! + ! Gradient relative to minimum distance + ! + + ibox = lboxfirst + do while( ibox > 0 ) + + call ibox_to_ijk(ibox,i,j,k) + + icart = latomfirst(i,j,k) + do while ( icart .ne. 0 ) + + if(comptype(ibtype(icart))) then + + ! Interactions inside box + + call gparc(icart,latomnext(icart)) + + ! Interactions of boxes that share faces + + call gparc(icart,latomfirst(i+1,j,k)) + call gparc(icart,latomfirst(i,j+1,k)) + call gparc(icart,latomfirst(i,j,k+1)) + + ! Interactions of boxes that share axes + + call gparc(icart,latomfirst(i+1,j+1,k)) + call gparc(icart,latomfirst(i+1,j,k+1)) + call gparc(icart,latomfirst(i+1,j-1,k)) + call gparc(icart,latomfirst(i+1,j,k-1)) + call gparc(icart,latomfirst(i,j+1,k+1)) + call gparc(icart,latomfirst(i,j+1,k-1)) + + ! Interactions of boxes that share vertices + + call gparc(icart,latomfirst(i+1,j+1,k+1)) + call gparc(icart,latomfirst(i+1,j+1,k-1)) + call gparc(icart,latomfirst(i+1,j-1,k+1)) + call gparc(icart,latomfirst(i+1,j-1,k-1)) + + end if + + icart = latomnext(icart) + end do + + ibox = lboxnext(ibox) + end do + + end if + + ! Computing the gradient using chain rule + + do i = 1, n + g(i) = 0.d0 + end do + + k1 = 0 + k2 = ntotmol * 3 + + icart = 0 + do itype = 1, ntype + + if(.not.comptype(itype)) then + icart = icart + nmols(itype)*natoms(itype) + else + do imol = 1, nmols(itype) + + beta = x(k2 + 1) + gama = x(k2 + 2) + teta = x(k2 + 3) + + cb = dcos(beta) + sb = dsin(beta) + cg = dcos(gama) + sg = dsin(gama) + ct = dcos(teta) + st = dsin(teta) + + dv1beta(1) = - cb * sg * ct - sb * cg + dv2beta(1) = - sb * sg * ct + cb * cg + dv3beta(1) = 0.d0 + + dv1gama(1) = - sb * cg * ct - cb * sg + dv2gama(1) = cb * cg * ct - sb * sg + dv3gama(1) = cg * st + + dv1teta(1) = sb * sg * st + dv2teta(1) = - cb * sg * st + dv3teta(1) = sg * ct + + dv1beta(2) = - cb * cg * ct + sb * sg + dv2beta(2) = - sb * cg * ct - cb * sg + dv3beta(2) = 0.d0 + + dv1gama(2) = sb * sg * ct - cb * cg + dv2gama(2) = - sg * cb * ct - cg * sb + dv3gama(2) = - sg * st + + dv1teta(2) = sb * cg * st + dv2teta(2) = - cb * cg * st + + dv3teta(2) = cg * ct + + dv1beta(3) = cb * st + dv2beta(3) = sb * st + dv3beta(3) = 0.d0 + + dv1gama(3) = 0.d0 + dv2gama(3) = 0.d0 + dv3gama(3) = 0.d0 + + dv1teta(3) = sb * ct + dv2teta(3) = - cb * ct + dv3teta(3) = - st + + idatom = idfirst(itype) - 1 + do iatom = 1, natoms(itype) + + icart = icart + 1 + idatom = idatom + 1 + + do k = 1, 3 + g(k1+k) = g(k1+k) + gxcar(icart, k) + end do + + do k = 1, 3 + g(k2 + 1) = g(k2 + 1) & + + (coor(idatom,1) * dv1beta(k) & + + coor(idatom, 2) * dv2beta(k) & + + coor(idatom, 3) * dv3beta(k)) & + * gxcar(icart, k) + + g(k2 + 2) = g(k2 + 2) & + + (coor(idatom,1) * dv1gama(k) & + + coor(idatom, 2) * dv2gama(k) & + + coor(idatom, 3) * dv3gama(k)) & + * gxcar(icart, k) + + g(k2 + 3) = g(k2 + 3) & + + (coor(idatom,1) * dv1teta(k) & + + coor(idatom, 2) * dv2teta(k) & + + coor(idatom, 3) * dv3teta(k)) & + * gxcar(icart, k) + end do + + end do + k2 = k2 + 3 + k1 = k1 + 3 + end do + end if + end do + + return +end subroutine computeg + diff --git a/tests/packmol/configure b/tests/packmol/configure new file mode 100755 index 00000000..6ed55049 --- /dev/null +++ b/tests/packmol/configure @@ -0,0 +1,52 @@ +#!/bin/bash +# +# Configure file for packmol +# +# If you want to set your own compiler, run the script with: +# +# ./configure gfortran +# +# where "gfortran" can be substituted by the compiler you use, +# put the path if it is not in the path, for example, +# /usr/bin/gfortran +# +# +# List of possible compilers: +compilerlist=" +$1 +gfortran +f77 +fort77 +ifc +ifort +" +# +# +IFS=$'\n' + +for searchcompiler in $compilerlist; do + compiler=`which $searchcompiler` + if [ "$compiler" \> " " ]; then + echo "Setting compiler to $compiler" + makefile=`cat Makefile` + \rm -f Makefile + for line in $makefile; do + echo ${line//"FORTRAN="*/"FORTRAN=$compiler"} >> Makefile + done + exit + fi +done + +echo " " +echo " ERROR: Could not find any fortran compiler." +echo " " +echo " To use your own compiler, run this script with: " +echo " " +echo " ./configure /path/to/compiler/yourcompiler " +echo " " +echo " Otherwise, install one of the following compilers" +echo " and run this configure script again:" +echo " " +echo " gfortran, f77, fort77, ifc, ifort" +echo " " + diff --git a/tests/packmol/data_types.f90 b/tests/packmol/data_types.f90 new file mode 100644 index 00000000..9c5eb19f --- /dev/null +++ b/tests/packmol/data_types.f90 @@ -0,0 +1,10 @@ + +type input_file + + use sizes + logical :: tinker, pdb, xyz, moldy + integer :: nlines + character(len=strl), allocatable :: line(:) + character(len=strl), allocatable :: keyword(:,:) + +end type input_file diff --git a/tests/packmol/flashmod.f90 b/tests/packmol/flashmod.f90 new file mode 100644 index 00000000..84aaa749 --- /dev/null +++ b/tests/packmol/flashmod.f90 @@ -0,0 +1,21 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! + +! +! Arrays required by the flashsort package. Used only in heuristics, but +! defined here to be allocated dynamically +! + +module flashsort + + use sizes + implicit none + integer, allocatable :: indflash(:) ! (ntotat) + integer, allocatable :: lflash(:) ! (ntotat) + integer :: mflash + +end module flashsort + diff --git a/tests/packmol/flashsort.f90 b/tests/packmol/flashsort.f90 new file mode 100644 index 00000000..0112e3cd --- /dev/null +++ b/tests/packmol/flashsort.f90 @@ -0,0 +1,95 @@ +!cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +! c +! Subroutine Flash1 c +! SORTS ARRAY A WITH N ELEMENTS BY USE OF INDEX VECTOR L c +! OF DIMENSION M WITH M ABOUT 0.1 N. c +! Karl-Dietrich Neubert, FlashSort1 Algorithm c +! in Dr. Dobb's Journal Feb.1998,p.123 c +! c +!cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + + subroutine flash1 (A, N, L, M, ind) + + implicit none + double precision :: a(*), anmin, c1, hold, flash + integer :: L(*), ind(*), i, n, nmax, m, k, ihold, nmove, j, iflash +! ============================ CLASS FORMATION ===== + + + do i = 1, n + ind(i) = i + end do + + ANMIN=A(1) + NMAX=1 + DO I=1,N + IF( A(I).LT.ANMIN) ANMIN=A(I) + IF( A(I).GT.A(NMAX)) NMAX=I + END DO + + IF (ANMIN.EQ.A(NMAX)) RETURN + C1=(M - 1) / (A(NMAX) - ANMIN) + DO K=1,M + L(K)=0 + END DO + DO I=1,N + K=1 + INT(C1 * (A(I) - ANMIN)) + L(K)=L(K) + 1 + END DO + DO K=2,M + L(K)=L(K) + L(K - 1) + END DO + HOLD=A(NMAX) + A(NMAX)=A(1) + A(1)=HOLD + + ihold = ind(nmax) + ind(nmax) = ind(1) + ind(1) = ihold + + +! =============================== PERMUTATION ===== + NMOVE=0 + J=1 + K=M + DO WHILE (NMOVE.LT.N - 1) + DO WHILE (J.GT.L(K)) + J=J + 1 + K=1 + INT(C1 * (A(J) - ANMIN)) + END DO + FLASH=A(J) + iflash=ind(j) + + DO WHILE (.NOT.(J.EQ.L(K) + 1)) + K=1 + INT(C1 * (FLASH - ANMIN)) + HOLD=A(L(K)) + ihold = ind(L(k)) + A(L(K))=FLASH + ind(L(k)) = iflash + iflash = ihold + FLASH=HOLD + L(K)=L(K) - 1 + NMOVE=NMOVE + 1 + END DO + END DO + +! ========================= STRAIGHT INSERTION ===== + DO I=N-2,1,-1 + IF (A(I + 1).LT.A(I)) THEN + HOLD=A(I) + ihold = ind(i) + J=I + DO WHILE (A(J + 1).LT.HOLD) + A(J)=A(J + 1) + ind(j) = ind(j+1) + J=J + 1 + END DO + A(J)=HOLD + ind(j) = ihold + ENDIF + END DO + +! =========================== RETURN,END FLASH1 ===== + RETURN + END + diff --git a/tests/packmol/fparc.f90 b/tests/packmol/fparc.f90 new file mode 100644 index 00000000..2b876c3e --- /dev/null +++ b/tests/packmol/fparc.f90 @@ -0,0 +1,77 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Function that computes the atom-to-atom component of the objective +! function +! + +double precision function fparc(icart,firstjcart) + + use sizes + use compute_data + implicit none + + ! SCALAR ARGUMENTS + integer :: icart,firstjcart + + ! LOCAL SCALARS + integer :: jcart + double precision :: datom, tol, short_tol, short_tol_penalty, short_tol_scale + + fparc = 0.0d0 + jcart = firstjcart + do while ( jcart > 0 ) + ! + ! Cycle if this type is not to be computed + ! + if ( .not. comptype(ibtype(jcart))) then + jcart = latomnext(jcart) + cycle + end if + ! + ! Cycle if the atoms are from the same molecule + ! + if ( ibmol(icart) == ibmol(jcart) .and. & + ibtype(icart) == ibtype(jcart) ) then + jcart = latomnext(jcart) + cycle + end if + ! + ! Cycle if both atoms are from fixed molecules + ! + if ( fixedatom(icart) .and. fixedatom(jcart) ) then + jcart = latomnext(jcart) + cycle + end if + ! + ! Otherwise, compute distance and evaluate function for this pair + ! + datom = ( xcart(icart,1)-xcart(jcart,1) )**2 + & + ( xcart(icart,2)-xcart(jcart,2) )**2 + & + ( xcart(icart,3)-xcart(jcart,3) )**2 + tol = (radius(icart)+radius(jcart))**2 + if ( datom < tol ) then + fparc = fparc + fscale(icart)*fscale(jcart)*(datom-tol)**2 + if ( use_short_radius(icart) .or. use_short_radius(jcart) ) then + short_tol = (short_radius(icart)+short_radius(jcart))**2 + if ( datom < short_tol ) then + short_tol_penalty = datom-short_tol + short_tol_scale = dsqrt(short_radius_scale(icart)*short_radius_scale(jcart)) + short_tol_scale = short_tol_scale*(tol**2/short_tol**2) + fparc = fparc + fscale(icart)*fscale(jcart)*short_tol_scale*short_tol_penalty**2 + end if + end if + end if + tol = (radius_ini(icart)+radius_ini(jcart))**2 + fdist = dmax1(tol-datom,fdist) + if ( move ) then + fdist_atom(icart) = dmax1(tol-datom,fdist_atom(icart)) + fdist_atom(jcart) = dmax1(tol-datom,fdist_atom(jcart)) + end if + jcart = latomnext(jcart) + end do + +end function fparc + diff --git a/tests/packmol/gencan.f b/tests/packmol/gencan.f new file mode 100644 index 00000000..3f98f10e --- /dev/null +++ b/tests/packmol/gencan.f @@ -0,0 +1,6006 @@ +C ***************************************************************** +C ***************************************************************** + + subroutine evalal(n,x,m,lambda,rho,f,flag) + +C This subroutine computes the objective function when GENCAN is +C being used stand-alone to solve a unique bound-constrained problem. +C When GENCAN is being used in an Augmented Lagrangian framework, +C this subroutine must compute the Augmented Lagrangian function. +C +C On Entry: +C +C n integer, +C number of variables, +C +C x double precision x(n), +C current point, +C +C m integer, +C number of constraints (equalities plus inequalities), +C +C lambda double precision lambdae(m), +C current estimation of the Lagrange multipliers, +C +C rho double precision rho(m) +C penalty parameters, +C +C NOTE: arguments m, lambda and rho are useful when GENCAN is being used +C for solving the box-constrained subproblems of an Augmented Lagrangian +C framework. When GENCAN is being used stand-alone for solving a bound- +C constrained problem, these arguments are dummy arguments. +C +C On Return +C +C f double precision, +C objective function value at x, +C +C flag integer +C 0 means "no errors", +C 1 means "some error occurs in the objective funtion evaluation". + + implicit none + +C SCALAR ARGUMENTS + integer flag,m,n + double precision f + +C ARRAY ARGUMENTS + double precision lambda(m),rho(m),x(n) + +C LOCAL SCALARS + + flag = 0 + + call computef(n,x,f) + + end + +C ***************************************************************** +C ***************************************************************** + + subroutine evalnal(n,x,m,lambda,rho,g,flag) + +C This subroutine computes the gradient of the objective function +C when GENCAN is being used stand-alone to solve a unique bound- +C constrained problem. When GENCAN is being used in an Augmented +C Lagrangian framework, this subroutine must compute the gradient of +C Augmented Lagrangian. +C +C On Entry: +C +C n integer, +C number of variables, +C +C x double precision x(n), +C current point, +C +C m integer, +C number of constraints (equalities plus inequalities), +C +C lambda double precision lambdae(m), +C current estimation of the Lagrange multipliers, +C +C rho double precision rho(m) +C penalty parameters, +C +C NOTE: arguments m, lambda and rho are useful when GENCAN is being used +C for solving the box-constrained subproblems of an Augmented Lagrangian +C framework. When GENCAN is being used stand-alone for solving a bound- +C constrained problem, these arguments are dummy arguments. +C +C On Return +C +C g double precision g(n), +C gradient of the objective function at x, +C +C flag integer +C 0 means "no errors", +C 1 means "some error occurs in the gradient evaluation". + + implicit none + +C SCALAR ARGUMENTS + integer flag,m,n + +C ARRAY ARGUMENTS + double precision g(n),lambda(m),rho(m),x(n) + +C LOCAL SCALARS + + flag = 0 + + call computeg(n,x,g) + + end + +C ***************************************************************** +C ***************************************************************** + +c Modified by L. Martinez (there was an error on the number of +c parameters when calling this subroutine). This subroutine does +c nothing. +c subroutine evalhd(nind,ind,n,x,m,lambda,rho,d,hd,flag) + + subroutine evalhd(n) + +C This subroutine computes the product of the Hessian matrix times +C the input vector argument d. If GENCAN is being used stand-alone +C to solve a bound-constrained problem, the ''Hessian matrix'' must +C be the Hessian matrix of the objective function. On the other hand, +C if GENCAN is being used to solve the bound-constrained subproblems +C in an Augmented Lagrangian framework, the Hessian matrix must be +C the Hessian of the Augmented Lagrangian function. +C +C IMPORTANT: This subroutine does not need to be coded if the user +C prefers to approximate the Hessian-vector product by incremental +C quotients. In this case, it is enough to set the GENCAN input +C argument htvtype equal to 1 and an internal GENCAN subroutine will +C be used to compute the approximation. In fact, this is the default +C GENCAN option. See the GENCAN and EASYGENCAN arguments descriptions +C for details. +C +C On Entry: +C +C nind integer +C number of component of the Hessian-vector product that +C must be computed, +C +C ind integer ind(nind) +C the component that must be computed are ind(1)-th ... ind(nind)-th, +C +C n integer, +C number of variables, +C +C x double precision x(n), +C current point, +C +C m integer, +C number of constraints (equalities plus inequalities), +C +C lambda double precision lambdae(m), +C current estimation of the Lagrange multipliers, +C +C rho double precision rho(m) +C penalty parameters, +C +C d double precision d(n) +C vector of the Hessian-vector product. +C +C NOTE: arguments m, lambda and rho are useful when GENCAN is being used +C for solving the box-constrained subproblems of an Augmented Lagrangian +C framework. When GENCAN is being used stand-alone for solving a bound- +C constrained problem, these arguments are dummy arguments. +C +C On Return +C +C hd double precision g(n), +C Hessian-vector product, +C +C flag integer +C 0 means "no errors", +C 1 means "some error occurs in the gradient evaluation". + + implicit none + +C SCALAR ARGUMENTS +c integer flag,m,n,nind + integer n + +C ARRAY ARGUMENTS +c integer ind(nind) +c double precision d(n),hd(n),lambda(m),rho(m),x(n) + +c flag = - 1 + + end + +C************************************************************************** + +C Last update of EASYGENCAN: February 18th, 2005. + + subroutine easygencan(n,x,l,u,m,lambda,rho,epsgpsn,maxit,maxfc, + +trtype,iprint,ncomp,f,g,gpsupn,iter,fcnt,gcnt,cgcnt,inform,wi,wd, + +delmin) + + implicit none + +C SCALAR ARGUMENTS + integer cgcnt,fcnt,gcnt,m,maxfc,maxit,n,ncomp,inform,iprint,iter + double precision epsgpsn,f,gpsupn + +C ARRAY ARGUMENTS + integer wi(n) + double precision g(n),l(n),lambda(m),rho(m),u(n),wd(8*n),x(n) + +C This subroutine aims to simplify the use of GENCAN. For this +C purpose it gives values to most of the GENCAN arguments and +C leaves to the user those arguments which he/she may would like to +C set by him/herself. +C +C The arguments of EASYGENCAN are the input and output arguments of +C GENCAN that are supposed to be useful for a common user. The input +C arguments are mostly related to basic problem information, like +C dimension and bounds, and the initial point. There are also input +C arguments related to simple stopping criteria (like norm of the +C projected gradient, and maximum number of iterations and +C functional evaluations). There are also two input arguments +C related to control the amount of information written into the +C screen. The output arguments are related to information of the +C solution and some few performance measurements. Basically, on +C return, EASYGENCAN gives to the user the solution, the objective +C functional value and its gradient at the solution, Euclidian and +C sup-norm of the projected gradient at the solution, the number of +C iterations, functional and gradient evaluations, and Conjugate +C Gradient iterations used to reach the solution, and, finally, a +C flag that indicates the stopping criterion that was satisfied. +C +C All the other arguments of GENCAN are setted with its default +C values by EASYGENCAN. EASYGENCAN divides the arguments of GENCAN +C in two sets. Those that are related to the behaviour of GENCAN are +C declared as Fortran parameters (constants). The other arguments of +C GENCAN, most of them related to alternative stopping criteria, and +C that may depend of, for example, maxit, are declared as local +C variables of EASYGENCAN. +C +C GENCAN arguments that are defined as Fortran parameters in this +C subroutine are GENCAN arguments that should not be modified by a +C common user. They are arguments that modify the behaviour of +C GENCAN and whos values were selected because they are classical +C values in some cases or because some numerical experiments seemed +C to indicate that they are the best choices. +C +C GENCAN arguments that are declared as local variables in this +C subroutine are GENCAN arguments that may be modified if, with +C their suggested values, GENCAN does not give the desired result. +C Most of them are related to Conjugate Gradients or to disabled +C stopping criteria that may be useful in bad-scaled problems or +C problems with not trustable derivatives. +C +C Finally, this subroutine declares as local variables some +C arguments of GENCAN which in fact are output arguments. Most of +C them are related to quantities that can be used for statistics +C related to the GENCAN performance, like number Spectral Projected +C Gradient iterations, Truncated Newton iterations, Conjugate +C Gradient iterations, etc. As we assume that this values are not +C useful for the common user, this subroutine throw all of them +C away. +C +C We describe below the meaning of the arguments of the EASYGENCAN +C subroutine. More detailed descriptions as well as the descriptions +C of all the other GENCAN arguments that are not arguments of +C EASYGENCAN are also described at the begining of the GENCAN +C subroutine. +C +C On entry: +C +C n integer +C number of variables +C +C x double precision x(n) +C initial estimation of the solution +C +C l double precision l(n) +C lower bounds on the variables +C +C u double precision u(n) +C upper bounds on the variables +C +C m integer +C lambda double precision lambda(m) +C rho double precision rho(m) +C These three parameters are not used nor modified by +C GENCAN and they are passed as arguments to the user- +C defined subroutines evalal and evalnal to compute the +C objective function and its gradient, respectively. +C Clearly, in an Augmented Lagrangian context, if GENCAN is +C being used to solve the bound-constrainted subproblems, m +C would be the number of constraints, lambda the Lagrange +C multipliers approximation and rho the penalty parameters +C +C epsgpsn double precision +C GENCAN stops declaring convergence if it finds a point +C whos projected gradient sup-norm is smaller than or equal +C to epsgpsn +C +C maxit integer +C GENCAN stops declaring ''maximum number of iteration +C achieved'' if the number of iterations exceeds maxit +C +C maxfc integer +C the same as before but with the number of functional +C evaluations +C +C iprint integer +C indicates the degree of details of the output generated +C by GENCAN. Setting iprint to a value smaller than 2 will +C make GENCAN to generate no output at all. An iprint value +C greater than or equal to 2 will generate information of +C every GENCAN iteration. An iprint value greater than or +C equal to 3 will also show information of the Conjugate +C Gradient iterations (used to compute the Truncated Newton +C direction) and also information related to the line +C search procedures in the Spectral Projected Gradient +C direction and the Truncated Newton direction. +C +C ncomp integer +C Sometimes, vectors like the current point x, the gradient +C of the objective function g, or the search directions +C (Spectral Projected Gradient direction or Truncated +C Newton direction), among other vector, are showed in the +C screen. In such cases, if the problem dimension is large, +C to show just a few elements of these vectors may be +C preferable. Argument ncomp can be used to indicate how +C many array elements must be displayed. +C +C wi integer wi(n) +C integer working space +C +C wd double precision wd(8*n) +C double precision working space +C +C On return: +C +C x double precision x(n) +C estimation of the solution +C +C f double precision +C objective function value at the solution +C +C g double precision g(n) +C gradient of the objective function at the solution +C +C gpsupn double precision +C sup-norm of the continuous projected gradient +C +C iter integer +C number of iterations used to reach the solution +C +C fcnt integer +C number of functional evaluations +C +C gcnt integer +C number of gradient evaluations +C +C cgcnt integer +C number of Conjugate Gradient iterations +C +C inform integer +C termination criteria. inform equal to 1 means that +C GENCAN converged with the sup-norm of the continuous +C projected gradient stopping criterion (inform equal to 0 +C means the same but with the Euclidian norm). Other +C positive values means that GENCAN stopped by a may be not +C successful stopping criteria. A negative value means that +C there was an error in the user-defined subroutines that +C computes the objective function (subroutine evalal), the +C gradient (subroutine evalnal), or the Hessian-vector +C product (subroutine evalhd). See the GENCAN description +C for more details. + +C HERE STARTS THE DESCRIPTION OF SOME GENCAN ARGUMENTS THAT ARE +C BEING SETTED INSIDE EASYGENCAN. THE FIRST SET OF ARGUMENTS ARE +C THOSE ARGUMENTS THAT WE WILL CALL ''CONSTANTS'' AND THAT, AS THEIR +C VALUES ALTER THE BEHAVIOUR OF GENCAN, SHOULD NOT BE MODIFIED BY A +C COMMON USER. + +C CONSTANTS FOR GENERAL USES + +C Steps: h = max( steabs, sterel * abs( x ) ) should be a number +C such that h is small ( relatively to x ) and x + h is different +C from x. So, h is something that can be used a a step for a finite +C differences approximation of a partial derivative relative to x. + +C Epsilons: something smaller than max( epsabs, epsrel * abs( x ) ) +C should be considered as ``zero'' when compared with x. It is used, +C for example, to detect that a step taken during a line search is +C too small. + +C Infinitys: infrel is a big number that may appear in the +C calculations. infabs is a number that should never be reached in +C the calculations and is used the represent ``infinite''. Detailed +C explanations of how are they used are rather cumbersome. + + double precision steabs,sterel,epsabs,epsrel,infabs,infrel + parameter ( steabs = 1.0d-10 ) + parameter ( sterel = 1.0d-07 ) + parameter ( epsabs = 1.0d-20 ) + parameter ( epsrel = 1.0d-10 ) + parameter ( infabs = 1.0d+99 ) + parameter ( infrel = 1.0d+20 ) + +C CONSTANTS FOR CLASSICAL LINE-SEARCH CONDITIONS + +C beta is the constant for the ''beta condition''. We use this +C condition to test whether is promising to extrapolate or not. + +C gamma is the constant for the sufficient decrease ''Armijo +C condition''. + +C theta is the constant for the ''angle condition''. + +C sigma1 and sigma2 are the constants for the safeguarding quadratic +C interpolations. We use them in a rather unusual way. Instead of +C discarding a new step anew if it does not belong to the interval +C [ sigma1 * aprev, sigma2 * aprev ], we discard it if it does not +C belong to the interval [ sigma1, sigma2 * aprev ]. In such a case +C we take something similar to ''anew = aprev / 2''. + + double precision beta,gamma,theta,sigma1,sigma2 + parameter ( beta = 0.5d0 ) + parameter ( gamma = 1.0d-04 ) + parameter ( theta = 1.0d-06 ) + parameter ( sigma1 = 0.1d0 ) + parameter ( sigma2 = 0.9d0 ) + +C CONSTANTS FOR SPECIFIC PROCEDURES (NOT SO CLASSICAL) + +C In line searches, when interpolating, the step may become so +C small that we should declare a line search failure indicating that +C direction may not be a descent direction. This decision is never +C take before doing at least mininterp interpolations. + +C In line searches, the beta condition (see above) may recommend to +C extrapolate. We never do more than maxextrap extrapolations. + +C In the line searches, when we need to interpolate and the result +C of the quadratic interpolation is rejected, the new step is +C computed as anew = aprev / nint. When the beta condition +C recommends to extrapolate, we compute anew = aprev * next. + +C When computing the Newton direction by Conjugate Gradients we +C never go further an artificial ''trust region''. This ''trust +C radius'' is never smaller than delmin. + +C In active set strategies, constants eta is used to decide whether +C the current face should be abandoned or not. In particular, the +C current face is abandoned when the norm of the internal to face +C component of the continuous projected gradient is smaller than +C ( 1 - eta ) times the norm of the continuous projected gradient. +C In this way, values of eta near 1 makes the method to work hard +C inside the faces and values of eta near 0 makes the method to +C abandon the faces very quickly. + +C We always use as a first step in a line search procedure along a +C first order direction the spectral steplength. This steplength +C must belong to the interval [lspgmi,lspgma]. + + integer maxextrap,mininterp + parameter ( maxextrap = 100 ) + parameter ( mininterp = 4 ) + + double precision nint,next,delmin,eta,lspgma,lspgmi + parameter ( nint = 2.0d0 ) + parameter ( next = 2.0d0 ) +c parameter ( delmin = 1.d4 ) + parameter ( eta = 0.9d0 ) + parameter ( lspgma = 1.0d+10 ) + parameter ( lspgmi = 1.0d-10 ) + +C DIMENSIONS FOR SOME WORKING SPACES + +C In non-monotone line searches, given p, the last p objective +C functional values must be stored. For this reason we declare a +C vector with pmax double precision elements. So p must be less than +C or equal to pmax. + +C Sometimes, is the problem is bad scaled, to request a small +C gradient norm at the solution may be inadequate. For this reason, +C a test to verify if this norm is not decreasing during maxitngp +C (MAXimum of ITerations with No Gradient Progress) consecutive +C iterations then we stop the method with a warning. As it is not +C expected a monotone decreasing of the gradient norm, again, the +C norm of the last maxitngp iterations must be saved. For this +C purpose, we declare a vector of tmax elements. So maxitngp must +C be less than or equal to tmax. + + integer tmax + parameter ( tmax = 10000 ) + +C HERE STARTS THE DESCRIPTION OF THE OTHER ARGUMENTS OF GENCAN BEING +C SETTED BY EASYGENCAN. THESE ARGUMENTS MAY BE MODIFIED BY A COMMON +C USER IF, WITH THEIR SUGGESTED VALUES, GENCAN DOES NOT GIVE THE +C EXPECTED RESULT. + +C GENCAN INPUT ARGUMENTS THAT WILL BE SETTED BELOW + + logical nearlyq + + integer cgmaxit,cgscre,gtype,htvtype,maxitnfp,maxitngp,maxitnqmp, + + trtype + + double precision cgepsf,cgepsi,cggpnf,delta0,epsgpen,epsnfp, + + epsnqmp,fmin + +C GENCAN OUTPUT ARGUMENTS THAT WILL BE DISCARDED + + integer spgfcnt,spgiter,tnexbcnt,tnexgcnt,tnexbfe,tnexgfe,tnfcnt, + + tnintcnt,tnintfe,tniter,tnstpcnt + + double precision gpeucn2 + +C GENCAN WORKING VECTORS (WHICH DIMENSION IS NOT RELATED TO THE +C PROBLEM DIMENSION) + + double precision lastgpns(tmax) + +C ARGUMENTS RELATED TO DERIVATIVES CALCULATIONS + +C gtype indicates in which way the gradient of the objective +C function will be computed. If the user have been implemented the +C user-supplied evalnal subroutine to compute the gradient of the +C objective function then gtype argument must be set to 0 (ZERO) and +C the user-supplied evalnal subroutine will be called by GENCAN any +C time the gradient would be required. +C +C The prototype of the evalnal subroutine must be: +C +C subroutine evalnal(n,x,m,lambda,rho,nal,flag) +C +C SCALAR ARGUMENTS +C integer n,m,flag +C +C ARRAY ARGUMENTS +C double precision x(n),lambda(m),rho(m),nal(n) +C +C ''Here must be written the subroutine body that calculates the +C n-dimensional gradient vector of the objective function +C evaluated at x and saves it in nal. It also must set flag to 0 +C (ZERO) if the gradient was successfully computed and to any +C other value if the gradient vector is not well defined at the +C required point x. If GENCAN is been used stand-alone to solve +C a unique bound-constrained problem then m, lambda and rho are +C dummy arguments. On the other hand, if GENCAN is been used in +C an Augmented Lagrangian framework then these arguments should +C be used for the number of constraints, the Lagrange +C multipliers approximation and the penalty parameters, +C respectively.'' +C +C end +C +C If, on the other hand, the user is not able to provide evalnal +C subroutine, gtype argument must be set to 1 (ONE). In this case, +C every time GENCAN needs to compute the gradient of the objective +C function, an internal subroutine that approximates it by finite- +C differences will be used (be aware that it maybe very time +C consuming). Moreover, note that the evalnal subroutine must still +C be present (with an empty body). + + gtype = 0 + +C htvtype indicates in which way the product of the Hessian of the +C objective function times an arbitrary vector will be computed. If +C the user has not been implemented the user-supplied evalhd +C subroutine to do this task then htvtype argument must be set to 1 +C (ONE). In this case an internal subroutine that approximates this +C product by incremental quotients will be used. Note that, even in +C this case, evalhd subroutine must be present (with an empty body). +C This is the default option and the empty-body subroutine follows: +C +C subroutine evalhd(nind,ind,n,x,m,lambda,rho,d,hd,flag) +C +C SCALAR ARGUMENTS +C integer nind,n,m,flag +C +C ARRAY ARGUMENTS +C integer ind(nind) +C double precision d(n),hd(n),lambda(m),rho(m),x(n) +C +C flag = - 1 +C +C end +C +C If, on the other hand, the user prefers to implement his/her own +C evalhd subroutine then htvtype argument must be set to 0 (ZERO). +C In this case, the product of the Hessian times vector d (input +C argument of evalhd subroutine) must be saved in vector hd (output +C argument of evalhd subroutine). The other arguments description as +C well as some hints on how to implement your own evalhd subroutine +C can be found in the GENCAN arguments description. + +C When ALGENCAN uses GENCAN to solve the subproblems in the classical +C Augmented Lagrangian framework, ALGENCAN uses its own evalhd +C subroutine to overcome the lack of continuity of the second +C derivatives. So, when GENCAN is being used toghether with ALGENCAN, +C htvtype must be equal to 0 (ZERO). On the other hand, if GENCAN is +C being used stand-alone, just set htvtype equal to 1 (ONE) and add +C the empty-body subroutine described above. + + htvtype = 1 + +C ARGUMENTS RELATED TO STOPPING CRITERIA + +C Besides the stopping criterion related to the sup-norm of the +C continuous projected gradient, there is another stopping criterion +C related to its Euclidian norm. So, GENCAN stops the process if it +C finds a point at which the Euclidian norm of the continuous +C projected gradient is smaller than epsgpen. + + epsgpen = 0.0d0 + +C For an explanation of maxitngp see above the explanation of tmax +C in ''DIMENSIONS FOR SOME WORKING SPACES''. Just note that the +C value of maxitngp must be less than or equal to tmax. + + maxitngp = tmax + +C maxitnfp means MAXimum of allowed number of iterations with No +C Progress in the objective functional value. ''Progress'' from one +C iteration to the next one refers to ( fnew - fprev ). Since the +C begining of the algorithm we save the ''best progress'' and +C consider that there was no progress in an iteration if the +C progress of this iterations was smaller than epsnfp times the best +C progress. Finally, the algorithm stops if there was no progress +C during maxitnfp consecutive iterations. + + maxitnfp = maxit + epsnfp = 0.0d0 + +C There is a stopping criterion that stops the method if a point +C with a functional value smaller than fmin is found. The idea +C behind this stopping criterion is to stop the method if the +C objective function is not bounded from below. + + fmin = 1.0d-05 + +C ARGUMENTS RELATED TO CONJUGATE GRADIENTS + +C When computing the Truncated Newton direction by Conjugate +C Gradients there is something similar to a ''trust-region radius''. +C This trust radius is updated from iteration to iteration depending +C on the agreement of the objective function and its quadratic +C model. But an initial value for the trust radius is required. If +C the user has a good guess for this initial value then it should be +C passed to GENCAN using the delta0 arguments. On the other hand, if +C delta0 is set to -1, a default value depending on the norm of the +C current point will be used. + + delta0 = - 1.0d0 + delmin = 1.d-2 +c delta0 = delmin + +C The ''trust-region'' can be like a ball (using Euclidian norm) or +C like a box (using sup-norm). This choice can be made using trtype +C (TRust region TYPE) argument. trtype equal to 0 means Euclidian +C norm and trtype equal to 1 means sup-norm. + + trtype = 1 + +C When the method is far from the solution, it may be not useful to +C do a very large effort in computing the Truncated Newton direction +C precisely. To avoid it, a fixed maximum number of iterations for +C Conjugate Gradients can be given to GENCAN. If the user would like +C to choose this maximum number of iterations for Conjugate +C Gradient then it should use the cgmaxit arguments. On the other +C hand he/she prefers to leave this task to GENCAN then he/she +C should set cgmaxit to -1. + + cgmaxit = -1 + +C If the task of deciding the accuracy for computing the Truncated +C Newton direction is leaved to GENCAN then a default strategy based +C on increasing accuracies will be used. The proximity to the +C solution is estimated observing the norm of the projected gradient +C at the current point and locating it between that norm at the +C initial point and the expected value of that norm at the solution. +C Then the accuracy for the Truncated Newton direction of the +C current iteration will be computed taking a precision located in +C the same relative position with respect to two given values for +C the accuracies for the first and the last Truncated Newton +C direction calculations. These two accuracies (cgepsi and cgepsf, +C respectively) must be given by the user. Moreover, the expected +C value of the projected gradient norm at the solution (cggpnf) must +C also be given by the user who must indicate setting argument +C cgscre to 1 or 2 if that norm is the Euclidian or the sup-norm. + + cggpnf = max( 1.0d-04, max( epsgpen, epsgpsn ) ) + cgscre = 2 + cgepsi = 1.0d-01 + cgepsf = 1.0d-05 + +C The next two arguments are used for an alternative stopping +C criterion for Conjugate Gradients. Conjugate Gradients method is +C stopped if the quadratic model makes no progress during maxitnqmp +C (MAXimum of ITerations with No Quadratic Model Progress) +C consecutive iterations. In this context, ''no progress'' means +C that the progress is smaller than epsnqmp (EPSilon to measure the +C No Quadratic Model Progress) times the best progress obtained +C during the previous iterations. + + epsnqmp = 1.0d-04 + maxitnqmp = 5 + +C Depending on how much the objective function seems to be a +C quadratic, function, Conjugate Gradients may take different +C decision. So, if the objective function is a quadratic function or +C is very similar to a quadratic function then the nearlyq argument +C should be set to TRUE, else, it should be set to FALSE. However, +C the option with nearlyq equal TRUE never showed good results. +C Regarding this unexpected no good performance, rather recently it +C was found a bug that affected the behaviour of GENCAN just in this +C case (See the April 1st, 2003 modifications report at the end of +C this file). So, new experiments setting nearlyq equal TRUE should +C be made. + + nearlyq = .false. + +C FINALLY, CALL GENCAN + + call gencan(n,x,l,u,m,lambda,rho,epsgpen,epsgpsn,maxitnfp,epsnfp, + +maxitngp,fmin,maxit,maxfc,delta0,cgmaxit,cgscre,cggpnf,cgepsi, + +cgepsf,epsnqmp,maxitnqmp,nearlyq,nint,next,mininterp,maxextrap, + +gtype,htvtype,trtype,iprint,ncomp,f,g,gpeucn2,gpsupn,iter,fcnt, + +gcnt,cgcnt,spgiter,spgfcnt,tniter,tnfcnt,tnstpcnt,tnintcnt, + +tnexgcnt,tnexbcnt,tnintfe,tnexgfe,tnexbfe,inform,wd(1),wd(n+1), + +wd(2*n+1),wi,lastgpns,wd(3*n+1),eta,delmin,lspgma,lspgmi,theta, + +gamma,beta,sigma1,sigma2,sterel,steabs,epsrel,epsabs,infrel, + +infabs) + + end + +C ****************************************************************** +C ****************************************************************** + +C Last update of GENCAN or any of its dependencies: +C +C February 18th, 2005. +C +C See report of modifications at the end of this file. + + subroutine gencan(n,x,l,u,m,lambda,rho,epsgpen,epsgpsn,maxitnfp, + +epsnfp,maxitngp,fmin,maxit,maxfc,udelta0,ucgmaxit,cgscre,cggpnf, + +cgepsi,cgepsf,epsnqmp,maxitnqmp,nearlyq,nint,next,mininterp, + +maxextrap,gtype,htvtype,trtype,iprint,ncomp,f,g,gpeucn2,gpsupn, + +iter,fcnt,gcnt,cgcnt,spgiter,spgfcnt,tniter,tnfcnt,tnstpcnt, + +tnintcnt,tnexgcnt,tnexbcnt,tnintfe,tnexgfe,tnexbfe,inform,s,y,d, + +ind,lastgpns,w,eta,delmin,lspgma,lspgmi,theta,gamma,beta,sigma1, + +sigma2,sterel,steabs,epsrel,epsabs,infrel,infabs) + + implicit none + +C SCALAR ARGUMENTS + logical nearlyq + integer cgcnt,cgscre,fcnt,gcnt,gtype,htvtype,inform,iprint,iter,m, + + maxextrap,maxfc,maxit,maxitnfp,maxitngp,maxitnqmp, + + mininterp,n,ncomp,spgfcnt,spgiter,tnexbcnt,tnexbfe, + + tnexgcnt,tnexgfe,tnfcnt,tnintcnt,tnintfe,tniter,tnstpcnt, + + trtype,ucgmaxit + double precision beta,cgepsf,cgepsi,cggpnf,delmin,epsabs,epsgpen, + + epsgpsn,epsnfp,epsnqmp,epsrel,eta,f,fmin,gamma,gpeucn2, + + gpsupn,infabs,infrel,lspgma,lspgmi,next,nint,sigma1, + + sigma2,steabs,sterel,theta,udelta0 + +C ARRAY ARGUMENTS + integer ind(n) + double precision d(n),g(n),l(n),lambda(m),lastgpns(0:maxitngp-1), + + rho(m),s(n),u(n),w(5*n),x(n),y(n) + +C Solves the box-constrained minimization problem +C +C Minimize f(x) +C +C subject to +C +C l <= x <= u +C +C using a method described in +C +C E. G. Birgin and J. M. Martinez, ''Large-scale active-set box- +C constrained optimization method with spectral projected +C gradients'', Computational Optimization and Applications 23, pp. +C 101-125, 2002. +C +C Subroutine evalal must be supplied by the user to evaluate the +C objective function. The prototype of evalal subroutine must be +C +C subroutine evalal(n,x,m,lambda,rho,f,flag) +C +C C On Entry: +C C +C C n integer +C C number of variables +C C +C C x double precision x(n) +C C current point +C C +C C m integer +C C number of constraints (equalities plus inequalities) +C C +C C lambda double precision lambda(m) +C C current estimation of the Lagrange multipliers +C C +C C rho double precision rho(m) +C C penalty parameters +C C +C C NOTE: arguments m, lambda and rho are useful when GENCAN is +C C being used for solving the box-constrained subproblems of an +C C Augmented Lagrangian framework. When GENCAN is being used +C C stand-alone for solving a bound-constrained problem, these +C C arguments are dummy arguments and must be ignored. +C C +C C On Return +C C +C C f double precision +C C objective function value at x +C C +C C flag integer +C C 0 means ''no errors'' +C C any other value means ''there was an error in the +C C objective function calculation''. +C C +C C SCALAR ARGUMENTS +C integer flag,m,n +C double precision f +C +C C ARRAY ARGUMENTS +C double precision lambda(m),rho(m),x(n) +C +C C ''Here it should be the body of evalal subroutine that saves +C C in f the objective function value at x. Moreover, it sets +C C flag equal to 0 if the calculation was successfully done and +C C sets flag equal to any other value different from 0 if the +C C objective function is not well defined at the current point +C C x.'' +C +C end +C +C Subroutine evalnal to calculate the gradient of the objective +C function may be supplied by the user or not, depending on the +C value of gtype argument (gtype equal to 0 means that the evalnal +C subroutine will be supplied by the user and gtype equal to 1 means +C that an internal GENCAN subroutine will be used to estimate the +C gradient vector by central finite differences). In any case, a +C subroutine named evalnal with the following prototype must +C present. +C +C subroutine evalnal(n,x,m,lambda,rho,g,flag) +C +C C On Entry: +C +C C n integer +C C number of variables +C C +C C x double precision x(n) +C C current point +C C +C C m integer +C C number of constraints (equalities plus inequalities) +C C +C C lambda double precision lambda(m) +C C current estimation of the Lagrange multipliers +C C +C C rho double precision rho(m) +C C penalty parameters +C C +C C NOTE: arguments m, lambda and rho are useful when GENCAN is +C C being used for solving the box-constrained subproblems of an +C C Augmented Lagrangian framework. When GENCAN is being used +C C stand-alone for solving a bound-constrained problem, these +C C arguments are dummy arguments and must be ignored. +C C +C C On Return +C C +C C g double precision g(n) +C C gradient of the objective function at x +C C +C C flag integer +C C 0 means ''no errors'', +C C any other value means ''there was an error in the +C C gradient calculation''. +C C +C C SCALAR ARGUMENTS +C integer flag,m,n +C +C C ARRAY ARGUMENTS +C double precision g(n),lambda(m),rho(m),x(n) +C +C C ''Here it should be the body of evalnal subroutine that +C C saves in g the gradient vector of the objective function at +C C x. Moreover, it sets flag equal to 0 if the calculation was +C C successfully done and sets flag equal to any other value +C C different from 0 if the gradient vector is not well defined +C C at the current point x. If GENCAN gtype argument was setted +C C to 1, i.e., the finite difference approximation provided by +C C GENCAN will be used, then this subroutine must even be +C C present for compilation purpose but it will never be +C C called.'' +C +C end +C +C Subroutine evalhd to calculate of the Hessian of the objective +C function times a given vector may be supplied by the user or not, +C depending on the value of htvtype argument (htvtype equal to 0 +C means that the evalhd subroutine will be supplied by the user and +C htvtype equal to 1 means tha an internal GENCAN subroutine will be +C used to estimate the product by incremental quotients). In any +C case, a subroutine named evalhd with the following prototype must +C present. +C +C subroutine evalhd(nind,ind,n,x,m,lambda,rho,d,hd,flag) +C +C C On Entry: +C C +C C nind integer +C C number of component of the Hessian-vector product that +C C must be computed +C C +C C ind integer ind(nind) +C C the component that must be computed are ind(1)-th ... +C C ind(nind)-th +C C +C C n integer +C C number of variables +C C +C C x double precision x(n) +C C current point +C C +C C m integer +C C number of constraints (equalities plus inequalities) +C C +C C lambda double precision lambda(m) +C C current estimation of the Lagrange multipliers +C C +C C rho double precision rho(m) +C C penalty parameters +C C +C C NOTE: arguments m, lambda and rho are useful when GENCAN is +C C being used for solving the box-constrained subproblems of an +C C Augmented Lagrangian framework. When GENCAN is being used +C C stand-alone for solving a bound-constrained problem, these +C C arguments are dummy arguments and must be ignored. +C C +C C d double precision d(n) +C C vector of the Hessian-vector product +C C +C C On Return +C C +C C hd double precision g(n) +C C Hessian-vector product +C C +C C flag integer +C C 0 means ''no errors'', +C C any other value means ''there was an error in the +C C product calculation''. Just as an example, as it has +C C no sense that an error occurs in a matrix-vector +C C product, the error could happen in the Hessian +C C calculation. But the possible errors will depend +C C on the way this Hessian-vector product is computed +C C or approximated. +C +C C SCALAR ARGUMENTS +C integer flag,m,n,nind +C +C C ARRAY ARGUMENTS +C integer ind(nind) +C double precision d(n),hd(n),lambda(m),rho(m),x(n) +C +C C ''Here it should be the body of evalhd subroutine that saves +C C in hd the product of the Hessian of the objective function +C C times vector d. Moreover, it sets flag equal to 0 if the +C C calculation was successfully done and sets flag equal to any +C C other value different from 0 if the Hessian matrix is not +C C well defined at the current point x. If GENCAN htvtype +C C argument was setted to 1, i.e., the incremental quotients +C C approximation provided by GENCAN will be used, then this +C C subroutine must even be present for compilation purposes +C C but it will never be called.'' +C +C end +C +C In evalhd subroutine, the information about the matrix H must be +C passed by means of common declarations. This subroutine must be +C coded by the user, taking into account that only nind components +C of d are nonnull and that ind is the set of indices of those +C components. In other words, the user must write evalhd in such a +C way that hd is the vector whose i-th entry is +C +C hd(i) = \Sum_{j=1}^{nind} H_{i,ind(j)} d_ind(j) +C +C Moreover, the only components of hd that must be computed are +C those which correspond to the indices ind(1),...,ind(nind). +C However, observe that it must be assumed that, in d, the whole +C dense vector is present, with its n components, even the null +C ones. So, if the user decides to code evalhd without taking into +C account the presence of ind and nind, it can be easily done. A +C final observation: probably, if nind is close to n, it is not +C worthwhile to use ind, due to the cost of accessing the correct +C indices. +C +C Example: Assume that H is dense. The main steps of evalhd could +C be: +C +C do i = 1,nind +C indi = ind(i) +C hd(indi) = 0.0d0 +C do j = 1,nind +C indj = ind(j) +C hd(indi) = hd(indi) + H(indi,indj) * d(indj) +C end do +C end do +C +C +C Description of the GENCAN arguments: +C +C On Entry +C +C n integer +C number of variables +C +C x double precision x(n) +C initial estimation of the solution +C +C l double precision l(n) +C lower bounds on the variables +C +C u double precision u(n) +C upper bounds on the variables +C +C m integer +C lambda double precision lambda(m) +C rho double precision rho(m) +C These three parameters are not used nor modified by +C GENCAN and they are passed as arguments to the user- +C defined subroutines evalal and evalnal to compute the +C objective function and its gradient, respectively. +C Clearly, in an Augmented Lagrangian context, if GENCAN is +C being used to solve the bound-constrainted subproblems, m +C would be the number of constraints, lambda the Lagrange +C multipliers approximation and rho the penalty parameters +C +C epsgpen double precision +C epsgpen means EPSilon for the Projected Gradient Euclidian +C Norm. It is a small positive number for declaring +C convergence when the Euclidian norm of the continuous +C projected gradient is less than or equal to epsgpen +C +C RECOMMENDED: epsgpen = 1.0d-05 +C +C CONSTRAINTS: epsgpen >= 0.0 +C +C epsgpsn double precision +C epsgpsn means EPSilon for the Projected Gradient Sup Norm. +C It is a small positive number for declaring convergence +C when the sup norm of the continuous projected gradient is +C less than or equal to epsgpsn +C +C RECOMMENDED: epsgpsn = 1.0d-05 +C +C CONSTRAINTS: epsgpsn >= 0.0 +C +C maxitnfp integer +C maxitnfp means MAXimum of ITerations with No Function +C Progress. See below for more details. +C +C epsnfp double precision +C epsnfp means EPSilon for No Function Progress. It is a +C small positive number for declaring ''lack of progress in +C the objective function value'' if f(x_k) - f(x_{k+1}) <= +C epsnfp * max{ f(x_j) - f(x_{j+1}, j < k } during maxitnfp +C consecutive iterations. This stopping criterion may be +C inhibited setting maxitnfp equal to maxit. +C +C RECOMMENDED: maxitnfp = 5 and epsnfp = 1.0d-02 +C +C CONSTRAINTS: maxitnfp >= 1 and epsnfp >= 0.0 +C +C maxitngp integer +C maxitngp means MAXimum of ITerations with No Gradient +C Progress. If the order of the Euclidian norm of the +C continuous projected gradient did not change during +C maxitngp consecutive iterations then the execution stops. +C +C RECOMMENDED: maxitngp = 10 +C +C CONSTRAINTS: maxitngp >= 1 +C +C fmin double precision +C function value for the stopping criteria f <= fmin +C +C There is a stopping criterion that stops GENCAN if a +C point with a functional value smaller than fmin is found. +C The idea behind this stopping criterion is to stop the +C method if the objective function is not bounded from +C below. +C +C RECOMMENDED: fmin = - infabs +C +C CONSTRAINTS: there are no constraints for this argument +C +C maxit integer +C maximum number of allowed iterations +C +C RECOMMENDED: maxit = 1000 +C +C CONSTRAINTS: maxit >= 0 +C +C maxfc integer +C maximum allowed number of functional evaluations +C +C RECOMMENDED: maxfc = 5 * maxit +C +C CONSTRAINTS: maxfc >= 1 +C +C udelta0 double precision +C initial ''trust-radius'' for Conjugate Gradients. The +C default value max( delmin, 0.1 * max( 1, ||x|| ) ) is +C used if the user sets udelta0 <= 0. +C +C RECOMMENDED: udelta0 = - 1.0 +C +C CONSTRAINTS: there are no constraints for this argument +C +C ucgmaxit integer +C maximum allowed number of iterations for each run of the +C Conjugate Gradient subalgorithm +C +C The default values for this argument is max( 1, 10 * +C log( nind ) ), where nind is the number of free +C variables, and it will be used if the user sets ucgmaxit +C to any non-positive value. +C +C RECOMMENDED: ucgmaxit = - 1 +C +C CONSTRAINTS: there are no constraints for this argument +C +C cgscre integer +C See below +C +C cggpnf double precision +C cgscre means conjugate gradient stopping criterion +C relation, and cggpnf means Conjugate Gradients projected +C gradient final norm. Both are related to a stopping +C criterion of Conjugate Gradients. This stopping criterion +C depends on the norm of the residual of the linear system. +C The norm of the residual should be less or equal than a +C ''small'' quantity which decreases as we are +C approximating the solution of the minimization problem +C (near the solution, better the truncated-Newton direction +C we aim). Then, the log of the required accuracy requested +C to Conjugate Gradient has a linear dependence on the log +C of the norm of the continuous projected gradient. This +C linear relation uses the squared Euclidian norm of the +C projected gradient if cgscre is equal to 1 and uses the +C sup-norm if cgscre is equal to 2. In addition, the +C precision required to CG is equal to cgepsi (conjugate +C gradient initial epsilon) at x0 and cgepsf (conjugate +C gradient final epsilon) when the Euclidian- or sup-norm +C of the projected gradient is equal to cggpnf (conjugate +C gradients projected gradient final norm) which is an +C estimation of the value of the Euclidian- or sup-norm of +C the projected gradient at the solution. +C +C RECOMMENDED: cgscre = 1, cggpnf = epsgpen; or +C cgscre = 2, cggpnf = epsgpsn. +C +C CONSTRAINTS: allowed values for cgscre are just 1 or 2 +C cggpnf >= 0.0 +C +C cgepsi double precision +C See below +C +C cgepsf double precision +C small positive numbers for declaring convergence of the +C Conjugate Gradients subalgorithm when ||r||_2 < cgeps * +C ||rhs||_2, where r is the residual and rhs is the right +C hand side of the linear system, i.e., CG stops when the +C relative error of the solution is smaller than cgeps. +C +C cgeps varies from cgepsi to cgepsf in a way that depends +C on cgscre as follows: +C +C i) CASE cgscre = 1: log10(cgeps^2) depends linearly on +C log10(||g_P(x)||_2^2) which varies from ||g_P(x_0)||_2^2 +C to epsgpen^2 +C +C ii) CASE cgscre = 2: log10(cgeps) depends linearly on +C log10(||g_P(x)||_inf) which varies from ||g_P(x_0)||_inf +C to epsgpsn +C +C RECOMMENDED: cgepsi = 1.0d-01, cgepsf = 1.0d-05 +C +C CONSTRAINTS: cgepsi >= cgepsf >= 0.0 +C +C epsnqmp double precision +C See below +C +C maxitnqmp integer +C This and the previous argument are used for a stopping +C criterion of the Conjugate Gradients subalgorithm. If the +C progress in the quadratic model is smaller than fraction +C of the best progress ( epsnqmp * bestprog ) during +C maxitnqmp consecutive iterations then CG is stopped +C declaring ''not enough progress of the quadratic model''. +C +C RECOMMENDED: epsnqmp = 1.0d-04, maxitnqmp = 5 +C +C CONSTRAINTS: epsnqmp >= 0.0, maxitnqmp >= 1. +C +C nearlyq logical +C If the objective function is (nearly) quadratic, use the +C option nearlyq = TRUE. Otherwise, keep the default +C option. +C +C If, in an iteration of CG we find a direction d such that +C d^T H d <= 0 then we take the following decision: +C +C (i) If nearlyq = TRUE then we take direction d and try to +C go to the boundary choosing the best point among the two +C points at the boundary and the current point. +C +C (ii) If nearlyq = FALSE then we stop at the current point. +C +C Moreover, if the objective function is quadratic more +c effort is due in computing the Truncated Newton direction. +C +C RECOMMENDED: nearlyq = FALSE +C +C CONSTRAINTS: allowed values are just TRUE or FALSE. +C +C nint double precision +C Constant for the interpolation. See the description of +C sigma1 and sigma2 above. Sometimes, in a line search, we +C take the new trial step as the previous one divided by +C nint +C +C RECOMMENDED: nint = 2.0 +C +C CONSTRAINTS: nint > 1.0. +C +C next double precision +C Constant for the extrapolation. When extrapolating we +C try alpha_new = alpha * next +C +C RECOMMENDED: next = 2.0 +C +C CONSTRAINTS: next > 1.0 +C +C mininterp integer +C Constant for testing if, after having made at least +C mininterp interpolations, the steplength is too small. In +C that case, failure of the line search is declared (may be +C the direction is not a descent direction due to an error +C in the gradient calculations). Use mininterp greater +C than or equal to maxfc for inhibit this stopping +C criterion +C +C RECOMMENDED: mininterp = 4 +C +C CONSTRAINTS: mininterp >= 1 +C +C maxextrap integer +C Constant to limit the number of extrapolations in the +C Truncated Newton direction. +C +C RECOMMENDED: maxextrap = 100 +C +C CONSTRAINTS: maxextrap >= 0 +C +C gtype integer +C gtype indicates in which way the gradient of the +C objective function will be computed. If the user have +C been implemented the user-supplied evalnal subroutine to +C compute the gradient of the objective function then +C gtype argument must be set to 0 (ZERO) and the user- +C supplied evalnal subroutine will be called by GENCAN any +C time the gradient would be required. +C +C subroutine evalnal(n,x,m,lambda,rho,g,flag) +C +C C On Entry: +C +C C n integer, +C C number of variables, +C C +C C x double precision x(n), +C C current point, +C C +C C m integer, +C C number of constraints (equalities plus +C C inequalities), +C C +C C lambda double precision lambda(m), +C C current estimation of the Lagrange +C C multipliers, +C C +C C rho double precision rho(m) +C C penalty parameters, +C C +C C NOTE: arguments m, lambda and rho are useful when +C C GENCAN is being used for solving the box- +C C constrained subproblems of an Augmented Lagrangian +C C framework. When GENCAN is being used stand-alone +C C for solving a bound-constrained problem, these +C C arguments are dummy arguments. +C C +C C On Return +C C +C C g double precision g(n), +C C gradient of the objective function at x, +C C +C C flag integer +C C 0 means ''no errors'', +C C 1 means ''some error occurs in the gradient +C C evaluation''. +C C +C C SCALAR ARGUMENTS +C integer flag,m,n +C +C C ARRAY ARGUMENTS +C double precision g(n),lambda(m),rho(m),x(n) +C +C C ''Here it should be the body of evalnal subroutine +C C that saves in g the gradient vector of the +C C objective at x. Moreover, it sets flag equal to 0 +C C if the calculation was successfully done and sets +C C flag equal to any other value different from 0 if +C C the gradient vector is not well defined at the +C C current point x. If GENCAN gtype argument was +C C setted to 1, i.e., the finite difference +C C approximation provided by GENCAN will be used, then +C C this subroutine must even be present for +C C compilation purposes but it will never be called.'' +C +C end +C +C If, on the other hand, the user is not able to provide +C evalnal subroutine, gtype argument must be set to 1 +C (ONE). In this case, every time GENCAN needs to compute +C the gradient of the objective function, an internal +C subroutine that approximates it by finite-differences +C will be used (be aware that it maybe very time +C consuming). Moreover, note that the evalnal subroutine +C must still be present (with an empty body). +C +C RECOMMENDED: gtype = 0 (provided you have the evalg +C subroutine) +C +C CONSTRAINTS: allowed values are just 0 or 1. +C +C htvtype integer +C htvtype indicates in which way the product of the Hessian +C of the objective function times an arbitrary vector will be +C computed. If the user has not been implemented the user- +C supplied evalhd subroutine to do this task then htvtype +C argument must be set to 1 (ONE). In this case an internal +C subroutine that approximates this product by incremental +C quotients will be used. Note that, even in this case, +C evalhd subroutine must be present (with an empty body). +C This is the default option and the empty-body subroutine +C follows: +C +C subroutine evalhd(nind,ind,n,x,m,lambda,rho,d,hd,flag) +C +C C SCALAR ARGUMENTS +C integer nind,n,m,flag +C +C C ARRAY ARGUMENTS +C integer ind(nind) +C double precision x(n),lambda(m),rho(m),d(n),hd(n) +C +C flag = - 1 +C +C end +C +C If, on the other hand, the user prefers to implement his/ +C her own evalhd subroutine then htvtype argument must be +C set to 0 (ZERO). In this case, the product of the Hessian +C times vector d (input argument of evalhd subroutine) must +C be saved in vector hd (output argument of evalhd +C subroutine). The other arguments description as well as +C some hints on how to implement your own evalhd subroutine +C can be found in the GENCAN arguments description. +C +C RECOMMENDED: htvtype = 1 +C +C (you take some risk using this option but, unless you +C have a good evalhd subroutine, incremental quotients is a +C very cheap option) +C +C CONSTRAINTS: allowed values are just 0 or 1. +C +C trtype integer +C Type of Conjugate Gradients ''trust-radius''. trtype +C equal to 0 means Euclidian-norm trust-radius and trtype +C equal to 1 means sup-norm trust radius +C +C RECOMMENDED: trtype = 0 +C +C CONSTRAINTS: allowed values are just 0 or 1. +C +C iprint integer +C Commands printing. Nothing is printed if iprint is +C smaller than 2. If iprint is greater than or equal to +C 2, GENCAN iterations information is printed. If iprint +C is greater than or equal to 3, line searches and +C Conjugate Gradients information is printed. +C +C RECOMMENDED: iprint = 2 +C +C CONSTRAINTS: allowed values are just 2 or 3. +C +C ncomp integer +C This constant is just for printing. In a detailed +C printing option, ncomp component of some vectors will be +C printed +C +C RECOMMENDED: ncomp = 5 +C +C CONSTRAINTS: ncomp >= 0 +C +C s double precision s(n) +C y double precision y(n) +C d double precision d(n) +C ind integer ind(n) +C lastgpns double precision lastgpns(maxitngp) +C w double precision w(5*n) +C working vectors +C +C eta double precision +C Constant for deciding abandon the current face or not. We +C abandon the current face if the norm of the internal +C gradient (here, internal components of the continuous +C projected gradient) is smaller than ( 1 - eta ) times the +C norm of the continuous projected gradient. Using eta = +C 0.9 is a rather conservative strategy in the sense that +C internal iterations are preferred over SPG iterations. +C +C RECOMMENDED: eta = 0.9 +C +C CONSTRAINTS: 0.0 < eta < 1.0 +C +C delmin double precision +C Smaller Conjugate Gradients ''trust radius'' to compute +C the Truncated Newton direction +C +C RECOMMENDED: delmin = 0.1 +C +C CONSTRAINTS: delmin > 0.0 +C +C lspgmi double precision +C See below +C +C lspgma double precision +C The spectral steplength, called lamspg, is projected onto +C the box [lspgmi,lspgma] +C +C RECOMMENDED: lspgmi = 1.0d-10 and lspgma = 1.0d+10 +C +C CONSTRAINTS: lspgma >= lspgmi > 0.0 +C +C theta double precision +C Constant for the angle condition, i.e., at iteration k we +C need a direction dk such that <= - theta +C ||gk||_2 ||dk||_2, where gk is \nabla f(xk) +C +C RECOMMENDED: theta = 10^{-6} +C +C CONSTRAINTS: 0.0 < theta < 1.0 +C +C gamma double precision +C Constant for the Armijo criterion +C f(x + alpha d) <= f(x) + gamma * alpha * +C +C RECOMMENDED: gamma = 1.0d-04 +C +C CONSTRAINTS: 0.0 < gamma < 0.5. +C +C beta double precision +C Constant for the beta condition < beta +C * . If (xk + dk) satisfies the Armijo condition +C but does not satisfy the beta condition then the point is +C accepted, but if it satisfied the Armijo condition and +C also satisfies the beta condition then we know that there +C is the possibility for a successful extrapolation +C +C RECOMMENDED: beta = 0.5 +C +C CONSTRAINTS: 0.0 < beta < 1.0. +C +C sigma1 double precision +C See below +C +C sigma2 double precision +C Constant for the safeguarded interpolation. If alpha_new +C is not inside the interval [sigma1, sigma * alpha] then +C we take alpha_new = alpha / nint +C +C RECOMMENDED: sigma1 = 0.1 and sigma2 = 0.9 +C +C CONSTRAINTS: 0 < sigma1 < sigma2 < 1. +C +C sterel double precision +C See below +C +C steabs double precision +C This constants mean a ''relative small number'' and ''an +C absolute small number'' for the increments in finite +C difference approximations of derivatives +C +C RECOMMENDED: epsrel = 1.0d-07 and epsabs = 1.0d-10 +C +C CONSTRAINTS: sterel >= steabs > 0 +C +C epsrel double precision +C See below +C +C epsabs double precision +C See below +C +C infrel double precision +C See below +C +C infabs double precision +C This four constants mean a ''relative small number'', +C ''an absolute small number'', ''a relative large number'' +C and ''an absolute large number''. Basically, a quantity A +C is considered negligible with respect to another quantity +C B if |A| < max ( epsrel * |B|, epsabs ) +C +C RECOMMENDED: epsrel = 1.0d-10, epsabs = 1.0d-20, +C infrel = 1.0d+20, infabs = 1.0d+99 +C +C CONSTRAINTS: epsrel >= epsabs >= 0.0 +C infabs >= infrel >= 0.0 +C +C On Return +C +C x double precision x(n) +C Final estimation to the solution +C +C f double precision +C Function value at the final estimation +C +C g double precision g(n) +C Gradient at the final estimation +C +C gpeucn2 double precision +C Squared Euclidian norm of the continuous projected +C gradient at the final estimation +C +C gpsupn double precision +C the same as before but with sup-norm +C +C iter integer +C number of iterations +C +C fcnt integer +C number of function evaluations +C +C gcnt integer +C number of gradient evaluations +C +C cgcnt integer +C number of Conjugate Gradients iterations +C +C spgiter integer +C number of Spectral Projected Gradient iterations +C +C spgfcnt integer +C number of functional evaluations along Spectral Projected +C Gradient directions +C +C tniter integer +C number of Truncated-Newton iterations +C +C tnfcnt integer +C number of functional evaluations along Truncated-Newton +C directions +C +C tnintcnt integer +C number of times a backtracking in a Truncated-Newton +C direction was needed +C +C tnexgcnt integer +C number of times an extrapolation in a Truncated-Newton +C direction successfully decreased the objective funtional +C value +C +C tnexbcnt integer +C number of times an extrapolation was aborted in the first +C extrapolated point by an increase in the objective +C functional value +C +C tnstpcnt integer +C number of times the Newton point was accepted (without +C interpolations nor extrapolations) +C +C tnintfe integer +C number of functional evaluations used in interpolations +C along Truncated-Newton directions +C +C tnexgfe integer +C number of functional evaluations used in successful +C extrapolations along Truncated-Newton directions +C +C tnexbfe integer +C number of functional evaluations used in unsuccessful +C extrapolations along Truncated-Newton directions +C +C inform integer +C This output parameter tells what happened in this +C subroutine, according to the following conventions: +C +C 0 = convergence with small Euclidian norm of the +C continuous projected gradient (smaller than epsgpen); +C +C 1 = convergence with small sup-norm of the continuous +C projected gradient (smaller than epsgpsn); +C +C 2 = the algorithm stopped by ''lack of progress'', that +C means that f(xk) - f(x_{k+1}) <= epsnfp * +C max{ f(x_j) - f(x_{j+1}, j < k } during maxitnfp +C consecutive iterations. If desired, set maxitnfp +C equal to maxit to inhibit this stopping criterion. +C +C 3 = the algorithm stopped because the order of the +C Euclidian norm of the continuous projected gradient +C did not change during maxitngp consecutive +C iterations. Probably, we are asking for an +C exaggerated small norm of continuous projected +C gradient for declaring convergence. If desired, set +C maxitngp equal to maxit to inhibit this stopping +C criterion. +C +C 4 = the algorithm stopped because the functional value +c is very small (smaller than fmin). If desired, set +C fmin equal to minus infabs to inhibit this stopping +C criterion. +C +C 6 = too small step in a line search. After having made at +C least mininterp interpolations, the steplength +C becames small. ''small steplength'' means that we are +C at point x with direction d and step alpha, and +C +C alpha * ||d||_infty < max( epsabs, epsrel * +C ||x||_infty ). +C +C In that case failure of the line search is declared +C (may be the direction is not a descent direction due +C to an error in the gradient calculations). If +C desired, set mininterp equal to maxfc to inhibit this +C stopping criterion. +C +C 7 = it was achieved the maximum allowed number of +C iterations (maxit); +C +C 8 = it was achieved the maximum allowed number of +C function evaluations (maxfc); +C +C < 0 = error in evalal, evalnal or evalhd subroutines. + +C LOCAL SCALARS + character * 3 ittype + integer cgiter,cgmaxit,fcntprev,i,infotmp,itnfp,nind,nprint, + + rbdind,rbdtype,tnexbprev,tnexgprev,tnintprev + double precision acgeps,amax,amaxx,bestprog,bcgeps,cgeps,currprog, + + delta,epsgpen2,fprev,gieucn2,gpeucn20,gpi,gpnmax,gpsupn0, + + kappa,lamspg,ometa2,sts,sty,xnorm + logical packmolprecision + +C ================================================================== +C Initialization +C ================================================================== + +C Set some initial values: + +C counters, + iter = 0 + fcnt = 0 + gcnt = 0 + cgcnt = 0 + + spgiter = 0 + spgfcnt = 0 + + tniter = 0 + tnfcnt = 0 + + tnstpcnt = 0 + tnintcnt = 0 + tnexgcnt = 0 + tnexbcnt = 0 + + tnintfe = 0 + tnexgfe = 0 + tnexbfe = 0 + +C just for printing, + nprint = min0( n, ncomp ) + +C for testing convergence, + epsgpen2 = epsgpen ** 2 + +C for testing whether to abandon the current face or not, +C (ometa2 means '(one minus eta) squared') + ometa2 = ( 1.0d0 - eta ) ** 2 + +C for testing progress in f, and + fprev = infabs + bestprog = 0.0d0 + itnfp = 0 + +C for testing progress in the projected gradient norm. + do i = 0,maxitngp - 1 + lastgpns(i) = infabs + end do + +C Print problem information + + if( iprint .ge. 3 ) then + write(*, 977) n + write(*, 978) nprint,(l(i),i=1,nprint) + write(*, 979) nprint,(u(i),i=1,nprint) + write(*, 980) nprint,(x(i),i=1,nprint) + + write(10,977) n + write(10,978) nprint,(l(i),i=1,nprint) + write(10,979) nprint,(u(i),i=1,nprint) + write(10,980) nprint,(x(i),i=1,nprint) + end if + +C Project initial guess. If the initial guess is infeasible, +C projection puts it into the box. + + do i = 1,n + x(i) = max( l(i), min( x(i), u(i) ) ) + end do + +C Compute x Euclidian norm + + xnorm = 0.0d0 + do i = 1,n + xnorm = xnorm + x(i) ** 2 + end do + xnorm = sqrt( xnorm ) + +C Compute function and gradient at the initial point + + call evalal(n,x,m,lambda,rho,f,inform) + +c LM: Added packmolprecision function test, for Packmol + + if ( packmolprecision(n,x) ) then + if(iprint.gt.0) then + write(*,780) +780 format(' Current point is a solution.') + end if + return + end if + + fcnt = fcnt + 1 + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 3 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + end if + + if ( gtype .eq. 0 ) then + call evalnal(n,x,m,lambda,rho,g,inform) + else ! if ( gtype .eq. 1 ) then + call evalnaldiff(n,x,m,lambda,rho,g,sterel,steabs,inform) + end if + gcnt = gcnt + 1 + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 3 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + end if + +C Compute continuous-project-gradient Euclidian and Sup norms, +C internal gradient Euclidian norm, and store in nind the number of +C free variables and in array ind their identifiers. + + nind = 0 + gpsupn = 0.0d0 + gpeucn2 = 0.0d0 + gieucn2 = 0.0d0 + do i = 1,n + gpi = min( u(i), max( l(i), x(i) - g(i) ) ) - x(i) + gpsupn = max( gpsupn, abs( gpi ) ) + gpeucn2 = gpeucn2 + gpi ** 2 + if ( x(i) .gt. l(i) .and. x(i) .lt. u(i) ) then + gieucn2 = gieucn2 + gpi ** 2 + nind = nind + 1 + ind(nind) = i + end if + end do + +C Compute a linear relation between gpeucn2 and cgeps2, i.e., +C scalars a and b such that +c +C a * log10(||g_P(x_0)||_2^2) + b = log10(cgeps_0^2) and +c +C a * log10(||g_P(x_f)||_2^2) + b = log10(cgeps_f^2), +c +C where cgeps_0 and cgeps_f are provided. Note that if +C cgeps_0 is equal to cgeps_f then cgeps will be always +C equal to cgeps_0 and cgeps_f. + +C We introduce now a linear relation between gpsupn and cgeps also. + +c LM: changed to avoid error with gpsupn=0 + if ( gpsupn .ne. 0.0d0 ) then + acgeps = log10( cgepsf / cgepsi ) / log10( cggpnf / gpsupn ) + bcgeps = log10( cgepsi ) - acgeps * log10( gpsupn ) + else + acgeps = 0.0d0 + bcgeps = cgepsf + end if +c if ( cgscre .eq. 1 ) then +c acgeps = 2.0d0 * log10( cgepsf / cgepsi ) / +c + log10( cggpnf ** 2 / gpeucn2 ) +c bcgeps = 2.0d0 * log10( cgepsi ) - acgeps * log10( gpeucn2 ) +c else ! if ( cgscre .eq. 2 ) then +c acgeps = log10( cgepsf / cgepsi ) / log10( cggpnf / gpsupn ) +c bcgeps = log10( cgepsi ) - acgeps * log10( gpsupn ) +c end if + +C And it will be used for the linear relation of cgmaxit + + gpsupn0 = gpsupn + gpeucn20 = gpeucn2 + +C Print initial information + + if( iprint .ge. 2 ) then +c LM: output for packmol +c write(*,1003) iter,f,gpsupn + if((mod((iter-1),10).eq.0.or.iter.eq.0).and.iter.ne.1) then + write(*,778) + else if(mod(iter,10).eq.0) then + write(*,779) + else if(iter.ne.1) then + write(*,777) + end if + end if +777 format('*******',$) +778 format(' |',$) +779 format('**********|') + + if( iprint .ge. 3 ) then + write(*, 981) iter + write(*, 985) nprint,(x(i),i=1,nprint) + write(*, 986) nprint,(g(i),i=1,nprint) + write(*, 987) nprint,(min(u(i),max(l(i),x(i)-g(i)))-x(i),i=1, + + nprint) + write(*, 988) min0(nprint,nind),nind,(ind(i),i=1,min0(nprint, + + nind)) + write(*, 1002) f,sqrt(gpeucn2),sqrt(gieucn2),gpsupn,nind,n, + + spgiter,tniter,fcnt,gcnt,cgcnt + + write(10,981) iter + write(10,985) nprint,(x(i),i=1,nprint) + write(10,986) nprint,(g(i),i=1,nprint) + write(10,987) nprint,(min(u(i),max(l(i),x(i)-g(i)))-x(i),i=1, + + nprint) + write(10,988) min0(nprint,nind),nind,(ind(i),i=1,min0(nprint, + + nind)) + write(10,1002) f,sqrt(gpeucn2),sqrt(gieucn2),gpsupn,nind,n, + + spgiter,tniter,fcnt,gcnt,cgcnt + end if + +C ================================================================== +C Main loop +C ================================================================== + + 100 continue + +C ================================================================== +C Test stopping criteria +C ================================================================== + +c LM: Added packmolprecision function test, for Packmol + + if ( packmolprecision(n,x) ) then + goto 500 + end if + +C Test whether the continuous-projected-gradient Euclidian norm +C is small enough to declare convergence + + if ( gpeucn2 .le. epsgpen2 ) then + inform = 0 + + if ( iprint .ge. 3 ) then + write(*, 990) inform,epsgpen + write(10,990) inform,epsgpen + end if + + go to 500 + end if + +C Test whether the continuous-projected-gradient Sup norm +C is small enough to declare convergence + + if ( gpsupn .le. epsgpsn ) then + inform = 1 + + if ( iprint .ge. 3 ) then + write(*, 991) inform,epsgpsn + write(10,991) inform,epsgpsn + end if + + go to 500 + end if + +C Test whether we performed many iterations without good progress +C of the functional value + + currprog = fprev - f + bestprog = max( currprog, bestprog ) + + if ( currprog .le. epsnfp * bestprog ) then + + itnfp = itnfp + 1 + + if ( itnfp .ge. maxitnfp ) then + inform = 2 + + if ( iprint .ge. 3 ) then + write(*, 992) inform,epsnfp,maxitnfp + write(10,992) inform,epsnfp,maxitnfp + end if + + go to 500 + endif + + else + itnfp = 0 + endif + +C Test whether we have performed many iterations without good +C reduction of the euclidian-norm of the projected gradient + + gpnmax = 0.0d0 + do i = 0,maxitngp - 1 + gpnmax = max( gpnmax, lastgpns(i) ) + end do + + lastgpns(mod( iter, maxitngp )) = gpeucn2 + + if ( gpeucn2 .ge. gpnmax ) then + + inform = 3 + + if ( iprint .ge. 3 ) then + write(*, 993) inform,maxitngp + write(10,993) inform,maxitngp + end if + + go to 500 + + endif + +C Test whether the functional value is very small + + if ( f .le. fmin ) then + + inform = 4 + + if ( iprint .ge. 3 ) then + write(*, 994) inform,fmin + write(10,994) inform,fmin + end if + + go to 500 + + end if + +C Test whether the number of iterations is exhausted + + if ( iter .ge. maxit ) then + + inform = 7 + + if ( iprint .ge. 3 ) then + write(*, 997) inform,maxit + write(10,997) inform,maxit + end if + + go to 500 + + end if + +C Test whether the number of functional evaluations is exhausted + + if ( fcnt .ge. maxfc ) then + + inform = 8 + + if ( iprint .ge. 3 ) then + write(*, 998) inform,maxfc + write(10,998) inform,maxfc + end if + + go to 500 + + end if + +C ================================================================== +C The stopping criteria were not satisfied, a new iteration will be +C made +C ================================================================== + + iter = iter + 1 + +C ================================================================== +C Save current values, f, x and g +C ================================================================== + + fprev = f + + do i = 1,n + s(i) = x(i) + y(i) = g(i) + end do + +C ================================================================== +C Compute new iterate +C ================================================================== + +C We abandon the current face if the norm of the internal gradient +C (here, internal components of the continuous projected gradient) +C is smaller than (1-eta) times the norm of the continuous +C projected gradient. Using eta=0.9 is a rather conservative +C strategy in the sense that internal iterations are preferred over +C SPG iterations. Replace eta = 0.9 by other tolerance in (0,1) if +C you find it convenient. + + if ( gieucn2 .le. ometa2 * gpeucn2 ) then + +C ============================================================== +C Some constraints should be abandoned. Compute the new iterate +C using an SPG iteration +C ============================================================== + + ittype = 'SPG' + spgiter = spgiter + 1 + +C Compute spectral steplength + + if ( iter .eq. 1 .or. sty .le. 0.0d0 ) then + lamspg = max( 1.0d0, xnorm ) / sqrt( gpeucn2 ) + else + lamspg = sts / sty + end if + lamspg = min( lspgma, max( lspgmi, lamspg ) ) + +C Perform a line search with safeguarded quadratic interpolation +C along the direction of the spectral continuous projected +C gradient + + fcntprev = fcnt + + call spgls(n,x,m,lambda,rho,f,g,l,u,lamspg,nint,mininterp, + + fmin,maxfc,iprint,fcnt,inform,w(1),w(n+1),gamma,sigma1,sigma2, + + sterel,steabs,epsrel,epsabs,infrel,infabs) + + spgfcnt = spgfcnt + ( fcnt - fcntprev ) + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 3 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + end if + +C Compute the gradient at the new iterate + + if ( gtype .eq. 0 ) then + call evalnal(n,x,m,lambda,rho,g,inform) + else ! if ( gtype .eq. 1 ) then + call evalnaldiff(n,x,m,lambda,rho,g,sterel,steabs,inform) + end if + gcnt = gcnt + 1 + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 3 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + end if + + else + +C ============================================================== +C The new iterate will belong to the closure of the current face +C ============================================================== + + ittype = 'TN ' + tniter = tniter + 1 + +C Compute trust-region radius + + if ( iter .eq. 1 ) then + if( udelta0 .le. 0.0d0 ) then + delta = max( delmin, 0.1d0 * max( 1.0d0, xnorm ) ) + else + delta = udelta0 + end if + else + delta = max( delmin, 10.0d0 * sqrt( sts ) ) + end if + +C Shrink the point, its gradient and the bounds + + call shrink(nind,ind,n,x) + call shrink(nind,ind,n,g) + call shrink(nind,ind,n,l) + call shrink(nind,ind,n,u) + +C Compute the descent direction solving the newtonian system by +C conjugate gradients + +C Set conjugate gradient stopping criteria. Default values are +C taken if you set ucgeps < 0 and ucgmaxit < 0, respectively. +C Otherwise, the parameters cgeps and cgmaxit will be the ones +C set by the user. + + if( ucgmaxit .le. 0 ) then + if ( nearlyq ) then + cgmaxit = nind + else + if ( cgscre .eq. 1 ) then + kappa = log10( gpeucn2 / gpeucn20 )/ + + log10( epsgpen2 / gpeucn20 ) + else ! if ( cgscre .eq. 2 ) then + kappa= log10( gpsupn / gpsupn0 ) / + + log10( epsgpsn / gpsupn0 ) + end if + kappa = max( 0.0d0, min( 1.0d0, kappa ) ) + cgmaxit = int( + + ( 1.0d0 - kappa ) * max( 1.0d0, 10.0d0 * + + log10( dfloat( nind ) ) ) + kappa * dfloat( nind ) ) +c L. Martinez added to accelerate the iterations near the solution + cgmaxit = min(20,cgmaxit) + end if +c cgmaxit = 2 * nind + else + cgmaxit = ucgmaxit + end if + + if ( cgscre .eq. 1 ) then + cgeps = sqrt( 10.0d0 ** ( acgeps * log10( gpeucn2 ) + + + bcgeps ) ) + else ! if ( cgscre .eq. 2 ) then + cgeps = 10.0d0 ** ( acgeps * log10( gpsupn ) + bcgeps ) + end if + cgeps = max( cgepsf, min( cgepsi, cgeps ) ) + +C Call conjugate gradients + + call cg(nind,ind,n,x,m,lambda,rho,g,delta,l,u,cgeps,epsnqmp, + + maxitnqmp,cgmaxit,nearlyq,gtype,htvtype,trtype,iprint,ncomp,d, + + cgiter,rbdtype,rbdind,inform,w(1),w(n+1),w(2*n+1),w(3*n+1), + + w(4*n+1),theta,sterel,steabs,epsrel,epsabs,infrel,infabs) + + cgcnt = cgcnt + cgiter + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 3 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + + end if + +C Compute maximum step + + if ( inform .eq. 2 ) then + amax = 1.0d0 + else + amax = infabs + do i = 1,nind + if ( d(i) .gt. 0.0d0 ) then + amaxx = ( u(i) - x(i) ) / d(i) + if ( amaxx .lt. amax ) then + amax = amaxx + rbdind = i + rbdtype = 2 + end if + else if ( d(i) .lt. 0.0d0 ) then + amaxx = ( l(i) - x(i) ) / d(i) + if ( amaxx .lt. amax ) then + amax = amaxx + rbdind = i + rbdtype = 1 + end if + end if + end do + end if + +C Perform the line search + + tnintprev = tnintcnt + tnexgprev = tnexgcnt + tnexbprev = tnexbcnt + + fcntprev = fcnt + + call tnls(nind,ind,n,x,m,lambda,rho,l,u,f,g,d,amax,rbdtype, + + rbdind,nint,next,mininterp,maxextrap,fmin,maxfc,gtype,iprint, + + fcnt,gcnt,tnintcnt,tnexgcnt,tnexbcnt,inform,w(1),w(n+1), + + w(2*n+1),gamma,beta,sigma1,sigma2,sterel,steabs,epsrel,epsabs, + + infrel,infabs) + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 3 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + + end if + + if ( tnintcnt .gt. tnintprev ) then + tnintfe = tnintfe + ( fcnt - fcntprev ) + else if ( tnexgcnt .gt. tnexgprev ) then + tnexgfe = tnexgfe + ( fcnt - fcntprev ) + else if ( tnexbcnt .gt. tnexbprev ) then + tnexbfe = tnexbfe + ( fcnt - fcntprev ) + else + tnstpcnt = tnstpcnt + 1 + end if + + tnfcnt = tnfcnt + ( fcnt - fcntprev ) + +C Expand the point, its gradient and the bounds + + call expand(nind,ind,n,x) + call expand(nind,ind,n,g) + call expand(nind,ind,n,l) + call expand(nind,ind,n,u) + +C If the line search (interpolation) in the Truncated Newton +C direction stopped due to a very small step (inform = 6), we +C will discard this iteration and force a SPG iteration + +C Note that tnls subroutine was coded in such a way that in case +C of inform = 6 termination the subroutine discards all what was +C done and returns with the same point it started + + if ( inform .eq. 6 ) then + + if ( iprint .ge. 3 ) then + write(*,*) + write(*,*) + + ' The previous TN iteration was discarded due to', + + ' a termination for very small step in the line ', + + ' search. A SPG iteration will be forced now. ' + + write(10,*) + write(10,*) + + ' The previous TN iteration was discarded due to', + + ' a termination for very small step in the line ', + + ' search. A SPG iteration will be forced now. ' + end if + + ittype = 'SPG' + spgiter = spgiter + 1 + +C Compute spectral steplength + + if ( iter .eq. 1 .or. sty .le. 0.0d0 ) then + lamspg = max( 1.0d0, xnorm ) / sqrt( gpeucn2 ) + else + lamspg = sts / sty + end if + lamspg = min( lspgma, max( lspgmi, lamspg ) ) + +C Perform a line search with safeguarded quadratic +C interpolation along the direction of the spectral +C continuous projected gradient + + fcntprev = fcnt + + call spgls(n,x,m,lambda,rho,f,g,l,u,lamspg,nint,mininterp, + + fmin,maxfc,iprint,fcnt,inform,w(1),w(n+1),gamma,sigma1, + + sigma2,sterel,steabs,epsrel,epsabs,infrel,infabs) + + spgfcnt = spgfcnt + ( fcnt - fcntprev ) + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 3 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + end if + +C Compute the gradient at the new iterate + + infotmp = inform + + if ( gtype .eq. 0 ) then + call evalnal(n,x,m,lambda,rho,g,inform) + else ! if ( gtype .eq. 1 ) then + call evalnaldiff(n,x,m,lambda,rho,g,sterel,steabs, + + inform) + end if + gcnt = gcnt + 1 + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 3 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + end if + + inform = infotmp + + end if + + end if + +C ================================================================== +C Prepare for the next iteration +C ================================================================== + +C This adjustment/projection is ''por lo que las putas pudiera'' + + do i = 1,n + if ( x(i) .le. l(i) + max( epsrel * abs( l(i) ), epsabs ) ) + + then + x(i) = l(i) + else if (x(i). ge. u(i) - max( epsrel * abs( u(i) ), epsabs )) + + then + x(i) = u(i) + end if + end do + +C Compute x Euclidian norm + + xnorm = 0.0d0 + do i = 1,n + xnorm = xnorm + x(i) ** 2 + end do + xnorm = sqrt( xnorm ) + +C Compute s = x_{k+1} - x_k, y = g_{k+1} - g_k, and + + sts = 0.0d0 + sty = 0.0d0 + do i = 1,n + s(i) = x(i) - s(i) + y(i) = g(i) - y(i) + sts = sts + s(i) ** 2 + sty = sty + s(i) * y(i) + end do + +C Compute continuous-project-gradient Euclidian and Sup norms, +C internal gradient Euclidian norm, and store in nind the number of +C free variables and in array ind their identifiers. + + nind = 0 + gpsupn = 0.0d0 + gpeucn2 = 0.0d0 + gieucn2 = 0.0d0 + do i = 1,n + gpi = min( u(i), max( l(i), x(i) - g(i) ) ) - x(i) + gpsupn = max( gpsupn, abs( gpi ) ) + gpeucn2 = gpeucn2 + gpi ** 2 + if ( x(i) .gt. l(i) .and. x(i) .lt. u(i) ) then + gieucn2 = gieucn2 + gpi ** 2 + nind = nind + 1 + ind(nind) = i + end if + end do + +C Print information of this iteration + + if( iprint .ge. 2 ) then +c Output for packmol +c write(*, 1003) iter,f,gpsupn + if((mod((iter-1),10).eq.0.or.iter.eq.0).and.iter.ne.1) then + write(*,778) + else if(mod(iter,10).eq.0) then + write(*,779) + else if(iter.ne.1) then + write(*,777) + end if + end if + + if ( iprint .ge. 3 ) then + write(*, 983) iter,ittype + write(*, 985) nprint,(x(i),i=1,nprint) + write(*, 986) nprint,(g(i),i=1,nprint) + write(*, 987) nprint,(min(u(i),max(l(i),x(i)-g(i)))-x(i),i=1, + + nprint) + write(*, 988) min0(nprint,nind),nind,(ind(i),i=1,min0(nprint, + + nind)) + write(*, 1002) f,sqrt(gpeucn2),sqrt(gieucn2),gpsupn,nind,n, + + spgiter,tniter,fcnt,gcnt,cgcnt + + write(10,983) iter,ittype + write(10,985) nprint,(x(i),i=1,nprint) + write(10,986) nprint,(g(i),i=1,nprint) + write(10,987) nprint,(min(u(i),max(l(i),x(i)-g(i)))-x(i),i=1, + + nprint) + write(10,988) min0(nprint,nind),nind,(ind(i),i=1,min0(nprint, + + nind)) + write(10,1002) f,sqrt(gpeucn2),sqrt(gieucn2),gpsupn,nind,n, + + spgiter,tniter,fcnt,gcnt,cgcnt + end if + +C ================================================================== +C Test some stopping criteria that may occur inside the line +C searches +C ================================================================== + + if ( inform .eq. 6 ) then + + if ( iprint .ge. 3 ) then + write(*, 996) inform,mininterp,epsrel,epsabs + write(10,996) inform,mininterp,epsrel,epsabs + end if + + go to 500 + + end if + +C ================================================================== +C Iterate +C ================================================================== + + go to 100 + +C ================================================================== +C End of main loop +C ================================================================== + +C ================================================================== +C Report output status and return +C ================================================================== + + 500 continue + +C Print final information + + if ( iprint .ge. 3 ) then + write(*, 982) iter + write(*, 985) nprint,(x(i),i=1,nprint) + write(*, 986) nprint,(g(i),i=1,nprint) + write(*, 987) nprint,(min(u(i),max(l(i),x(i)-g(i)))-x(i),i=1, + + nprint) + write(*, 988) min0(nprint,nind),nind,(ind(i),i=1,min0(nprint, + + nind)) + write(*, 1002) f,sqrt(gpeucn2),sqrt(gieucn2),gpsupn,nind,n, + + spgiter,tniter,fcnt,gcnt,cgcnt + + write(10,982) iter + write(10,985) nprint,(x(i),i=1,nprint) + write(10,986) nprint,(g(i),i=1,nprint) + write(10,987) nprint,(min(u(i),max(l(i),x(i)-g(i)))-x(i),i=1, + + nprint) + write(10,988) min0(nprint,nind),nind,(ind(i),i=1,min0(nprint, + + nind)) + write(10,1002) f,sqrt(gpeucn2),sqrt(gieucn2),gpsupn,nind,n, + + spgiter,tniter,fcnt,gcnt,cgcnt + end if + + return + +C Non-executable statements + + 977 format(/1X, 'Entry to GENCAN. Number of variables: ',I7) + 978 format(/1X,'Lower bounds (first ',I6, ' components): ', + */,6(1X,1PD11.4)) + 979 format(/1X,'Upper bounds (first ',I6, ' components): ', + */,6(1X,1PD11.4)) + 980 format(/1X,'Initial point (first ',I6, ' components): ', + */,6(1X,1PD11.4)) + 981 format(/1X,'GENCAN iteration: ',I6, ' (Initial point)') + 982 format(/1X,'GENCAN iteration: ',I6, ' (Final point)') + 983 format(/,1X,'GENCAN iteration: ',I6, + *' (This point was obtained using a ',A3,' iteration)') + 985 format(1X,'Current point (first ',I6, ' components): ', + */,6(1X,1PD11.4)) + 986 format(1X,'Current gradient (first ',I6, ' components): ', + */,6(1X,1PD11.4)) + 987 format(1X,'Current continuous projected gradient (first ',I6, + *' components): ',/,6(1X,1PD11.4)) + 988 format(1X,'Current free variables (first ',I6, + *', total number ',I6,'): ',/,10(1X,I6)) + 990 format(/1X,'Flag of GENCAN = ',I3, + *' (convergence with Euclidian-norm of the projected gradient', + */,1X,'smaller than ',1PD11.4,')') + 991 format(/1X,'Flag of GENCAN = ',I3, + *' (convergence with sup-norm of the projected gradient', + */,1X,'smaller than ',1PD11.4,')') + 992 format(/1X,'Flag of GENCAN= ',I3, + *' (The algorithm stopped by lack of enough progress. This means', + */,1X,'that f(x_k) - f(x_{k+1}) .le. ',1PD11.4, + *' * max [ f(x_j)-f(x_{j+1}, j < k ]',/,1X,'during ',I7, + *' consecutive iterations') + 993 format(/1X,'Flag of GENCAN = ',I3, + *' (The algorithm stopped because the order of the', + */,1X,'Euclidian-norm of the continuous projected gradient did', + *' not change during ',/,1X,I7,' consecutive iterations.', + *' Probably, an exaggerated small norm of the',/,1X,'continuous', + *' projected gradient is required for declaring convergence') + 994 format(/1X,'Flag of GENCAN = ',I3, + *' (The algorithm stopped because the functional value is', + */,1X,'smaller than ',1PD11.4) + 996 format(/1X,'Flag of GENCAN = ',I3, + *' (Too small step in a line search. After having made at ', + */,1X,'least ',I7,' interpolations, the steplength becames small.', + *' Small means that',/,1X,'we were at point x with direction d', + *' and took a step alpha such that',/,1X,'alpha * |d_i| .lt.', + *' max [',1PD11.4,' * |x_i|,',1PD11.4,' ] for all i)') + 997 format(/1X,'Flag of GENCAN = ',I3, + *' (It was exceeded the maximum allowed number of iterations', + */,1X,'(maxit=',I7,')') + 998 format(/1X,'Flag of GENCAN = ',I3, + *' (It was exceeded the maximum allowed number of functional', + */,1X,'evaluations (maxfc=',I7,')') + 1002 format(1X,'Functional value: ', 1PD11.4, + */,1X,'Euclidian-norm of the continuous projected gradient: ', + *1PD11.4, + */,1X,'Euclidian-norm of the internal projection of gp: ',1PD11.4, + */,1X,'Sup-norm of the continuous projected gradient: ',1PD11.4, + */,1X,'Free variables at this point: ',I7, + *' (over a total of ',I7,')', + */,1X,'SPG iterations: ',I7, + */,1X,'TN iterations: ',I7, + */,1X,'Functional evaluations: ',I7, + */,1X,'Gradient evaluations: ',I7, + */,1X,'Conjugate gradient iterations: ',I7) + 1003 format(6X,I6,T22,D17.6,T43,D17.6) +C1003 format(6X,'Iter = ',I6,' f = ',1PD11.4,' gpsupn = ',1PD11.4) + 1000 format(/1X,'Flag of GENCAN = ',I3,' Fatal Error') + + end + +C ****************************************************************** +C ****************************************************************** + + subroutine spgls(n,x,m,lambda,rho,f,g,l,u,lamspg,nint,mininterp, + +fmin,maxfc,iprint,fcnt,inform,xtrial,d,gamma,sigma1,sigma2,sterel, + +steabs,epsrel,epsabs,infrel,infabs) + + implicit none + +C SCALAR ARGUMENTS + integer fcnt,m,maxfc,mininterp,n,inform,iprint + double precision epsabs,epsrel,f,fmin,gamma,infrel,infabs,lamspg, + + nint,sigma1,sigma2,steabs,sterel + +C ARRAY ARGUMENTS + double precision d(n),g(n),l(n),lambda(m),rho(m),u(n),x(n), + + xtrial(n) + +C Safeguarded quadratic interpolation, used in the Spectral +C Projected Gradient directions. +C +C On Entry +C +C n integer +C the order of the x +C +C x double precision x(n) +C current point +C +C m integer +C lambda double precision lambda(m) +C rho double precision rho(m) +C These three parameters are not used nor modified by +C GENCAN and they are passed as arguments to the user- +C defined subroutines evalal and evalnal to compute the +C objective function and its gradient, respectively. +C Clearly, in an Augmented Lagrangian context, if GENCAN is +C being used to solve the bound-constrainted subproblems, m +C would be the number of constraints, lambda the Lagrange +C multipliers approximation and rho the penalty parameters +C +C f double precision +C function value at the current point +C +C g double precision g(n) +C gradient vector at the current point +C +C l double precision l(n) +C lower bounds +C +C u double precision u(n) +C upper bounds +C +C lamspg double precision +C spectral steplength +C +C nint double precision +C constant for the interpolation. See the description of +C sigma1 and sigma2 above. Sometimes we take as a new +C trial step the previous one divided by nint +C +C RECOMMENDED: nint = 2.0 +C +C mininterp integer +C constant for testing if, after having made at least +C mininterp interpolations, the steplength is so small. In +C that case failure of the line search is declared (may be +C the direction is not a descent direction due to an error +C in the gradient calculations) +C +C RECOMMENDED: mininterp = 4 +C +C fmin double precision +C functional value for the stopping criterion f <= fmin +C +C maxfc integer +C maximum number of functional evaluations +C +C iprint integer +C Commands printing. Nothing is printed if iprint is +C smaller than 2. If iprint is greater than or equal to +C 2, GENCAN iterations information is printed. If iprint +C is greater than or equal to 3, line searches and +C Conjugate Gradients information is printed. +C +C RECOMMENDED: iprint = 2 +C +C CONSTRAINTS: allowed values are just 2 or 3. +C +C xtrial double precision xtrial(n) +C d double precision d(n) +C working vectors +C +C gamma double precision +C constant for the Armijo criterion +C f(x + alpha d) <= f(x) + gamma * alpha * <\nabla f(x),d> +C +C RECOMMENDED: gamma = 10^{-4} +C +C sigma1 double precision +C sigma2 double precision +C constant for the safeguarded interpolation +C if alpha_new \notin [sigma1, sigma*alpha] then we take +C alpha_new = alpha / nint +C +C RECOMMENDED: sigma1 = 0.1 and sigma2 = 0.9 +C +C sterel double precision +C steabs double precision +C this constants mean a ``relative small number'' and ``an +C absolute small number'' for the increments in finite +C difference approximations of derivatives +C +C RECOMMENDED: epsrel = 10^{-7}, epsabs = 10^{-10} +C +C epsrel double precision +C epsabs double precision +C infrel double precision +C infabs double precision +C this constants mean a ``relative small number'', ``an +C absolute small number'', and ``infinite or a very big +C number''. Basically, a quantity A is considered +C negligible with respect to another quantity B if |A| < +C max ( epsrel * |B|, epsabs ) +C +C RECOMMENDED: epsrel = 10^{-10}, epsabs = 10^{-20}, +C infrel = 10^{+20}, infabs = 10^{+99} +C +C On Return +C +C x double precision +C final estimation of the solution +C +C f double precision +C functional value at the final estimation +C +C fcnt integer +C number of functional evaluations used in the line search +C +C inform integer +C This output parameter tells what happened in this +C subroutine, according to the following conventions: +C +C 0 = convergence with an Armijo-like criterion +C (f(xnew) <= f(x) + gamma * alpha * ); +C +C 4 = the algorithm stopped because the functional value +C is smaller than fmin; +C +C 6 = too small step in the line search. After having made +C at least mininterp interpolations, the steplength +C becames small. ''small steplength'' means that we are +C at point x with direction d and step alpha, and, for +C all i, +C +C | alpha * d(i) | <= max ( epsrel * |x(i)|, epsabs ). +C +C In that case failure of the line search is declared +C (maybe the direction is not a descent direction due +C to an error in the gradient calculations). Use +C mininterp > maxfc to inhibit this criterion; +C +C 8 = it was achieved the maximum allowed number of +C function evaluations (maxfc); +C +C < 0 = error in evalf subroutine. + +C LOCAL SCALARS + logical samep + integer i,interp + double precision alpha,atmp,ftrial,gtd + +C Print presentation information + + if ( iprint .ge. 4 ) then + write(*, 980) lamspg + write(10,980) lamspg + end if + +C Initialization + + interp = 0 + +C Compute first trial point, spectral projected gradient direction, +C and directional derivative . + + alpha = 1.0d0 + + gtd = 0.0d0 + do i = 1,n + xtrial(i) = min( u(i), max( l(i), x(i) - lamspg * g(i) ) ) + d(i) = xtrial(i) - x(i) + gtd = gtd + g(i) * d(i) + end do + + call evalal(n,xtrial,m,lambda,rho,ftrial,inform) + fcnt = fcnt + 1 + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 4 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + + end if + +C Print information of the first trial + + if ( iprint .ge. 4 ) then + write(*, 999) alpha,ftrial,fcnt + write(10,999) alpha,ftrial,fcnt + end if + +C Main loop + + 100 continue + +C Test Armijo stopping criterion + + if ( ftrial .le. f + gamma * alpha * gtd ) then + + f = ftrial + + do i = 1,n + x(i) = xtrial(i) + end do + + inform = 0 + + if ( iprint .ge. 4 ) then + write(*, 990) inform + write(10,990) inform + end if + + go to 500 + + end if + +C Test whether f is very small + + if ( ftrial .le. fmin ) then + + f = ftrial + + do i = 1,n + x(i) = xtrial(i) + end do + + inform = 4 + + if ( iprint .ge. 4 ) then + write(*, 994) inform + write(10,994) inform + end if + + go to 500 + + end if + +C Test whether the number of functional evaluations is exhausted + + if ( fcnt .ge. maxfc ) then + + if ( ftrial .lt. f ) then + + f = ftrial + + do i = 1,n + x(i) = xtrial(i) + end do + + end if + + inform = 8 + + if ( iprint .ge. 4 ) then + write(*, 998) inform + write(10,998) inform + end if + + go to 500 + + end if + +C Compute new step (safeguarded quadratic interpolation) + + interp = interp + 1 + + if ( alpha .lt. sigma1 ) then + alpha = alpha / nint + + else + atmp = ( - gtd * alpha ** 2 ) / + + ( 2.0d0 * ( ftrial - f - alpha * gtd ) ) + + if ( atmp .lt. sigma1 .or. atmp .gt. sigma2 * alpha ) then + alpha = alpha / nint + + else + alpha = atmp + end if + end if + +C Compute new trial point + + do i = 1,n + xtrial(i) = x(i) + alpha * d(i) + end do + + call evalal(n,xtrial,m,lambda,rho,ftrial,inform) + fcnt = fcnt + 1 + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 4 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + + end if + +C Print information of the current trial + + if ( iprint .ge. 4 ) then + write(*, 999) alpha,ftrial,fcnt + write(10,999) alpha,ftrial,fcnt + end if + +C Test whether at least mininterp interpolations were made and two +C consecutive iterates are close enough + + samep = .true. + do i = 1,n + if ( abs( alpha * d(i) ) .gt. + + max( epsrel * abs( x(i) ), epsabs ) ) then + samep = .false. + end if + end do + + if ( interp .ge. mininterp .and. samep ) then + + if ( ftrial .lt. f ) then + + f = ftrial + + do i = 1,n + x(i) = xtrial(i) + end do + + end if + + inform = 6 + + if ( iprint .ge. 4 ) then + write(*, 996) inform + write(10,996) inform + end if + + go to 500 + + end if + +C Iterate + + go to 100 + +C Return + + 500 continue + + return + +C Non-executable statements + + 980 format(/,6x,'SPG (spectral steplength ',1PD11.4,')',/,/, + * 6x,'SPG Line search') + 999 format(6x,'Alpha= ',1PD11.4,' F= ',1PD11.4,' FE= ',I5) + 990 format(6x,'Flag of SPG Line search = ',I3, + * ' (Convergence with an Armijo-like criterion)') + 994 format(6x,'Flag of SPG Line search = ',I3, + * ' (Small functional value, smaller than ',/, + * 6X,'parameter fmin)') + 996 format(6x,'Flag of SPG Line search = ',I3, + * ' (Too small step in the interpolation)') + 998 format(6x,'Flag of SPG Line search = ',I3, + * ' (Too many functional evaluations)') + 1000 format(6x,'Flag of SPG Line search = ',I3,' Fatal Error') + + end + +C ****************************************************************** +C ****************************************************************** + + subroutine cg(nind,ind,n,x,m,lambda,rho,g,delta,l,u,eps,epsnqmp, + +maxitnqmp,maxit,nearlyq,gtype,htvtype,trtype,iprint,ncomp,s,iter, + +rbdtype,rbdind,inform,w,y,r,d,sprev,theta,sterel,steabs,epsrel, + +epsabs,infrel,infabs) + + implicit none + +C SCALAR ARGUMENTS + logical nearlyq + integer gtype,htvtype,inform,iprint,iter,m,maxit,maxitnqmp,n, + + ncomp,nind,trtype,rbdind,rbdtype + double precision delta,eps,epsnqmp,epsabs,epsrel,infrel,infabs, + + steabs,sterel,theta + +C ARRAY ARGUMENTS + integer ind(nind) + double precision d(n),g(n),l(n),lambda(m),r(n),rho(m),s(n), + + sprev(n),u(n),w(n),x(n),y(n) + +C This subroutine implements the Conjugate Gradients method for +C minimizing the quadratic approximation q(s) of f(x) at x, where +C +C q(s) = 1/2 s^T H s + g^T s, +C +C H = \nabla^2 f(x), +C +C g = \nabla f(x), +C +C subject to || s || <= delta and l <= x + s <= u. +C +C In the constraint ''|| s || <= delta'', the norm will be the +C Euclidian norm if the input parameter trtype is equal to 0, and +C it will be the Sup norm if trtype is equal to 1. +C +C The method returns an approximation s to the solution such that +C ||H s + g||_2 <= eps * ||g||_2; or converges to the boundary of +C ||s||_2 <= delta and l <= x + s <= u; or finds a point s and a +C direction d such that q(s + alpha d) = q(s) for any alpha, i.e., +C d^T H d = g^T d = 0. +C +C On Entry +C +C nind integer +C number of free variables (this is thee dimension in +C which this subroutine will work) +C +C ind integer ind(n) +C array which contains, in the first nind positions, the +C identifiers of the free variables +C +C n integer +C dimension of the full space +C +C x double precision x(n) +C point at which f function is being approximated by the +C quadratic model +C +C The first nind positions of x contains the free variables +C x_ind(1), x_ind(2), ..., x_ind(nind). +C +C m integer +C lambda double precision lambda(m) +C rho double precision rho(m) +C These three parameters are not used nor modified by +C GENCAN and they are passed as arguments to the user- +C defined subroutines evalal and evalnal to compute the +C objective function and its gradient, respectively. +C Clearly, in an Augmented Lagrangian context, if GENCAN is +C being used to solve the bound-constrainted subproblems, m +C would be the number of constraints, lambda the Lagrange +C multipliers approximation and rho the penalty parameters +C +C g double precision g(n) +C linear coefficient of the quadratic function +C +C This is \nabla f(x) and it also contains in the first +C nind positions the components g_ind(1), g_ind(2), ..., +C g_ind(nind). +C +C IMPORTANT: the linear algebra of this subroutine lies in +C a space of dimension nind. The value of the full +C dimension n, the non-free variables (which are at the end +C of array x) and its gradient components (which are at the +C and of array g) are, at this moment, being used to +C approximate the Hessian times vector products by +C incremental quotients. +C +C delta double precision +C trust region radius (||s||_2 <= delta) +C +C l double precision l(n) +C lower bounds on x + s. It components are ordered in the +C same way as x and g. +C +C u double precision u(n) +C upper bounds on x + s. It components are ordered in the +C same way as x, g and l. +C +C eps double precision +C tolerance for the stopping criterion ||H s + g||_2 < eps +C * ||g||_2 +C +C epsnqmp double precision +C See below +C +C maxitnqmp integer +C This and the previous one parameter are used for a +C stopping criterion of the conjugate gradient +C subalgorithm. If the progress in the quadratic model is +C less or equal than a fraction of the best progress +C ( epsnqmp * bestprog ) during maxitnqmp consecutive +C iterations then CG is stopped by not enough progress of +C the quadratic model. +C +C RECOMMENDED: epsnqmp = 1.0d-4, maxitnqmp = 5 +C +C maxit integer +C maximum number of iterations allowed +C +C nearlyq logical +C if function f is (nearly) quadratic, use the option +C nearlyq = TRUE. Otherwise, keep the default option. +C +C if, in an iteration of CG we find a direction d such that +C d^T H d <= 0 then we take the following decision: +C +C (i) if nearlyq = TRUE then take direction d and try to go +C to the boundary choosing the best point among the two +C point at the boundary and the current point. +C +C (ii) if nearlyq = FALSE then we stop at the current +C point. +C +C RECOMMENDED: nearlyq = FALSE +C +C gtype integer +C type of gradient calculation +C gtype = 0 means user suplied evalg subroutine, +C gtype = 1 means central difference approximation. +C +C RECOMMENDED: gtype = 0 +C +C (provided you have the evalg subroutine) +C +C htvtype integer +C type of Hessian times vector product calculation +C htvtype = 0 means user supplied evalhd subroutine, +C htvtype = 1 means incremental quotients approximation. +C +C RECOMMENDED: htvtype = 1 +C +C (you take some risk using this option but, unless you +C have a good evalhd subroutine, incremental quotients is a +C very cheap option) +C +C trtype integer +C type of trust-region radius +C trtype = 0 means 2-norm trust-region +C trtype = 1 means infinite-norm trust-region +C +C RECOMMENDED: trtype = 0 +C +C iprint integer +C Commands printing. Nothing is printed if iprint is +C smaller than 2. If iprint is greater than or equal to +C 2, GENCAN iterations information is printed. If iprint +C is greater than or equal to 3, line searches and +C Conjugate Gradients information is printed. +C +C RECOMMENDED: iprint = 2 +C +C CONSTRAINTS: allowed values are just 2 or 3. +C +C ncomp integer +C This constant is just for printing. In a detailed +C printing option, ncomp component of some vectors will be +C printed +C +C RECOMMENDED: ncomp = 5 +C +C CONSTRAINTS: ncomp >= 0 +C +C w double precision w(n) +C y double precision y(n) +C r double precision r(n) +C d double precision d(n) +C sprev double precision sprev(n) +C working vectors +C +C theta double precision +C constant for the angle condition, i.e., at iteration k we +C need a direction d_k such that <= - theta +C ||gk||_2 ||dk||_2, where gk is \nabla f(xk) +C +C RECOMMENDED: theta = 10^{-6} +C +C sterel double precision +C steabs double precision +C this constants mean a ``relative small number'' and ``an +C absolute small number'' for the increments in finite +C difference approximations of derivatives +C +C RECOMMENDED: epsrel = 10^{-7}, epsabs = 10^{-10} +C +C epsrel double precision +C epsabs double precision +C infrel double precision +C infabs double precision +C this constants mean a ``relative small number'', ``an +C absolute small number'', and ``infinite or a very big +C number''. Basically, a quantity A is considered +C negligible with respect to another quantity B if |A| < +C max ( epsrel * |B|, epsabs ) +C +C RECOMMENDED: epsrel = 10^{-10}, epsabs = 10^{-20}, +C infrel = 10^{+20}, infabs = 10^{+99} +C +C On Return +C +C s double precision s(n) +C final estimation of the solution +C +C iter integer +C number of Conjugate Gradient iterations performed +C +C inform integer +C termination parameter: +C +C 0 = convergence with ||H s + g||_2 <= eps * ||g||_2; +C +C 1 = convergence to the boundary of ||s||_2 <= delta; +C +C 2 = convergence to the boundary of l - x <= s <= u - x; +C +C 3 = stopping with s = sk such that <= -t heta +C ||gk||_2 ||sk||_2 and > - theta +C ||gk||_2 ||s_{k+1}||_2; +C +C 4 = not enough progress of the quadratic model during +C maxitnqmp iterations, i.e., during maxitnqmp +C iterations | q - qprev | <= max ( epsrel * | q |, +C epsabs ); +C +C 6 = very similar consecutive iterates, for two +C consecutive iterates x and y, for all i | x(i) - +C y(i) | <= max ( epsrel * | x(i) |, epsabs ); +C +C 7 = stopping with d such that d^T H d = 0 and g^T d = 0; +C +C 8 = too many iterations; +C +C < 0 = error in evalhd subroutine. + +C LOCAL SCALARS + character * 5 rbdtypea + logical samep + integer i,itnqmp,rbdnegaind,rbdnegatype,rbdposaind,rbdposatype + double precision aa,alpha,amax,amax1,amax1n,amaxn,amax2,amax2n, + + amax2nx,amax2x,bb,bestprog,beta,cc,currprog,dd,dnorm2,dtr, + + dts,dtw,gnorm2,gts,norm2s,q,qamax,qamaxn,qprev,rnorm2, + + rnorm2prev,snorm2,snorm2prev + +C ================================================================== +C Initialization +C ================================================================== + + gnorm2 = norm2s(nind,g) + + iter = 0 + itnqmp = 0 + qprev = infabs + bestprog = 0.0d0 + + do i = 1,nind + s(i) = 0.0d0 + r(i) = g(i) + end do + + q = 0.0d0 + gts = 0.0d0 + snorm2 = 0.0d0 + rnorm2 = gnorm2 + +C ================================================================== +C Print initial information +C ================================================================== + + if ( iprint .ge. 4 ) then + write(*, 980) maxit,eps + if ( trtype .eq. 0 ) then + write(*, 981) delta + else if ( trtype .eq. 1 ) then + write(*, 982) delta + else + write(*, 983) + end if + write(*, 984) iter,rnorm2,sqrt(snorm2),q + + write(10,980) maxit,eps + if ( trtype .eq. 0 ) then + write(10,981) delta + else if ( trtype .eq. 1 ) then + write(10,982) delta + else + write(10,983) + end if + write(10,984) iter,rnorm2,sqrt(snorm2),q + + end if + +C ================================================================== +C Main loop +C ================================================================== + + 100 continue + +C ================================================================== +C Test stopping criteria +C ================================================================== + +C if ||r||_2 = ||H s + g||_2 <= eps * ||g||_2 then stop + + if ( rnorm2 .le. 1.0d-16 .or. + + ( ( rnorm2 .le. eps ** 2 * gnorm2 .or. + + ( rnorm2 .le. 1.0d-10 .and. iter .ne. 0 ) ) + + .and. iter .ge. 4 ) ) then + + inform = 0 + + if ( iprint .ge. 4 ) then + write(*, 990) inform + write(10,990) inform + end if + + go to 500 + + end if + +C if the maximum number of iterations was achieved then stop + + if ( iter .ge. max(4, maxit) ) then + + inform = 8 + + if ( iprint .ge. 4 ) then + write(*, 998) inform + write(10,998) inform + end if + + go to 500 + + end if + +C ================================================================== +C Compute direction +C ================================================================== + + if ( iter .eq. 0 ) then + + do i = 1,nind + d(i) = - r(i) + end do + + dnorm2 = rnorm2 + dtr = - rnorm2 + + else + + beta = rnorm2 / rnorm2prev + + do i = 1,nind + d(i) = - r(i) + beta * d(i) + end do + + dnorm2 = rnorm2 - 2.0d0 * beta * ( dtr + alpha * dtw ) + + + beta ** 2 * dnorm2 + dtr = - rnorm2 + beta * ( dtr + alpha * dtw ) + + end if + +C Force d to be a descent direction of q(s), i.e., +C <\nabla q(s), d> = = \le 0. + + if ( dtr .gt. 0.0d0 ) then + + do i = 1,nind + d(i) = - d(i) + end do + dtr = - dtr + + end if + +C ================================================================== +C Compute d^T H d +C ================================================================== + +C w = A d + + if ( htvtype .eq. 0 ) then + call calchd(nind,ind,x,d,g,n,x,m,lambda,rho,w,y,sterel,steabs, + + inform) + + else if ( htvtype .eq. 1 ) then + call calchddiff(nind,ind,x,d,g,n,x,m,lambda,rho,gtype,w,y, + + sterel,steabs,inform) + end if + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 4 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + end if + +C Compute d^T w and ||w||^2 + + dtw = 0.0d0 + do i = 1,nind + dtw = dtw + d(i) * w(i) + end do + +C ================================================================== +C Compute maximum step +C ================================================================== + +C amax1 > 0 and amax1n < 0 are the values of alpha such that +C ||s + alpha * d||_2 or ||s + alpha * d||_\infty = delta + + dts = 0.0d0 + do i = 1,nind + dts = dts + d(i) * s(i) + end do + +C Euclidian-norm trust radius + + if ( trtype .eq. 0 ) then + + aa = dnorm2 + bb = 2.0d0 * dts + cc = snorm2 - delta ** 2 + dd = sqrt( bb ** 2 - 4.0d0 * aa * cc ) + + amax1 = ( - bb + dd ) / ( 2.0d0 * aa ) + amax1n = ( - bb - dd ) / ( 2.0d0 * aa ) + +C Sup-norm trust radius + + else if ( trtype .eq. 1 ) then + + amax1 = infabs + amax1n = -infabs + + do i = 1,nind + if ( d(i) .gt. 0.0d0 ) then + amax1 = min( amax1, ( delta - s(i) ) / d(i) ) + amax1n = max( amax1n, ( - delta - s(i) ) / d(i) ) + else if ( d(i) .lt. 0.0d0 ) then + amax1 = min( amax1, ( - delta - s(i) ) / d(i) ) + amax1n = max( amax1n, ( delta - s(i) ) / d(i) ) + end if + end do + + end if + +C amax2 > 0 and amax2n < 0 are the maximum and the minimum values of +C alpha such that l - x <= s + alpha * d <= u - x, respectively + + amax2 = infabs + amax2n = - infabs + + do i = 1,nind + if ( d(i) .gt. 0.0d0 ) then +C if (u(i).lt.infrel) then + amax2x = ( u(i) - x(i) - s(i) ) / d(i) + if ( amax2x .lt. amax2 ) then + amax2 = amax2x + rbdposaind = i + rbdposatype = 2 + end if +C end if +C if (l(i).gt.-infrel) then + amax2nx = ( l(i) - x(i) - s(i) ) / d(i) + if ( amax2nx .gt. amax2n ) then + amax2n = amax2nx + rbdnegaind = i + rbdnegatype = 1 + end if +C end if + else if ( d(i) .lt. 0.0d0 ) then +C if (l(i).gt.-infrel) then + amax2x = ( l(i) - x(i) - s(i) ) / d(i) + if ( amax2x .lt. amax2 ) then + amax2 = amax2x + rbdposaind = i + rbdposatype = 1 + end if +C end if +C if (u(i).lt.infrel) then + amax2nx = ( u(i) - x(i) - s(i) ) / d(i) + if ( amax2nx .gt. amax2n ) then + amax2n = amax2nx + rbdnegaind = i + rbdnegatype = 2 + end if +C end if + end if + end do + +C Compute amax as the minimum among amax1 and amax2, and amaxn as +C the minimum among amax1n and amax2n. Moreover change amaxn by +C - amaxn to have amax and amaxn as maximum steps along d direction +C (and not -d in the case of amaxn) + + amax = min( amax1 , amax2 ) + amaxn = max( amax1n, amax2n ) + +C ================================================================== +C Compute the step (and the quadratic functional value at the new +C point) +C ================================================================== + + qprev = q + +C If d^T H d > 0 then take the conjugate gradients step + + if ( dtw .gt. 0.0d0 ) then + + alpha = min( amax, rnorm2 / dtw ) + + q = q + 0.5d0 * alpha ** 2 * dtw + alpha * dtr + +C If d^T H d <= 0 and function f is nearly quadratic then take the +C point with the minimum functional value (q) among the current one +C and the ones which are at the boundary, i.e., the best one between +C q(s), q(s + amax*d) and q(s + amaxn*d). + + else + + qamax = q + 0.5d0 * amax ** 2 * dtw + amax * dtr + +C If we are at iteration zero then take the maximum positive +C step in the minus gradient direction + + if ( iter .eq. 0 ) then + + alpha = amax + q = qamax + +C If we are not in the first iteration then if function f is +C nearly quadratic and q(s + amax * d) or q(s + amaxn * d) is +C smaller than q(s), go to the best point in the boundary + + else + + qamaxn = q + 0.5d0 * amaxn ** 2 * dtw + amaxn * dtr + + if ( nearlyq .and. + + ( qamax .lt. q .or. qamaxn .lt. q ) ) then + + if ( qamax .lt. qamaxn ) then + alpha = amax + q = qamax + else + alpha = amaxn + q = qamaxn + end if + +C Else, stop at the current point + + else + + inform = 7 + + if ( iprint .ge. 4 ) then + write(*, 997) inform + write(10,997) inform + end if + + go to 500 + + end if + + end if + end if + +C ================================================================== +C Compute new s +C ================================================================== + + do i = 1,nind + sprev(i) = s(i) + s(i) = s(i) + alpha * d(i) + end do + + snorm2prev = snorm2 + snorm2 = snorm2 + alpha ** 2 * dnorm2 + 2.0d0 * alpha * dts + +C ================================================================== +C Compute the residual r = H s + g +C ================================================================== + + rnorm2prev = rnorm2 + + do i = 1,nind + r(i) = r(i) + alpha * w(i) + end do + + rnorm2 = norm2s(nind,r) + +C ================================================================== +C Increment number of iterations +C ================================================================== + + iter = iter + 1 + +C ================================================================== +C Print information of this iteration +C ================================================================== + + if ( iprint .ge. 4 ) then + write(*, 984) iter,sqrt(rnorm2),sqrt(snorm2),q + write(10,984) iter,sqrt(rnorm2),sqrt(snorm2),q + end if + +C ================================================================== +C Test other stopping criteria +C ================================================================== + +C Test angle condition + + gts = 0.0d0 + do i = 1,nind + gts = gts + g(i) * s(i) + end do + + if ( gts .gt. 0.0d0 .or. + + gts ** 2 .lt. theta ** 2 * gnorm2 * snorm2 ) then + + do i = 1,nind + s(i) = sprev(i) + end do + + snorm2 = snorm2prev + + q = qprev + + inform = 3 + + if ( iprint .ge. 4 ) then + write(*, 993) inform + write(10,993) inform + end if + + go to 500 + + end if + +C If we are in the boundary of the box also stop + + if ( alpha .eq. amax2 .or. alpha .eq. amax2n ) then + + if ( alpha .eq. amax2 ) then + rbdind = rbdposaind + rbdtype = rbdposatype + else ! if (alpha.eq.amax2n) then + rbdind = rbdnegaind + rbdtype = rbdnegatype + end if + + if ( rbdtype .eq. 1 ) then + rbdtypea = 'lower' + else ! if (rbdtype.eq.2) then + rbdtypea = 'upper' + end if + + inform = 2 + + if ( iprint .ge. 4 ) then + write(*, 992) inform,ind(rbdind),rbdtypea + write(10,992) inform,ind(rbdind),rbdtypea + end if + + go to 500 + + end if + +C If we are in the boundary of the trust region then stop + + if ( alpha .eq. amax1 .or. alpha .eq. amax1n ) then + + inform = 1 + + if ( iprint .ge. 4 ) then + write(*, 991) inform + write(10,991) inform + end if + + go to 500 + + end if + +C If two consecutive iterates are much close then stop + + samep = .true. + do i = 1,nind + if ( abs( alpha * d(i) ) .gt. + + max( epsrel * abs( s(i) ), epsabs ) ) then + samep = .false. + end if + end do + + if ( samep ) then + + inform = 6 + + if ( iprint .ge. 4 ) then + write(*, 996) inform + write(10,996) inform + end if + + go to 500 + + end if + +C Test whether we performed many iterations without good progress of +C the quadratic model + +C if (abs( q - qprev ) .le. max( epsrel * abs( qprev ), epsabs ) ) +C +then + +C itnqmp = itnqmp + 1 + +C if ( itnqmp .ge. maxitnqmp ) then + +C inform = 4 + +C if ( iprint .ge. 4 ) then +C write(*,994) inform,itnqmp +C write(10,994) inform,itnqmp +C end if + +C go to 500 + +C endif + +C else +C itnqmp= 0 +C endif + +C Test whether we performed many iterations without good progress of +C the quadratic model + + currprog = qprev - q + bestprog = max( currprog, bestprog ) + + if ( currprog .le. epsnqmp * bestprog ) then + + itnqmp = itnqmp + 1 + + if ( itnqmp .ge. maxitnqmp ) then + inform = 4 + + if ( iprint .ge. 4 ) then + write(*, 994) inform,itnqmp,epsnqmp,bestprog + write(10,994) inform,itnqmp,epsnqmp,bestprog + end if + + go to 500 + endif + + else + itnqmp = 0 + endif + +C ================================================================== +C Iterate +C ================================================================== + + go to 100 + +C ================================================================== +C End of main loop +C ================================================================== + +C ================================================================== +C Return +C ================================================================== + + 500 continue + +C Print final information + + if ( iprint .ge. 4 ) then + write(*, 985) min0(nind,ncomp),(s(i),i=1,min0(nind,ncomp)) + write(10,985) min0(nind,ncomp),(s(i),i=1,min0(nind,ncomp)) + end if + + return + +C Non-executable statements + + 980 format(/,6x,'Conjugate gradients (maxit= ',I7,' acc= ',1PD11.4, + *')') + 981 format(6x,'Using Euclidian trust region (delta= ',1PD11.4, + *')') + 982 format(6x,'Using sup-norm trust region (delta= ',1PD11.4,')') + 983 format(6x,'Unknown trust-region type') + 984 format(6x,'CG iter= ',I5,' rnorm: ',1PD11.4,' snorm= ',1PD11.4, + *' q= ',1PD11.4) + 985 format(/,6x,'Truncated Newton direction (first ',I6, + *' components): ',/,1(6x,6(1PD11.4,1x))) + 990 format(6x,'Flag of CG = ',I3,' (Convergence with small residual)') + 991 format(6x,'Flag of CG = ',I3, + *' (Convergence to the trust region boundary)') + 992 format(6x,'Flag of CG = ',I3, + *' (Convergence to the boundary of the box constraints,',/,6x, + *'taking step >= 1, variable ',I6,' will reaches its ',A5, + *' bound)') + 993 format(6x,'Flag of CG = ',I3, + *' (The next CG iterate will not satisfy the angle condition)') + 994 format(6x,'Flag of CG = ',I3, + *' (Not enough progress in the quadratic model. This means',/,6x, + *'that the progress of the last ',I7,' iterations was smaller ', + *'than ',/,6x,1PD11.4,' times the best progress (',1PD11.4,')') + 996 format(6x,'Flag of CG = ',I3, + *' (Very near consecutive iterates)') + 997 format(6x,'Flag of CG= ',I3, + *' (d such that d^T H d = 0 and g^T d = 0 was found)') + 998 format(6x,'Flag of CG = ',I3,' (Too many GC iterations)') + 1000 format(6x,'Flag of CG = ',I3,' Fatal Error') + + end + +C ***************************************************************** +C ***************************************************************** + subroutine tnls(nind,ind,n,x,m,lambda,rho,l,u,f,g,d,amax,rbdtype, + +rbdind,nint,next,mininterp,maxextrap,fmin,maxfc,gtype,iprint,fcnt, + +gcnt,intcnt,exgcnt,exbcnt,inform,xplus,xtmp,xbext,gamma,beta, + +sigma1,sigma2,sterel,steabs,epsrel,epsabs,infrel,infabs) + + implicit none + +C SCALAR ARGUMENTS + integer exbcnt,exgcnt,fcnt,gcnt,gtype,inform,intcnt,iprint,m, + + maxextrap,maxfc,mininterp,n,nind,rbdind,rbdtype + double precision amax,beta,epsabs,epsrel,f,fmin,gamma,infabs, + + infrel,next,nint,sigma1,sigma2,steabs,sterel + +C ARRAY ARGUMENTS + integer ind(nind) + double precision d(n),g(n),l(n),lambda(m),rho(m),u(n),x(n), + + xbext(n),xplus(n),xtmp(n) + +C This subroutine implements the line search used in the Truncated +C Newton direction. +C +C On Entry +C +C nind integer +C number of free variables (this is thee dimension in +C which this subroutine will work) +C +C ind integer ind(n) +C array which contains, in the first nind positions, the +C identifiers of the free variables +C +C n integer +C dimension of the full space +C +C x double precision x(n) +C current point +C +C The first nind positions of x contains the free variables +C x_ind(1), x_ind(2), ..., x_ind(nind). +C +C m integer +C lambda double precision lambda(m) +C rho double precision rho(m) +C These three parameters are not used nor modified by +C GENCAN and they are passed as arguments to the user- +C defined subroutines evalal and evalnal to compute the +C objective function and its gradient, respectively. +C Clearly, in an Augmented Lagrangian context, if GENCAN is +C being used to solve the bound-constrainted subproblems, m +C would be the number of constraints, lambda the Lagrange +C multipliers approximation and rho the penalty parameters +C +C l double precision l(nind) +C lower bounds on x. It components are ordered in the +C same way as x and g. +C +C u double precision u(nind) +C upper bounds on x. It components are ordered in the +C same way as x, g and l. +C +C f double precision +C functional value at x +C +C g double precision g(n) +C gradient vector at x +C +C It also contains in the first nind positions the +C components g_ind(1), g_ind(2), ..., g_ind(nind). +C +C IMPORTANT: the linear algebra of this subroutine lies in +C a space of dimension nind. The value of the full +C dimension n, the non-free variables (which are at the end +C of array x) and its gradient components (which are at the +C end of array g) are also used and updated any time the +C gradient is being computed. +C +C d double precision d(nind) +C descent direction +C +C amax double precision +C +C rbdtype integer +C +C rbdind integer +C +C nint double precision +C constant for the interpolation. See the description of +C sigma1 and sigma2 above. Sometimes we take as a new +C trial step the previous one divided by nint +C +C RECOMMENDED: nint = 2.0 +C +C next double precision +C constant for the extrapolation +C when extrapolating we try alpha_new = alpha * next +C +C RECOMMENDED: next = 2.0 +C +C mininterp integer +C constant for testing if, after having made at least +C mininterp interpolations, the steplength is so small. +C In that case failure of the line search is declared (may +C be the direction is not a descent direction due to an +C error in the gradient calculations) +C +C RECOMMENDED: mininterp = 4 +C +C maxextrap integer +C constant to limit the number of extrapolations +C +C RECOMMENDED: maxextrap = 1000 (a big number) +C +C fmin double precision +C functional value for the stopping criteria f <= fmin +C +C maxfc integer +C maximum number of functional evaluations +C +C gtype integer +C type of gradient calculation +C gtype = 0 means user suplied evalg subroutine, +C gtype = 1 means central difference approximation. +C +C RECOMMENDED: gtype = 0 +C +C (provided you have the evalg subroutine) +C +C iprint integer +C Commands printing. Nothing is printed if iprint is +C smaller than 2. If iprint is greater than or equal to +C 2, GENCAN iterations information is printed. If iprint +C is greater than or equal to 3, line searches and +C Conjugate Gradients information is printed. +C +C RECOMMENDED: iprint = 2 +C +C CONSTRAINTS: allowed values are just 2 or 3. +C +C xplus double precision xplus(nind) +C xtmp double precision xtmp(nind) +C xbext double precision xbext(nind) +C working vectors +C +C gamma double precision +C constant for the Armijo criterion +C f(x + alpha d) <= f(x) + gamma * alpha * <\nabla f(x),d> +C +C RECOMMENDED: gamma = 10^{-4} +C +C beta double precision +C constant for the beta condition < beta +C * . If (xk + dk) satisfies the Armijo condition +C but does not satisfy the beta condition then the point is +C accepted, but if it satisfied the Armijo condition and +C also satisfies the beta condition then we know that there +C is the possibility for a successful extrapolation +C +C RECOMMENDED: beta = 0.5 +C +C sigma1 double precision +C sigma2 double precision +C constant for the safeguarded interpolation +C if alpha_new \notin [sigma1, sigma*alpha] then we take +C alpha_new = alpha / nint +C +C RECOMMENDED: sigma1 = 0.1 and sigma2 = 0.9 +C +C sterel double precision +C steabs double precision +C this constants mean a ``relative small number'' and ``an +C absolute small number'' for the increments in finite +C difference approximations of derivatives +C +C RECOMMENDED: epsrel = 10^{-7}, epsabs = 10^{-10} +C +C epsrel double precision +C epsabs double precision +C infrel double precision +C infabs double precision +C this constants mean a ``relative small number'', ``an +C absolute small number'', and ``infinite or a very big +C number''. Basically, a quantity A is considered +C negligible with respect to another quantity B if +C |A| < max ( epsrel * |B|, epsabs ) +C +C RECOMMENDED: epsrel = 10^{-10}, epsabs = 10^{-20}, +C infrel = 10^{+20}, infabs = 10^{+99} +C +C On Return +C +C x double precision x(n) +C new current point +C +C f double precision +C functional value at x +C +C g double precision g(n) +C gradient vector at x +C +C fcnt integer +C number of functional evaluations used in this line search +C +C gcnt integer +C number of gradient evaluations used in this line search +C +C intcnt integer +C number of interpolations +C +C exgcnt integer +C number of good extrapolations +C +C exbcnt integer +C number of bad extrapolations +C +C inform integer +C This output parameter tells what happened in this +C subroutine, according to the following conventions: +C +C 0 = convergence with an Armijo-like criterion +C (f(xnew) <= f(x) + 1.0d-4 * alpha * ); +C +C 4 = the algorithm stopped because the functional value +C is very small (f <= fmin); +C +C 6 = so small step in the line search. After having made +C at least mininterp interpolations, the steplength +C becames small. ``small steplength'' means that we are +C at point x with direction d and step alpha, and, for +C all i, +C +C |alpha * d(i)| .le. max ( epsrel * |x(i)|, epsabs ). +C +C In that case failure of the line search is declared +C (may be the direction is not a descent direction +C due to an error in the gradient calculations). Use +C mininterp > maxfc for inhibit this criterion; +C +C 8 = it was achieved the maximum allowed number of +C function evaluations (maxfc); +C +C < 0 = error in evalf or evalg subroutines. + +C LOCAL SCALARS + logical samep + integer extrap,i,interp + double precision alpha,atmp,fbext,fplus,ftmp,gptd,gtd + +C ================================================================== +C Initialization +C ================================================================== + +C ================================================================== +C Compute directional derivative +C ================================================================== + + gtd = 0.0d0 + do i = 1,nind + gtd = gtd + g(i) * d(i) + end do + +C ================================================================== +C Compute first trial +C ================================================================== + + alpha = min( 1.0d0, amax ) + + do i = 1,nind + xplus(i) = x(i) + alpha * d(i) + end do + + if ( alpha .eq. amax ) then + if ( rbdtype .eq. 1 ) then + xplus(rbdind) = l(rbdind) + else ! if (rbdtype.eq.2) then + xplus(rbdind) = u(rbdind) + end if + end if + + call calcf(nind,ind,xplus,n,x,m,lambda,rho,fplus,inform) + fcnt = fcnt + 1 + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 4 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + + end if + +C Print initial information + + if ( iprint .ge. 4 ) then + write(*, 980) amax + write(*, 999) alpha,fplus,fcnt + + write(10,980) amax + write(10,999) alpha,fplus,fcnt + end if + +C ================================================================== +C Test Armijo and beta-condition and decide for accepting the trial +C point, interpolate or extrapolate. +C ================================================================== + + if ( amax .gt. 1.0d0 ) then + +C x + d belongs to the interior of the feasible set + if ( iprint .ge. 4 ) then + write(*, *) ' x+d belongs to int of the feasible set' + write(10,*) ' x+d belongs to int of the feasible set' + end if + +C Verify Armijo + + if ( fplus .le. f + gamma * alpha * gtd ) then + +C Armijo condition holds + if ( iprint .ge. 4 ) then + write(*, *) ' Armijo condition holds' + write(10,*) ' Armijo condition holds' + end if + + if ( gtype .eq. 0 ) then + call calcg(nind,ind,xplus,n,x,m,lambda,rho,g,inform) + else if ( gtype .eq. 1 ) then + call calcgdiff(nind,ind,xplus,n,x,m,lambda,rho,g, + + sterel,steabs,inform) + end if + gcnt = gcnt + 1 + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 4 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + + end if + + gptd = 0.0d0 + do i = 1,nind + gptd = gptd + g(i) * d(i) + end do + +C Verify directional derivative (beta condition) + + if ( gptd .lt. beta * gtd ) then + +C Extrapolate + if ( iprint .ge. 4 ) then + write(*, *)' The beta-condition does not hold' + write(*, *)' We will extrapolate' + write(10,*)' The beta-condition does not hold' + write(10,*)' We will extrapolate' + end if + +C f and x before extrapolation + fbext = fplus + + do i = 1,nind + xbext(i) = xplus(i) + end do + + go to 100 + + else + +C Step = 1 was ok, finish the line search + if ( iprint .ge. 4 ) then + write(*, *) ' The beta condition is also true' + write(*, *) ' Line search is over' + write(10,*) ' The beta condition is also true' + write(10,*) ' Line search is over' + end if + + f = fplus + + do i = 1,nind + x(i) = xplus(i) + end do + + inform = 0 + + if ( iprint .ge. 4 ) then + write(*, 990) inform + write(10,990) inform + end if + + go to 500 + + end if + + else + +C Interpolate + if ( iprint .ge. 4 ) then + write(*, *) ' Armijo does not hold' + write(*, *) ' We will interpolate' + write(10,*) ' Armijo does not hold' + write(10,*) ' We will interpolate' + end if + + go to 200 + + end if + + else + +C x + d does not belong to the feasible set (amax <= 1) + if ( iprint .ge. 4 ) then + write(*, *) ' x+d does not belong to box-interior' + write(10,*) ' x+d does not belong to box-interior' + end if + + if ( fplus .lt. f ) then + +C Extrapolate + if ( iprint .ge. 4 ) then + write(*, *) ' f(x+d) < f(x)' + write(*, *) ' We will extrapolate' + write(10,*) ' f(x+d) < f(x)' + write(10,*) ' We will extrapolate' + end if + +C f and x before extrapolation + fbext = fplus + + do i = 1,nind + xbext(i) = xplus(i) + end do + + go to 100 + + else + +C Interpolate + if ( iprint .ge. 4 ) then + write(*, *) ' f(x+d) >= f(x)' + write(*, *) ' We will interpolate' + write(10,*) ' f(x+d) >= f(x)' + write(10,*) ' We will interpolate' + end if + + go to 200 + + end if + + end if + + +C ================================================================== +C Extrapolation +C ================================================================== + + 100 continue + + extrap = 0 + +C Test f going to -inf + + 120 if ( fplus .le. fmin ) then + +C Finish the extrapolation with the current point + + f = fplus + + do i = 1,nind + x(i) = xplus(i) + end do + + if ( extrap .ne. 0 .or. amax .le. 1.0d0 ) then + + if ( gtype .eq. 0 ) then + call calcg(nind,ind,x,n,x,m,lambda,rho,g,inform) + else if ( gtype .eq. 1 ) then + call calcgdiff(nind,ind,x,n,x,m,lambda,rho,g,sterel, + + steabs,inform) + end if + gcnt = gcnt + 1 + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 4 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + + end if + + if ( f .lt. fbext ) then + exgcnt = exgcnt + 1 + else + exbcnt = exbcnt + 1 + end if + + end if + + inform = 4 + + if ( iprint .ge.3 ) then + write(*, 994) inform + write(10,994) inform + end if + + go to 500 + + end if + +C Test maximum number of functional evaluations + + if ( fcnt .ge. maxfc ) then + +C Finish the extrapolation with the current point + + f = fplus + + do i = 1,nind + x(i) = xplus(i) + end do + +C If extrap=0 and amax>1 the gradient was computed for testing +C the beta condition and it is not necessary to compute it again + if ( extrap .ne. 0 .or. amax .le. 1.0d0 ) then + + if ( gtype .eq. 0 ) then + call calcg(nind,ind,x,n,x,m,lambda,rho,g,inform) + else if ( gtype .eq. 1 ) then + call calcgdiff(nind,ind,x,n,x,m,lambda,rho,g,sterel, + + steabs,inform) + end if + gcnt = gcnt + 1 + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 4 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + + end if + + if ( f .lt. fbext ) then + exgcnt = exgcnt + 1 + else + exbcnt = exbcnt + 1 + end if + + end if + + inform = 8 + + if ( iprint .ge. 4 ) then + write(*, 998) inform + write(10,998) inform + end if + + go to 500 + + end if + +C Test if the maximum number of extrapolations was exceeded + + if ( extrap .ge. maxextrap ) then + +C Finish the extrapolation with the current point + + f = fplus + + do i = 1,nind + x(i) = xplus(i) + end do + +C If extrap=0 and amax>1 the gradient was computed for testing +C the beta condition and it is not necessary to compute it again + if ( extrap .ne. 0 .or. amax .le. 1.0d0 ) then + + if ( gtype .eq. 0 ) then + call calcg(nind,ind,x,n,x,m,lambda,rho,g,inform) + else if ( gtype .eq. 1 ) then + call calcgdiff(nind,ind,x,n,x,m,lambda,rho,g,sterel, + + steabs,inform) + end if + gcnt = gcnt + 1 + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 4 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + + end if + + if ( f .lt. fbext ) then + exgcnt = exgcnt + 1 + else + exbcnt = exbcnt + 1 + end if + + end if + + inform = 7 + + if ( iprint .ge. 4 ) then + write(*, 997) inform + write(10,997) inform + end if + + go to 500 + + end if + +C Chose new step + + if ( alpha .lt. amax .and. next * alpha .gt. amax ) then + atmp = amax + else + atmp = next * alpha + end if + +C Compute new trial point + + do i = 1,nind + xtmp(i) = x(i) + atmp * d(i) + end do + + if ( atmp .eq. amax ) then + if ( rbdtype .eq. 1 ) then + xtmp(rbdind) = l(rbdind) + else ! if ( rbdtype .eq. 2 ) then + xtmp(rbdind) = u(rbdind) + end if + end if + +C Project + + if ( atmp .gt. amax ) then + do i = 1,nind + xtmp(i) = max( l(i), min( xtmp(i), u(i) ) ) + end do + end if + +C Test if this is not the same point as the previous one. +C This test is performed only when alpha > amax. + + if( alpha .gt. amax ) then + + samep = .true. + do i = 1,nind + if ( abs( xtmp(i) - xplus(i) ) .gt. + + max( epsrel * abs( xplus(i) ), epsabs ) ) then + samep = .false. + end if + end do + + if ( samep ) then + +C Finish the extrapolation with the current point + + f = fplus + + do i = 1,nind + x(i) = xplus(i) + end do + +C If extrap=0 and amax>1 the gradient was computed for +C testing the beta condition and it is not necessary to +C compute it again + if ( extrap .ne. 0 .or. amax .le. 1.0d0 ) then + + if ( gtype .eq. 0 ) then + call calcg(nind,ind,x,n,x,m,lambda,rho,g,inform) + else if ( gtype .eq. 1 ) then + call calcgdiff(nind,ind,x,n,x,m,lambda,rho,g, + + sterel,steabs,inform) + end if + gcnt = gcnt + 1 + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 4 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + + end if + + if ( f .lt. fbext ) then + exgcnt = exgcnt + 1 + else + exbcnt = exbcnt + 1 + end if + + end if + + inform = 0 + + if ( iprint .ge. 4 ) then + write(*, 990) inform + write(10,990) inform + end if + + go to 500 + + end if + + end if + +C Evaluate function + + call calcf(nind,ind,xtmp,n,x,m,lambda,rho,ftmp,inform) + fcnt = fcnt + 1 + + if ( inform .lt. 0 ) then + +C if ( iprint .ge. 4 ) then +C write(*, 1000) inform +C write(10,1000) inform +C end if + +C return + +C If the objective function is not well defined in an +C extrapolated point, we discard all the extrapolated points +C and return to a safe region (where the point before +C starting the extrapolations is) + + f = fbext + + do i = 1,nind + x(i) = xbext(i) + end do + +C If extrap=0 and amax>1 the gradient was computed for testing +C the beta condition and it is not necessary to compute it again + if ( extrap .ne. 0 .or. amax .le. 1.0d0 ) then + + if ( gtype .eq. 0 ) then + call calcg(nind,ind,x,n,x,m,lambda,rho,g,inform) + else if ( gtype .eq. 1 ) then + call calcgdiff(nind,ind,x,n,x,m,lambda,rho,g,sterel, + + steabs,inform) + end if + gcnt = gcnt + 1 + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 4 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + + end if + + exbcnt = exbcnt + 1 + + end if + + inform = 0 + + if ( iprint .ge. 4 ) then + write(*, 1010) inform + write(10,1010) inform + end if + + go to 500 + + end if + +C Print information of this iteration + + if ( iprint .ge. 4 ) then + write(*, 999) atmp,ftmp,fcnt + write(10,999) atmp,ftmp,fcnt + end if + +C If the functional value decreases then set the current point and +C continue the extrapolation + + if ( ftmp .lt. fplus ) then + + alpha = atmp + + fplus = ftmp + + do i = 1,nind + xplus(i) = xtmp(i) + end do + + extrap = extrap + 1 + + go to 120 + +C If the functional value does not decrease then discard the last +C trial and finish the extrapolation with the previous point + + else + + f = fplus + + do i = 1,nind + x(i) = xplus(i) + end do + +C If extrap=0 and amax>1 the gradient was computed for testing +C the beta condition and it is not necessary to compute it again + if ( extrap .ne. 0 .or. amax .le. 1.0d0 ) then + + if ( gtype .eq. 0 ) then + call calcg(nind,ind,x,n,x,m,lambda,rho,g,inform) + else if ( gtype .eq. 1 ) then + call calcgdiff(nind,ind,x,n,x,m,lambda,rho,g,sterel, + + steabs,inform) + end if + gcnt = gcnt + 1 + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 4 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + + end if + + if ( f .lt. fbext ) then + exgcnt = exgcnt + 1 + else + exbcnt = exbcnt + 1 + end if + + end if + + inform = 0 + + if ( iprint .ge.3 ) then + write(*, 990) inform + write(10,990) inform + end if + + go to 500 + + end if +C ================================================================== +C End of extrapolation +C ================================================================== + +C ================================================================== +C Interpolation +C ================================================================== + + 200 continue + + intcnt = intcnt + 1 + + interp = 0 + + 210 continue + +C Test f going to -inf + + if ( fplus .le. fmin ) then + +C Finish the interpolation with the current point + + f = fplus + + do i = 1,nind + x(i) = xplus(i) + end do + + if ( gtype .eq. 0 ) then + call calcg(nind,ind,x,n,x,m,lambda,rho,g,inform) + else if ( gtype .eq. 1 ) then + call calcgdiff(nind,ind,x,n,x,m,lambda,rho,g,sterel, + + steabs,inform) + end if + gcnt = gcnt + 1 + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 4 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + + end if + + inform = 4 + + if ( iprint .ge. 4 ) then + write(*, 994) inform + write(10,994) inform + end if + + go to 500 + + end if + +C Test maximum number of functional evaluations + + if ( fcnt .ge. maxfc ) then + +C As this is an abrupt termination then the current point of the +C interpolation may be worst than the initial one + +C If the current point is better than the initial one then +C finish the interpolation with the current point else discard +C all we did inside this line search and finish with the initial +C point + + if ( fplus .lt. f ) then + + f = fplus + + do i = 1,nind + x(i) = xplus(i) + end do + + if ( gtype .eq. 0 ) then + call calcg(nind,ind,x,n,x,m,lambda,rho,g,inform) + else if ( gtype .eq. 1 ) then + call calcgdiff(nind,ind,x,n,x,m,lambda,rho,g,sterel, + + steabs,inform) + end if + gcnt = gcnt + 1 + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 4 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + + end if + + end if + + inform = 8 + + if ( iprint .ge. 4 ) then + write(*, 998) inform + write(10,998) inform + end if + + go to 500 + + end if + +C Test Armijo condition + + if ( fplus .le. f + gamma * alpha * gtd ) then + +C Finish the line search + + f = fplus + + do i = 1,nind + x(i) = xplus(i) + end do + + if ( gtype .eq. 0 ) then + call calcg(nind,ind,x,n,x,m,lambda,rho,g,inform) + else if ( gtype .eq. 1 ) then + call calcgdiff(nind,ind,x,n,x,m,lambda,rho,g,sterel, + + steabs,inform) + end if + gcnt = gcnt + 1 + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 4 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + + end if + + inform = 0 + + if ( iprint .ge. 4 ) then + write(*, 990) inform + write(10,990) inform + end if + + go to 500 + + end if + +C Compute new step + + interp = interp + 1 + + if ( alpha .lt. sigma1 ) then + alpha = alpha / nint + + else + atmp = ( - gtd * alpha **2 ) / + + (2.0d0 * ( fplus - f - alpha * gtd ) ) + + if ( atmp .lt. sigma1 .or. atmp .gt. sigma2 * alpha ) then + alpha = alpha / nint + + else + alpha = atmp + end if + end if + +C Compute new trial point + + do i = 1,nind + xplus(i) = x(i) + alpha * d(i) + end do + + call calcf(nind,ind,xplus,n,x,m,lambda,rho,fplus,inform) + fcnt = fcnt + 1 + + if ( inform .lt. 0 ) then + + if ( iprint .ge. 4 ) then + write(*, 1000) inform + write(10,1000) inform + end if + + return + + end if + +C Print information of this iteration + + if ( iprint .ge. 4 ) then + write(*, 999) alpha,fplus,fcnt + write(10,999) alpha,fplus,fcnt + end if + +C Test whether at least mininterp interpolations were made and two +C consecutive iterates are much close + + samep = .true. + do i = 1,nind + if ( abs( alpha * d(i) ) .gt. + + max( epsrel * abs( x(i) ), epsabs ) ) then + samep = .false. + end if + end do + + if ( interp .ge. mininterp .and. samep ) then + +C As this is an abrupt termination then the current point of the +C interpolation may be worst than the initial one + +C If the current point is better than the initial one then +C finish the interpolation with the current point else discard +C all we did inside this line search and finish with the initial +C point + +C if ( fplus .lt. f ) then + +C f = fplus + +C do i = 1,nind +C x(i) = xplus(i) +C end do + +C if ( gtype .eq. 0 ) then +C call calcg(nind,ind,x,n,x,m,lambda,rho,g,inform) +C else if ( gtype .eq. 1 ) then +C call calcgdiff(nind,ind,x,n,x,m,lambda,rho,g, +c + sterel,steabs,inform) +C end if +C gcnt = gcnt + 1 + +C if ( inform .lt. 0 ) then + +C if ( iprint .ge. 4 ) then +C write(*, 1000) inform +C write(10,1000) inform +C end if + +C return + +C end if + +C end if + +C The previous lines were commented because, as it is been used, +C this subroutine must return with the initial point in case of +C finding a very small interpolation step. From that initial +C point, something different will be tried. + + inform = 6 + + if ( iprint .ge. 4 ) then + write(*, 996) inform + write(10,996) inform + end if + + go to 500 + + end if + +C Else, iterate + + go to 210 +C ================================================================== +C End of interpolation +C ================================================================== + + 500 continue + +C ================================================================== +C Return +C ================================================================== + + return + +C Non-executable statements + + 980 format(/,6X,'TN Line search (alphamax= ',1PD11.4,')') + 999 format(6X,'Alpha= ',1PD11.4,' F= ',1PD11.4,' FE= ',I5) + 990 format(6X,'Flag of TN Line search= ',I3, + + ' (Convergence with an Armijo-like criterion)') + 994 format(6X,'Flag of TN Line search= ',I3, + + ' (Small functional value, smaller than ',/, + + 6X,'parameter fmin)') + 996 format(6X,'Flag of TN Line search= ',I3, + + ' (Too small step in the interpolation)') + 997 format(6X,'Flag of TN Line search= ',I3, + + ' (Too many extrapolations)') + 998 format(6X,'Flag of TN Line search= ',I3, + + ' (Too many functional evaluations)') + 1000 format(6X,'Flag of TN Line search = ',I3,' Fatal Error') + 1010 format(6X,'Flag of TN Line search= ',I3, + + ' (Fatal Error in an extrapolated point)') + + end + +C ****************************************************************** +C ****************************************************************** + + subroutine calcf(nind,ind,x,n,xc,m,lambda,rho,f,inform) + + implicit none + +C SCALAR ARGUMENTS + integer nind,n,m,inform + double precision f + +C ARRAY ARGUMENTS + integer ind(nind) + double precision x(n),xc(n),lambda(m),rho(m) + +C This subroutines computes the objective function. +C +C It is called from the reduced space (dimension nind), expands the +C point x where the function will be evaluated and call the +C subroutine evalf to compute the objective function Finally, +C shrinks vector x to the reduced space. +C +C About subroutines named calc[something]. The subroutines whos +C names start with ``calc'' work in (are called from) the reduced +C space. Their tasks are (i) expand the arguments to the full space, +C (ii) call the corresponding ``eval'' subroutine (which works in +C the full space), and (iii) shrink the parameters again and also +C shrink a possible output of the ``eval'' subroutine. Subroutines +C of this type are: calcf, calcg, calchd, calcgdiff and calchddiff. +C The corresponding subroutines in the full space are the user +C defined subroutines evalf, evalg and evalhd. + +C LOCAL SCALARS + integer i + +C Complete x + + do i = nind + 1,n + x(i) = xc(i) + end do + +C Expand x to the full space + + call expand(nind,ind,n,x) + +C Compute f calling the user supplied subroutine evalf + + call evalal(n,x,m,lambda,rho,f,inform) + +C Shrink x to the reduced space + + call shrink(nind,ind,n,x) + + return + + end + +C ****************************************************************** +C ****************************************************************** + + subroutine calcg(nind,ind,x,n,xc,m,lambda,rho,g,inform) + + implicit none + +C SCALAR ARGUMENTS + integer nind,n,m,inform + +C ARRAY ARGUMENTS + integer ind(nind) + double precision x(n),xc(n),lambda(m),rho(m),g(n) + +C This subroutine computes the gradient vector g of the objective +C function. +C +C It is called from the reduced space (dimension nind), expands the +C point x where the gradient will be evaluated and calls the user +C supplied subroutine evalg to compute the gradient vector. Finally, +C shrinks vectors x and g to the reduced space. +C +C About subroutines named calc[something]. The subroutines whos +C names start with ``calc'' work in (are called from) the reduced +C space. Their tasks are (i) expand the arguments to the full space, +C (ii) call the corresponding ``eval'' subroutine (which works in +C the full space), and (iii) shrink the parameters again and also +C shrink a possible output of the ``eval'' subroutine. Subroutines +C of this type are: calcf, calcg, calchd, calcgdiff and calchddiff. +C The corresponding subroutines in the full space are the user +C defined subroutines evalf, evalg and evalhd. + +C LOCAL SCALARS + integer i + +C Complete x + + do i = nind + 1,n + x(i) = xc(i) + end do + +C Expand x to the full space + + call expand(nind,ind,n,x) + +C Compute the gradient vector calling the user supplied subroutine +C evalg + + call evalnal(n,x,m,lambda,rho,g,inform) + +C Shrink x and g to the reduced space + + call shrink(nind,ind,n,x) + call shrink(nind,ind,n,g) + + return + + end + +C ****************************************************************** +C ****************************************************************** + + subroutine calcgdiff(nind,ind,x,n,xc,m,lambda,rho,g,sterel,steabs, + +inform) + + implicit none + +C SCALAR ARGUMENTS + integer nind,n,m,inform + double precision sterel,steabs + +C ARRAY ARGUMENTS + integer ind(nind) + double precision x(n),xc(n),lambda(m),rho(m),g(n) + +C This subroutine approximates the gradient vector g of the +C objective function in the reduced space using central finite +C differences. +C +C It is called from the reduced space (dimension nind), expands the +C point x where the gradient will be estimated and calls evalf +C subroutine (to evaluate the objective function) 2 * nind times. +C Finally, shrinks vectors x and g to the reduced space. +C +C About subroutines named calc[something]. The subroutines whos +C names start with ``calc'' work in (are called from) the reduced +C space. Their tasks are (i) expand the arguments to the full space, +C (ii) call the corresponding ``eval'' subroutine (which works in +C the full space), and (iii) shrink the parameters again and also +C shrink a possible output of the ``eval'' subroutine. Subroutines +C of this type are: calcf, calcg, calchd, calcgdiff and calchddiff. +C The corresponding subroutines in the full space are the user +C defined subroutines evalf, evalg and evalhd. + +C LOCAL SCALARS + integer i,indi + double precision fminus,fplus,step,tmp + +C Complete x + + do i = nind + 1,n + x(i) = xc(i) + end do + +C Expand x to the full space + + call expand(nind,ind,n,x) + +C Approximate the gradient vector by central finite differences + + do i = 1,nind + indi = ind(i) + + tmp = x(indi) + step = max( steabs, sterel * abs( tmp ) ) + + x(indi) = tmp + step + call evalal(n,x,m,lambda,rho,fplus,inform) + if ( inform .lt. 0 ) then + return + end if + + x(indi) = tmp - step + call evalal(n,x,m,lambda,rho,fminus,inform) + if ( inform .lt. 0 ) then + return + end if + + g(indi) = ( fplus - fminus ) / ( 2.0d0 * step ) + x(indi) = tmp + end do + +C Shrink x and g to the reduced space + + call shrink(nind,ind,n,x) + call shrink(nind,ind,n,g) + + return + + end + + +C ****************************************************************** +C ****************************************************************** + + subroutine calchd(nind,ind,x,d,g,n,xc,m,lambda,rho,hd,xtmp,sterel, + +steabs,inform) + + implicit none + +C SCALAR ARGUMENTS + integer inform,m,n,nind + double precision steabs,sterel + +C ARRAY ARGUMENTS + integer ind(nind) + double precision d(n),g(n),hd(n),lambda(m),rho(m),x(n),xc(n), + + xtmp(n) + +C This subroutine computes the product Hessian times vector d. As it +C is called from the reduced space, it expands vectors x and d, +C calls the user supplied subroutine evalhd to compute the Hessian +C times vector d product, and shrinks vectors x, d and hd. +C +C About subroutines named calc[something]. The subroutines whos +C names start with ``calc'' work in (are called from) the reduced +C space. Their tasks are (i) expand the arguments to the full space, +C (ii) call the corresponding ``eval'' subroutine (which works in +C the full space), and (iii) shrink the parameters again and also +C shrink a possible output of the ``eval'' subroutine. Subroutines +C of this type are: calcf, calcg, calchd, calcgdiff and calchddiff. +C The corresponding subroutines in the full space are the user +C defined subroutines evalf, evalg and evalhd. + +C LOCAL SCALARS + integer i + +C Complete d with zeroes + + do i = nind + 1,n + d(i) = 0.0d0 + end do + +C Complete x + + do i = nind + 1,n + x(i) = xc(i) + end do + +C Expand x and d to the full space + + call expand(nind,ind,n,x) + call expand(nind,ind,n,d) + call expand(nind,ind,n,g) + +C Compute the Hessian times vector d product calling the user +C supplied subroutine evalhd + + call evalhd(n) + +C Shrink x, d and hd to the reduced space + + call shrink(nind,ind,n,x) + call shrink(nind,ind,n,d) + call shrink(nind,ind,n,g) + call shrink(nind,ind,n,hd) + + end + +C ****************************************************************** +C ****************************************************************** + + subroutine calchddiff(nind,ind,x,d,g,n,xc,m,lambda,rho,gtype,hd, + +xtmp,sterel,steabs,inform) + + implicit none + +C SCALAR ARGUMENTS + integer gtype,inform,m,n,nind + double precision steabs,sterel + +C ARRAY ARGUMENTS + integer ind(nind) + double precision d(n),g(n),hd(n),lambda(m),rho(m),x(n),xc(n), + + xtmp(n) + +C This subroutine computes the Hessian times vector d product by +C means of a ``directional finite difference''. The idea is that, at +C the current point x, the product H d is the limit of +C +C [ Gradient(x + t d) - Gradient(x) ] / t +C +C In this implementation we use +C +C t = max(steabs, sterel ||x||_\infty) / ||d||_\infty +C +C provided that d is not equal 0, of course. +C +C So, we evaluate the Gradient at the auxiliary point x + t d and +C use the quotient above to approximate H d. To compute the gradient +C vector at the auxiliary point it is used evalg or evalgdiff +C depending on gtype parameter. +C +C About subroutines named calc[something]. The subroutines whos +C names start with ``calc'' work in (are called from) the reduced +C space. Their tasks are (i) expand the arguments to the full space, +C (ii) call the corresponding ``eval'' subroutine (which works in +C the full space), and (iii) shrink the parameters again and also +C shrink a possible output of the ``eval'' subroutine. Subroutines +C of this type are: calcf, calcg, calchd, calcgdiff and calchddiff. +C The corresponding subroutines in the full space are the user +C defined subroutines evalf, evalg and evalhd. + +C On Entry +C +C n integer +C order of the x +C +C x double precision x(n) +C point for which Hessian(x) times d will be approximated +C +C d double precision d(n) +C vector for which the Hessian times vetor product will +C be approximated +C +C g double precision g(n) +C gradient at x +C +C xtmp double precision xtmp(n) +C working vector +C +C sterel double precision +C steabs double precision +C these constants mean a ``relative small number'' and +C ``an absolute small number'' +C +C On Return +C +C hd double precision hd(n) +C approximation of H d + +C LOCAL SCALARS + integer flag,i,indi + double precision dsupn,step,tmp,xsupn + + inform = 0 + +C Compute incremental quotients step + + xsupn = 0.0d0 + dsupn = 0.0d0 + do i = 1,nind + xsupn = max( xsupn, abs( x(i) ) ) + dsupn = max( dsupn, abs( d(i) ) ) + end do + +c Safeguard added by LM + if(dsupn.lt.1.d-20) dsupn = 1.d-20 + + step = max( sterel * xsupn, steabs ) / dsupn + +C Set the point at which the gradient will be evaluated + + do i = 1,nind + xtmp(i) = x(i) + step * d(i) + end do + +C Evaluate the gradient at xtmp = x + step * d + + if ( gtype .eq. 0 ) then + +C Complete xtmp + + do i = nind + 1,n + xtmp(i) = xc(i) + end do + +C Expand xtmp to the full space + + do i = nind,1,-1 + indi = ind(i) + if ( i .ne. indi ) then + tmp = xtmp(indi) + xtmp(indi) = xtmp(i) + xtmp(i) = tmp + end if + end do + +c Compute the gradient at xtmp = x + step * d + + call evalnal(n,xtmp,m,lambda,rho,hd,flag) + +C Shrink hd to the reduced space + + do i= 1, nind + indi= ind(i) + if (i.ne.indi) then + tmp = hd(indi) + hd(indi) = hd(i) + hd(i) = tmp + end if + end do + + else if ( gtype .eq. 1 ) then + + call calcgdiff(nind,ind,xtmp,n,xc,m,lambda,rho,hd,sterel, + + steabs,inform) + + end if + +C Compute incremental quotients + + do i = 1,nind + hd(i) = ( hd(i) - g(i) ) / step + end do + + return + + end + + +C ****************************************************************** +C ****************************************************************** + + subroutine shrink(nind,ind,n,v) + + implicit none + +C SCALAR ARGUMENTS + integer n,nind + +C ARRAY ARGUMENTS + integer ind(nind) + double precision v(n) + +C This subroutine shrinks vector v from the full dimension space +C (dimension n) to the reduced space (dimension nind). +C +C On entry: +C +C nind integer +C dimension of the reduced space +C +C ind integer ind(nind) +C components ind(1)-th, ..., ind(nind)-th are the +C components that belong to the reduced space +C +C n integer +C dimension of the full space +C +C v double precision v(n) +C vector to be shrinked +C +C On Return +C +C v double precision v(n) +C shrinked vector + +C LOCAL SCALARS + integer i,indi + double precision tmp + + do i = 1,nind + indi = ind(i) + if ( i .ne. indi ) then + tmp = v(indi) + v(indi) = v(i) + v(i) = tmp + end if + end do + + return + + end + +C ****************************************************************** +C ****************************************************************** + + subroutine expand(nind,ind,n,v) + + implicit none + +C SCALAR ARGUMENTS + integer n, nind + +C ARRAY ARGUMENTS + integer ind(nind) + double precision v(n) + +C This subroutine expands vector v from the reduced space +C (dimension nind) to the full space (dimension n). +C +C On entry: +C +C nind integer +C dimension of the reduced space +C +C ind integer ind(nind) +C components ind(1)-th, ..., ind(nind)-th are the +C components that belong to the reduced space +C +C n integer +C dimension of the full space +C +C v double precision v(n) +C vector to be expanded +C +C On Return +C +C v double precision v(n) +C expanded vector + +C LOCAL SCALARS + integer i,indi + double precision tmp + + do i = nind,1,- 1 + indi = ind(i) + if ( i .ne. indi ) then + tmp = v(indi) + v(indi) = v(i) + v(i) = tmp + end if + end do + + return + + end + +C ****************************************************************** +C ****************************************************************** + + subroutine evalnaldiff(n,x,m,lambda,rho,g,sterel,steabs,inform) + + implicit none + +C SCALAR ARGUMENTS + integer n,m,inform + double precision sterel,steabs + +C ARRAY ARGUMENTS + double precision x(n),lambda(m),rho(m),g(n) + +C Approximates the gradient vector g(x) of the objective function by +C central finite differences. This subroutine, which works in the +C full space, is prepared to replace the subroutine evalnal (to +C evaluate the gradient vector) in the case of the lastest have not +C being provided by the user. +C +C On entry: +C +C n integer +C number of variables +C +C x double precision x(n) +C current point +C +C m integer +C lambda double precision lambda(m) +C rho double precision rho(m) +C These three parameters are not used nor modified by +C GENCAN and they are passed as arguments to the user- +C defined subroutines evalal and evalnal to compute the +C objective function and its gradient, respectively. +C Clearly, in an Augmented Lagrangian context, if GENCAN is +C being used to solve the bound-constrainted subproblems, m +C would be the number of constraints, lambda the Lagrange +C multipliers approximation and rho the penalty parameters +C +C sterel double precision +C See below +C +C steabs double precision +C This constants mean a ''relative small number'' and ''an +C absolute small number'' for the increments in finite +C difference approximations of derivatives +C +C RECOMMENDED: epsrel = 1.0d-07 and epsabs = 1.0d-10 +C +C CONSTRAINTS: sterel >= steabs > 0 +C +C On Return +C +C g double precision g(n) +C approximation of the gradient vector at x +C +C inform integer +C 0 = no errors, +C < 0 = there was an error in the gradient calculation. + +C LOCAL SCALARS + integer j + double precision tmp,step,fplus,fminus + + inform = 0 + + do j = 1,n + tmp = x(j) + step = max( steabs, sterel * abs( tmp ) ) + + x(j) = tmp + step + call evalal(n,x,m,lambda,rho,fplus,inform) + if ( inform .lt. 0 ) then + return + end if + + x(j) = tmp - step + call evalal(n,x,m,lambda,rho,fminus,inform) + if ( inform .lt. 0 ) then + return + end if + + g(j) = ( fplus - fminus ) / ( 2.0d0 * step ) + x(j) = tmp + end do + + return + + end + +C ***************************************************************** +C ***************************************************************** + + double precision function norm2s(n,x) + + implicit none + +C SCALAR ARGUMENTS + integer n + +C ARRAY ARGUMENTS + double precision x(n) + +C This subroutine computes the squared Euclidian norm of an +C n-dimensional vector. +C +C On entry: +C +C n integer +C dimension +C +C x double precision x(n) +C vector +C +C On return: +C +C The function return the squared Euclidian norm of the +C n-dimensional vector x. + + external hsldnrm2 + double precision hsldnrm2 + + norm2s = hsldnrm2(n,x,1) ** 2 + + return + + end + +C ****************************************************************** +C ****************************************************************** + + DOUBLE PRECISION FUNCTION HSLDNRM2(N,DX,INCX) + DOUBLE PRECISION ZERO,ONE + PARAMETER (ZERO=0.0D0,ONE=1.0D0) + DOUBLE PRECISION CUTLO,CUTHI + PARAMETER (CUTLO=8.232D-11,CUTHI=1.304D19) + INTEGER INCX,N + DOUBLE PRECISION DX(*) + DOUBLE PRECISION HITEST,SUM,XMAX + INTEGER I,J,NN + INTRINSIC DABS,DSQRT,FLOAT + IF (N.GT.0) GO TO 10 + HSLDNRM2 = ZERO + GO TO 300 + 10 CONTINUE + SUM = ZERO + NN = N*INCX + I = 1 + 20 CONTINUE + 30 IF (DABS(DX(I)).GT.CUTLO) GO TO 85 + XMAX = ZERO + 50 IF (DX(I).EQ.ZERO) GO TO 200 + IF (DABS(DX(I)).GT.CUTLO) GO TO 85 + GO TO 105 + 100 I = J + SUM = (SUM/DX(I))/DX(I) + 105 XMAX = DABS(DX(I)) + GO TO 115 + 70 IF (DABS(DX(I)).GT.CUTLO) GO TO 75 + 110 IF (DABS(DX(I)).LE.XMAX) GO TO 115 + SUM = ONE + SUM* (XMAX/DX(I))**2 + XMAX = DABS(DX(I)) + GO TO 200 + 115 SUM = SUM + (DX(I)/XMAX)**2 + GO TO 200 + 75 SUM = (SUM*XMAX)*XMAX + 85 HITEST = CUTHI/DFLOAT(N) + DO 95 J = I,NN,INCX + IF (DABS(DX(J)).GE.HITEST) GO TO 100 + SUM = SUM + DX(J)**2 + 95 END DO + HSLDNRM2 = DSQRT(SUM) + GO TO 300 + 200 CONTINUE + I = I + INCX + IF (I.LE.NN) GO TO 20 + HSLDNRM2 = XMAX*DSQRT(SUM) + 300 CONTINUE + RETURN + END + +C ****************************************************************** +C ****************************************************************** +C +C Report of modifications. +C +C February 18th, 2005. +C +C 1) An unsed format statement, previously used to automaticaly +C generates some tables, was deleted. +C +C 2) An unmateched parenthesis was corrected in the format +C statement used to stop GENCAN due to a small step in a line search. +C +C February 16th, 2005. +C +C 1) The evalhd subroutine used by default in GENCAN is now the one +C implemented in calchddiff, which approximates the Hessian-vector +C product by incremental quotients. The implementation used to +C overcome the non twice continuously differentiability of the +C classical (PHR) Augmented Lagrangian function is now part of +C ALGENCAN (and not GENCAN). So, to use GENCAN inside ALGENCAN, +C htvtype argument must be set equal to 0 (ZERO). +C +C 2) The commented version of the empty function evalhd that must +C be added when GENCAN is beinf used stand-alone was wrong. The +C arguments declarations had been copied from evalnal. It was +C corrected. +C +C November 10th, 2004. +C +C 1) After several test, all references to nonmontone line search +C schemes were deleted. +C +C September 28th, 2004. +C +C 1) Subroutines were checked an some absent arguments explanations +C were added +C +C 2) Some calling sequences were modified to group related arguments +C +C 3) Arguments and local variables declarations were reordered in +C alphabetical order. +C +C 3) Shrink and expand subroutines were modified to deal with just +C one vector at a time. In this way, they are now being called from +C calc* subroutines. +C +C September 27th, 2004. +C +C 1) All comments were arranged to fit into the 72-columns format +C +C 2) Unused variable goth, which was prepared to indicate whether +C the Hessian matrix have been evaluated at the current point, was +C deleted from CG subroutine. +C +C 3) A spell check was used to correct the comments +C +C September 21th, 2004. +C +C 1) In the stopping criterion where the progress in the objective +C function is verified, ''itnfp .ge. maxitnfp'' was changed for +C ''itnfp .gt. maxitnfp'', to make the choice maxitnfp equal to 1 +C sounds reasonable. +C +C 2) Moreover, the previous chance came from the addition in the +C comments of GENCAN of the ''constraints'' information which makes +C clear to the user the values each argument may assume. +C +C 3) In the calculations of the first ''trust-radius'' for Conjugate +C Gradients, ''if( udelta0 .lt. 0.d0 ) then'' was changed by ''if +C ( udelta0 .le. 0.0d0 ) then'' to also make the default GENCAN +C choice of this initial trust-radius in the case of the user have +C been setted udelta = 0 by mistake. +C +C 4) The same for ucgmaxit. +C +C 5) In the line search subroutines spgls and tnls, ''if ( interp +C .gt. mininterp .and. samep ) then'' was changes by ''.ge.''. +C +C 6) Some comments of GENCAN arguments were re-written. +C +C September 16th, 2004. +C +C 1) With the reconfiguration of the calc* subroutines (see (1) +C below) there were a number of redundant parameters in calchd and +C evalhd subroutines. These parameters were eliminated. +C +C September 13th, 2004. +C +C 1) Subroutines named calc* that work in the reduced space always +C call the corresponding eval* subroutine. As it was, calcg (that +C computes the gradient in the reduced space) called evalg or +C evalgdiff depending on gtype parameter. The same was for calchd. +C Now, calcg calls evalg, calchd calls evalhd, and calchddiff (new) +C approximates the Hessian times vector product by incremental +C quotients calling calcg or calcgdiff depending on gtype parameter. +C An improvement of this modification is that calcg does not call +C evalg or evalgdiff (both work in the full space) any more but it +C approximates the gradient vector in the reduced space (by central +C finite differences) calling 2 * nind times evalf subroutine. +C +C 2) Some comments were added inside evalg and evalhd user supplied +C subroutines alerting about the relation of these subroutines and +C the parameters gtype and htvtype, respectively. +C +C 3) Description of tnls subroutine was slightly modified. +C +C 4) The description of htvtype parameter in gencan was again +C slightly modified. +C +C 5) With the introduction of the parameter lambda (that in the +C context of Augmented Lagrangians is used to store the +C approximation of the Lagrange multipliers) the name of the +C variable used for spectral steplength was changed from lambda to +C lamspg. In addition, lammax was changed to lspgma and lammin to +C lspgmi. +C +C 6) Modifications introduced in June 15th, 2004 and May 5th, 2004 +C were, in fact, made in this version on September 13th, 2004. +C +C June 15th, 2004. +C +C 1) The fmin stopping criterion and the maximum number of +C functional evaluation stopping criterion were erroneously being +C tested before the main loop. It was just redundant and, for this +C reason, deleted. +C +C May 5th, 2004. +C +C 1) Incorporated into an Augmented Lagrangian framework. +C +C a) evalf and evalg were renamed as evalal and evalnal, +C respectively. +C +C b) m,lambda,rho were added as parameters of the subroutines evalal +C and evalnal, and, as a consequence, as parameters of almost all +C the other subroutines. +C +C 2) The comment of htvtype parameter of gencan was in portuguese +C and it was translated into english. +C +C 3) A nonmonotone version of gencan is starting to be studied. +C Parameters p and lastfv(0:p-1) were added to gencan, spgls, and +C tnls to allow a nonmonotone line search. Array lastfv is now +C been updated for saving the last p functional values and the +C nonmonotone line searches are been done in a SPG or a +C Truncated Newton direction. p = 1 means monotone line search +C and is recommended until this study finish. +C +C April 13th, 2004. +C +C 1) The modifications introduced in the occasion of the IRLOC +C development and re-development (October 21th, 2003 and February +C 19th, 2003, respectively) were in fact made in this version on +C April 13th, 2004. The motivation to do this was to unify two +C parallel and different version of GENCAN (created, obviously, by +C mistake). +C +C 2) The complete reference of the GENCAN paper was finally added. +C +C May 14th, 2003. +c +C 1) The way amax2 and amax2n were being computing may caused a +C segmentation fault. Its initialization was changed from infty and +C -infty to 1.0d+99 and -1.0d+99, respectively. Using infty, when +C combined with a big trust region radius, the final value of amax2 +C or amax2n may cause the impression that a bound is being attained, +C when it is not. "Redundant" ifs inside the amax2 and anax2n +C calculation were deleted. It should considered the possibility of +C using two constants, namely, bignum = 1.0d+20 and infty = 1.0d+99, +C instead of just infty. +C +C Modification introduced in October 21, 2003 in occasion of the +C IRLOC re-development: +C +C 1) The stooping criteria related to functional value smaller than +C fmin and exhaustion of maximum allowed number of functional +C evaluations have been done after the line search. And the +C questions were done as "if line search flag is equal to 4" or "if +C line search flag is equal to 8". But it was wrong in the case, for +C example, inside the line search, a functional value such that f <= +C fmin and the Armijo criterion was satisfied. In such case, the +C line search flag was being setted to 0 and not to 4. And gencan +C did not stop by the fmin criterion. Now, both stooping criteria +C are tested at the begining of the main gencan loop and just the +C stooping criteria by small line search step is tested after the +C line search. +C +C Modification introduced in February 19, 2003 in occasion of the +C IRLOC development: +C +C 1) The description of epsnfp parameter of GENCAN was modified. It +C was written that to inhibit the related stopping criterion (lack +C of function progress) it was necessary just set epsnfp = 0 when +C it is also necessary to set maxitnfp = maxit. it was added in the +C explanation. +C +C 2) In the explanation at the beginning of GENCAN it was written +C that cgscre parameter should be double precision. This comment was +C wrong. The correct type for cgscre parameter is integer. +C +C Modifications introduced near April 1st 2003 in occasion of the +C PHR and inequality-constraints Augmented Lagrangian methods +C development: +C +C 1) The use of iprint was redefined and iprint2 was deleted. +C +C 2) The way to detect no progress in the log of the projected +C gradient norm was changed. As it was, ''no progress'' means no +C reduction in the projected gradient norm over M iterations. +C But this criterion implicitly assumed that the projected +C gradient norm must decrease monotonously. Is it is clearly not +C true, the criterion was changed by a non-monotone decrease +C criterion. Now, progress means that the projected gradient +C norm is, at each iteration, smaller than the maximum over the +C last M iterations. And "no progress" means the it does not +C occurs during not smaller than the +C +C 3 ) The computation of qamaxn inside cg subroutine was in the +C wrong place (it was being used before computed) and it may was +C the reason for which the option nearlyq = .true. never worked +C properly. With this correction this option should be tested again. +C +C On September 29th, 2004, we did a new test using the 41 bound +C constrained problems with quadratic objective function from the +C CUTE collection. The behaviour of GENCAN setting nearly equal +C to true or false was indistinguishable. The test did not +C include the different choices for the maximum number of CG +C iterations being restricted to evaluate the different +C alternatives for the case of finding a direction d such that +C d^t H d <= 0. As a conclusion of this experiment we continue +C recommending as a default choice to set nearlyq equal to false. +C +C Modifications introduced from March 1st to March 21th of 2002 +C in occasion of the ISPG development: +C +C 1) Comments of some new parameters introduced in the previous +C modification +C +C 2) As it was, in the first iteration of GENCAN (when kappa takes +C value equal 1) and for one-dimensional faces, cgmaxit(the maximum +C number of Conjugate Gradient iterations to compute the internal to +C the face truncated-Newton direction) was being 0. As it is +C obviously wrong, we add a max between what was being computed and +C one to allow at least one CG iteration. +C +C 3) Parameter inform in subroutines evalf, evalg and evalhd +C supplied by the user was added +C +C Modifications introduced from May 31th to November 2nd of 2001 +C in occasion of the ALGENCAN development: +C +C Fixed bugs: +C +C 1) The first spectral steplength was not been projected in the +C [lspgmi,lspgma] interval. +C +C 2) The conjugate gradients accuracy (cgeps) which is linearly +C dependent of the Euclidian norm of the projected gradient, was +C also not been projected in the interval [cgepsi,cgepsf]. +C +C 3) Conjugate gradients said that it was being used an Euclidian +C norm trust region when it has really being used an infinite norm +C trust region and viceversa. +C +C 4) Sometimes, the analytic gradient has been used although the +C user choose the finite differences option. +C +C Modifications: +C +C 1) To avoid roundoff errors, an explicit detection of at least one +C variable reaching its bound when a maximum step is being made was +C added. +C +C 2) The way in which two points were considered very similar in, +C for example, the interpolations and the extrapolations (which was +C dependent of the infinity norm of the points) showed to be very +C scale dependent. A new version which test the difference +C coordinate to coordinate was done. In this was the calculus of the +C current point x and the descent direction sup-norm is not done any +C more. +C +C 3) The same constants epsrel and epsabs were used as small +C relative and absolute values for, for example, detecting similar +C points and for finite differences. Now, epsrel and epsabs are used +C for detecting similar points (and the recommended values are +C 10^{-10} and 10^{-20}, respectively) and new constants sterel and +C steabs were introduced for finite differences (and the recommended +C values are 10^{-7} and 10^{-10}, respectively). +C +C 4) Two new stopping criteria for CG were added: (i) we stop if +C two consecutive iterates are too close; and (ii) we also +C stop if there is no enough quadratic model progress during +C maxitnqmp iterations. +C +C 5) The linear relation between the conjugate gradient accuracy +C and the norm of the projected gradient can be computed using +C the Euclidian- and the sup-norm of the projected gradient (only +C Euclidian norm version was present in the previous version. The +C linear relation is such that the CG accuracy is cgepsi when the +C projected gradient norm value is equal to the value corresponding +C to the initial guess and the CG accuracy is cgepsf when the +C projected gradient norm value is cgrelf). +C +C 6) Inside Conjugate Gradients, the Euclidian-norm is been computed +C using an algorithm developed by C.L.LAWSON, 1978 JAN 08. Numerical +C experiments showed that the performance of GENCAN depends +C basically on the conjugate gradients performance and stopping +C criteria and that the conjugate gradients depends on the way the +C Euclidian-norm is been computed. These things deserve further +C research. +C +C 7) In the Augmented Lagrangian algorithm ALGENCAN, which uses +C GENCAN to solve the bounded constrained subproblems, the maximum +C number of Conjugate Gradients iterations (cgmaxit), which in this +C version is linearly dependent of the projected gradient norm, was +C set to 2 * (# of free variables). As CG is not using restarts we +C do not know very well what this means. On the other hand, the +C accuracy (given by cgeps) continues being more strict when we are +C near to the solution and less strict when we ar far from the +C solution. +c +C 8) Many things in the output were changed. diff --git a/tests/packmol/getinp.f90 b/tests/packmol/getinp.f90 new file mode 100644 index 00000000..89144e86 --- /dev/null +++ b/tests/packmol/getinp.f90 @@ -0,0 +1,1108 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Subroutine getinp: subroutine that reads the input file +! + +subroutine getinp() + + use sizes + use compute_data, only : ntype, natoms, idfirst, nmols, ityperest, coor, restpars + use input + use usegencan + + implicit none + integer :: i, k, ii, iarg, iline, idatom, iatom, in, lixo, irest, itype, itest,& + imark, ioerr, nloop0, iread, idfirstatom + double precision :: clen + character(len=strl) :: record, blank + logical :: inside_structure + + ! Clearing the blank character arrays + + do i = 1, strl + blank(i:i) = ' ' + end do + + ! Getting random seed and optional optimization parameters if set + + seed = 1234567 + randini = .false. + check = .false. + chkgrad = .false. + iprint1 = 2 + iprint2 = 2 + discale = 1.1d0 + writeout = 10 + maxit = 20 + nloop = 0 + nloop0 = 0 + movefrac = 0.05 + movebadrandom = .false. + precision = 1.d-2 + writebad = .false. + add_amber_ter = .false. + add_box_sides = .false. + add_sides_fix = 0.d0 + sidemax = 1000.d0 + ioerr = 0 + avoidoverlap = .true. + packall = .false. + use_short_tol = .false. + crd = .false. + + inside_structure = .false. + + do i = 1, nlines + + if ( keyword(i,1).eq.'structure') inside_structure = .true. + if ( keyword(i,1).eq.'end' .and. & + keyword(i,2).eq.'structure') inside_structure = .false. + + if(keyword(i,1).eq.'seed') then + read(keyword(i,2),*,iostat=ioerr) seed + if ( ioerr /= 0 ) exit + if ( seed == -1 ) call seed_from_time(seed) + else if(keyword(i,1).eq.'randominitialpoint') then + randini = .true. + else if(keyword(i,1).eq.'check') then + check = .true. + else if(keyword(i,1).eq.'writebad') then + writebad = .true. + else if(keyword(i,1).eq.'precision') then + read(keyword(i,2),*,iostat=ioerr) precision + if ( ioerr /= 0 ) exit + write(*,*) ' Optional precision set: ', precision + else if(keyword(i,1).eq.'movefrac') then + read(keyword(i,2),*,iostat=ioerr) movefrac + if ( ioerr /= 0 ) exit + write(*,*) ' Optional movefrac set: ', movefrac + else if(keyword(i,1).eq.'movebadrandom') then + movebadrandom = .true. + write(*,*) ' Will move randomly bad molecues (movebadrandom) ' + else if(keyword(i,1).eq.'chkgrad') then + chkgrad = .true. + else if(keyword(i,1).eq.'writeout') then + read(keyword(i,2),*,iostat=ioerr) writeout + if ( ioerr /= 0 ) exit + write(*,*) ' Output frequency: ', writeout + else if(keyword(i,1).eq.'maxit') then + read(keyword(i,2),*,iostat=ioerr) maxit + if ( ioerr /= 0 ) exit + write(*,*) ' User defined GENCAN number of iterations: ', maxit + else if(keyword(i,1).eq.'nloop') then + if( .not. inside_structure ) then + read(keyword(i,2),*,iostat=ioerr) nloop + if ( ioerr /= 0 ) exit + end if + else if(keyword(i,1).eq.'nloop0') then + if( .not. inside_structure ) then + read(keyword(i,2),*,iostat=ioerr) nloop0 + if ( ioerr /= 0 ) exit + end if + else if(keyword(i,1).eq.'discale') then + read(keyword(i,2),*,iostat=ioerr) discale + if ( ioerr /= 0 ) exit + write(*,*) ' Optional initial tolerance scale: ', discale + else if(keyword(i,1).eq.'sidemax') then + read(keyword(i,2),*,iostat=ioerr) sidemax + if ( ioerr /= 0 ) exit + write(*,*) ' User set maximum system dimensions: ', sidemax + else if(keyword(i,1).eq.'fbins') then + read(keyword(i,2),*,iostat=ioerr) fbins + if ( ioerr /= 0 ) exit + write(*,*) ' User set linked-cell bin parameter: ', fbins + else if(keyword(i,1).eq.'add_amber_ter') then + add_amber_ter = .true. + write(*,*) ' Will add the TER flag between molecules. ' + else if(keyword(i,1).eq.'avoid_overlap') then + if ( keyword(i,2).eq.'yes') then + avoidoverlap = .true. + write(*,*) ' Will avoid overlap to fixed molecules at initial point. ' + else + avoidoverlap = .false. + write(*,*) ' Will NOT avoid overlap to fixed molecules at initial point. ' + end if + else if(keyword(i,1).eq.'packall') then + packall = .true. + write(*,*) ' Will pack all molecule types from the beginning. ' + else if(keyword(i,1).eq.'use_short_tol') then + use_short_tol = .true. + write(*,*) ' Will use a short distance penalty for all atoms. ' + else if(keyword(i,1).eq.'writecrd') then + crd = .true. + write(*,*) ' Will write output also in CRD format ' + read(keyword(i,2),*,iostat=ioerr) crdfile + else if(keyword(i,1).eq.'add_box_sides') then + add_box_sides = .true. + write(*,*) ' Will print BOX SIDE informations. ' + read(keyword(i,2),*,iostat=ioerr) add_sides_fix + if ( ioerr /= 0 ) then + ioerr = 0 + cycle + end if + write(*,*) ' Will sum ', add_sides_fix,' to each side length on print' + else if(keyword(i,1).eq.'iprint1') then + read(keyword(i,2),*,iostat=ioerr) iprint1 + if ( ioerr /= 0 ) exit + write(*,*) ' Optional printvalue 1 set: ', iprint1 + else if(keyword(i,1).eq.'iprint2') then + read(keyword(i,2),*,iostat=ioerr) iprint2 + if ( ioerr /= 0 ) exit + write(*,*) ' Optional printvalue 2 set: ', iprint2 + else if( keyword(i,1) /= 'tolerance' .and. & + keyword(i,1) /= 'short_tol_dist' .and. & + keyword(i,1) /= 'short_tol_scale' .and. & + keyword(i,1) /= 'structure' .and. & + keyword(i,1) /= 'end' .and. & + keyword(i,1) /= 'atoms' .and. & + keyword(i,1) /= 'output' .and. & + keyword(i,1) /= 'filetype' .and. & + keyword(i,1) /= 'number' .and. & + keyword(i,1) /= 'inside' .and. & + keyword(i,1) /= 'outside' .and. & + keyword(i,1) /= 'fixed' .and. & + keyword(i,1) /= 'center' .and. & + keyword(i,1) /= 'centerofmass' .and. & + keyword(i,1) /= 'over' .and. & + keyword(i,1) /= 'above' .and. & + keyword(i,1) /= 'below' .and. & + keyword(i,1) /= 'constrain_rotation' .and. & + keyword(i,1) /= 'radius' .and. & + keyword(i,1) /= 'fscale' .and. & + keyword(i,1) /= 'short_radius' .and. & + keyword(i,1) /= 'short_radius_scale' .and. & + keyword(i,1) /= 'resnumbers' .and. & + keyword(i,1) /= 'connect' .and. & + keyword(i,1) /= 'changechains' .and. & + keyword(i,1) /= 'chain' .and. & + keyword(i,1) /= 'discale' .and. & + keyword(i,1) /= 'maxit' .and. & + keyword(i,1) /= 'movebadrandom' .and. & + keyword(i,1) /= 'maxmove' .and. & + keyword(i,1) /= 'add_amber_ter' .and. & + keyword(i,1) /= 'sidemax' .and. & + keyword(i,1) /= 'seed' .and. & + keyword(i,1) /= 'randominitialpoint' .and. & + keyword(i,1) /= 'restart_from' .and. & + keyword(i,1) /= 'restart_to' .and. & + keyword(i,1) /= 'nloop' .and. & + keyword(i,1) /= 'nloop0' .and. & + keyword(i,1) /= 'writeout' .and. & + keyword(i,1) /= 'writebad' .and. & + keyword(i,1) /= 'check' .and. & + keyword(i,1) /= 'iprint1' .and. & + keyword(i,1) /= 'iprint2' .and. & + keyword(i,1) /= 'writecrd' .and. & + keyword(i,1) /= 'segid' .and. & + keyword(i,1) /= 'chkgrad' ) then + write(*,*) ' ERROR: Keyword not recognized: ', trim(keyword(i,1)) + stop + end if + end do + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Some optional keyword was not used correctly: ', trim(keyword(i,1)) + stop + end if + write(*,*) ' Seed for random number generator: ', seed + call init_random_number(seed) + + ! Checking for the name of the output file to be created + + xyzout = '####' + do iline = 1, nlines + if(keyword(iline,1).eq.'output') then + xyzout = keyword(iline,2) + xyzout = trim(adjustl(xyzout)) + end if + end do + if(xyzout(1:4) == '####') then + write(*,*)' ERROR: Output file not (correctly?) specified. ' + stop + end if + write(*,*)' Output file: ', trim(adjustl(xyzout)) + + ! Reading structure files + + itype = 0 + do iline = 1, nlines + if(keyword(iline,1).eq.'structure') then + itype = itype + 1 + + record = keyword(iline,2) + write(*,*) ' Reading coordinate file: ', trim(adjustl(record)) + + ! Reading pdb input files + + if(pdb) then + name(itype) = trim(adjustl(record)) + record = keyword(iline,2) + pdbfile(itype) = trim(record) + idfirst(itype) = 1 + idfirstatom = 0 + do ii = itype - 1, 1, -1 + idfirst(itype) = idfirst(itype) + natoms(ii) + end do + open(10,file=keyword(iline,2),status='old',iostat=ioerr) + if ( ioerr /= 0 ) call failopen(keyword(iline,2)) + ! Read coordinates + record(1:6) = '######' + do while(record(1:4).ne.'ATOM'.and.record(1:6).ne.'HETATM') + read(10,str_format) record + end do + idatom = idfirst(itype) - 1 + do while(idatom.lt.natoms(itype)+idfirst(itype)-1) + if(record(1:4).eq.'ATOM'.or.record(1:6).eq.'HETATM') then + idatom = idatom + 1 + amass(idatom) = 1.d0 + maxcon(idatom) = 0 + ! Read the index of the first atom, to adjust connectivities, if any + if(idfirstatom == 0) read(record(7:11),*,iostat=ioerr) idfirstatom + read(record,"( t31,f8.3,t39,f8.3,t47,f8.3 )",iostat=ioerr) & + (coor(idatom,k),k=1,3) + if( ioerr /= 0 ) then + record = keyword(iline,2) + write(*,*) ' ERROR: Failed to read coordinates from', & + ' file: ', trim(adjustl(record)) + write(*,*) ' Probably the coordinates are not in', & + ' standard PDB file format. ' + write(*,*) ' Standard PDB format specifications', & + ' can be found at: ' + write(*,*) ' www.rcsb.org/pdb ' + stop + end if + + ! This only tests if residue numbers can be read, they are used + ! only for output + read(record(23:26),*,iostat=ioerr) itest + if( ioerr /= 0 ) then + record = pdbfile(itype) + write(*,*) ' ERROR: Failed reading residue number',& + ' from PDB file: ', trim(adjustl(record)) + write(*,*) ' Residue numbers are integers that',& + ' must be within columns 23 and 26. ' + write(*,*) ' Other characters within these columns',& + ' will cause input/output errors. ' + write(*,*) ' Standard PDB format specifications',& + ' can be found at: ' + write(*,*) ' www.rcsb.org/pdb ' + stop + end if + end if + read(10,str_format,iostat=ioerr) record + end do + ! + ! Read connectivity, if there is any specified + ! + do while(.true.) + if ( ioerr /= 0 ) exit + if(record(1:6).eq.'CONECT') then + iread = 7 + read(record(iread:iread+4),*,iostat=ioerr) iatom + iatom = iatom - idfirstatom + 1 + idatom = idfirst(itype) - 1 + iatom + if(ioerr /= 0) then + write(*,*) " ERROR: Could not read atom index from CONECT line: " + write(*,*) trim(adjustl(record)) + stop + end if + iread = iread + 5 + read(record(iread:iread+4),*,iostat=ioerr) nconnect(idatom,1) + if(ioerr /= 0) then + write(*,*) " ERROR: Could not read any connection index from CONECT line: " + write(*,*) trim(adjustl(record)) + stop + end if + nconnect(idatom,1) = nconnect(idatom,1) - idfirstatom + 1 + maxcon(idatom) = 1 + do while(.true.) + iread = iread + 5 + read(record(iread:iread+4),*,iostat=ioerr) nconnect(idatom,maxcon(idatom)+1) + if(ioerr == 0) then + maxcon(idatom) = maxcon(idatom) + 1 + nconnect(idatom,maxcon(idatom)) = nconnect(idatom,maxcon(idatom)) - idfirstatom + 1 + else + exit + end if + end do + end if + read(10,str_format,iostat=ioerr) record + end do + close(10) + end if + + ! Reading tinker input files + + if(tinker) then + open(10,file=keyword(iline,2),status='old',iostat=ioerr) + if ( ioerr /= 0 ) call failopen(keyword(iline,2)) + idfirst(itype) = 1 + do ii = itype - 1, 1, -1 + idfirst(itype) = idfirst(itype) + natoms(ii) + end do + record = keyword(iline,2) + call setcon(record(1:64),idfirst(itype)) + open(10,file = keyword(iline,2), status = 'old') + record = blank + do while(record.le.blank) + read(10,str_format) record + end do + i = 1 + do while(record(i:i).le.' ') + i = i + 1 + if ( i > strl ) exit + end do + iarg = i + if ( i < strl ) then + do while(record(i:i).gt.' ') + i = i + 1 + if ( i > strl ) exit + end do + end if + read(record(iarg:i-1),*) natoms(itype) + if ( i < strl ) then + do while(record(i:i).le.' ') + i = i + 1 + if ( i > strl ) exit + end do + end if + iarg = i + if ( i < strl ) then + do while(record(i:i).gt.' ') + i = i + 1 + if ( i > strl ) exit + end do + end if + read(record(iarg:i-1),str_format) name(itype) + record = name(itype) + name(itype) = trim(adjustl(record)) + if(name(itype).lt.' ') name(itype) = 'Without_title' + idatom = idfirst(itype) - 1 + do iatom = 1, natoms(itype) + idatom = idatom + 1 + record = blank + do while(record.le.blank) + read(10,str_format) record + end do + i = 1 + do while(record(i:i).le.' ') + i = i + 1 + if ( i > strl ) exit + end do + iarg = i + if ( i < strl ) then + do while(record(i:i).gt.' ') + i = i + 1 + if ( i > strl ) exit + end do + end if + read(record(iarg:i-1),*) in + if ( i < strl ) then + do while(record(i:i).le.' ') + i = i + 1 + if ( i > strl ) exit + end do + end if + iarg = i + if ( i < strl ) then + do while(record(i:i).gt.' ') + i = i + 1 + if ( i > strl ) exit + end do + end if + read(record(iarg:i-1),*) ele(idatom) + read(record(i:strl),*) (coor(idatom,k), k = 1, 3),& + (nconnect(idatom, k), k = 1, maxcon(idatom)) + amass(idatom) = 1.d0 + end do + close(10) + end if + + ! Reading xyz input files + + if(xyz) then + open(10,file=keyword(iline,2),status='old',iostat=ioerr) + if ( ioerr /= 0 ) call failopen(keyword(iline,2)) + read(10,*) natoms(itype) + read(10,str_format) name(itype) + if(name(itype).lt.' ') name(itype) = 'Without_title' + idfirst(itype) = 1 + do ii = itype - 1, 1, -1 + idfirst(itype) = idfirst(itype) + natoms(ii) + end do + idatom = idfirst(itype) - 1 + do iatom = 1, natoms(itype) + idatom = idatom + 1 + record = blank + read(10,str_format) record + read(record,*) ele(idatom), (coor(idatom,k),k=1,3) + amass(idatom) = 1.d0 + end do + close(10) + end if + + ! Reading moldy input files + + if(moldy) then + open(10,file=keyword(iline,2), status ='old',iostat=ioerr) + if ( ioerr /= 0 ) call failopen(keyword(iline,2)) + read(10,*) name(itype), nmols(itype) + natoms(itype) = 0 + do while(.true.) + read(10,str_format,iostat=ioerr) record + if ( ioerr /= 0 ) exit + if(record.gt.' '.and.record(1:3).ne.'end') & + natoms(itype) = natoms(itype) + 1 + end do + close(10) + idfirst(itype) = 1 + do ii = itype - 1, 1, -1 + idfirst(itype) = idfirst(itype) + natoms(ii) + end do + open(10,file=keyword(iline,2),status='old') + read(10,str_format) record + idatom = idfirst(itype) - 1 + do iatom = 1, natoms(itype) + idatom = idatom + 1 + read(10,str_format) record + read(record,*) lixo, (coor(idatom,k), k = 1, 3),& + amass(idatom), charge(idatom), ele(idatom) + end do + close(10) + end if + end if + + end do + ntype = itype + + write(*,*) ' Number of independent structures: ', ntype + write(*,*) ' The structures are: ' + + do itype = 1, ntype + record = name(itype) + write(*,*) ' Structure ', itype, ':', trim(adjustl(record)),& + '(',natoms(itype),' atoms)' + end do + + ! Setting the vectors for the number of GENCAN loops + + if(nloop.eq.0) then + nloop_all = 200*ntype + nloop = nloop_all + else + nloop_all = nloop + end if + write(*,*) ' Maximum number of GENCAN loops for all molecule packing: ', nloop_all + do itype = 1, ntype + if ( nloop_type(itype) == 0 ) then + nloop_type(itype) = nloop_all + else + write(*,*) ' Maximum number of GENCAN loops for type: ', itype, ': ', nloop_type(itype) + end if + end do + + ! nloop0 are the number of loops for the initial phase packing + + if(nloop0.eq.0) then + nloop0 = 20*ntype + else + write(*,*) ' Maximum number of GENCAN loops-0 for all molecule packing: ', nloop0 + end if + do itype = 1, ntype + if ( nloop0_type(itype) == 0 ) then + nloop0_type(itype) = nloop0 + else + write(*,*) ' Maximum number of GENCAN loops-0 for type: ', itype, ': ', nloop0_type(itype) + end if + end do + + ! Reading the restrictions that were set + + irest = 0 + ioerr = 0 + do iline = 1, nlines + + if(keyword(iline,1).eq.'fixed') then + irest = irest + 1 + irestline(irest) = iline + ityperest(irest) = 1 + read(keyword(iline,2),*,iostat=ioerr) restpars(irest,1) + read(keyword(iline,3),*,iostat=ioerr) restpars(irest,2) + read(keyword(iline,4),*,iostat=ioerr) restpars(irest,3) + read(keyword(iline,5),*,iostat=ioerr) restpars(irest,4) + read(keyword(iline,6),*,iostat=ioerr) restpars(irest,5) + read(keyword(iline,7),*,iostat=ioerr) restpars(irest,6) + end if + + if(keyword(iline,1).eq.'inside') then + irest = irest + 1 + irestline(irest) = iline + if(keyword(iline,2).eq.'cube') then + ityperest(irest) = 2 + read(keyword(iline,3),*,iostat=ioerr) restpars(irest,1) + read(keyword(iline,4),*,iostat=ioerr) restpars(irest,2) + read(keyword(iline,5),*,iostat=ioerr) restpars(irest,3) + read(keyword(iline,6),*,iostat=ioerr) restpars(irest,4) + else if(keyword(iline,2).eq.'box') then + ityperest(irest) = 3 + read(keyword(iline,3),*,iostat=ioerr) restpars(irest,1) + read(keyword(iline,4),*,iostat=ioerr) restpars(irest,2) + read(keyword(iline,5),*,iostat=ioerr) restpars(irest,3) + read(keyword(iline,6),*,iostat=ioerr) restpars(irest,4) + read(keyword(iline,7),*,iostat=ioerr) restpars(irest,5) + read(keyword(iline,8),*,iostat=ioerr) restpars(irest,6) + else if(keyword(iline,2).eq.'sphere') then + ityperest(irest) = 4 + read(keyword(iline,3),*,iostat=ioerr) restpars(irest,1) + read(keyword(iline,4),*,iostat=ioerr) restpars(irest,2) + read(keyword(iline,5),*,iostat=ioerr) restpars(irest,3) + read(keyword(iline,6),*,iostat=ioerr) restpars(irest,4) + else if(keyword(iline,2).eq.'ellipsoid') then + ityperest(irest) = 5 + read(keyword(iline,3),*,iostat=ioerr) restpars(irest,1) + read(keyword(iline,4),*,iostat=ioerr) restpars(irest,2) + read(keyword(iline,5),*,iostat=ioerr) restpars(irest,3) + read(keyword(iline,6),*,iostat=ioerr) restpars(irest,4) + read(keyword(iline,7),*,iostat=ioerr) restpars(irest,5) + read(keyword(iline,8),*,iostat=ioerr) restpars(irest,6) + read(keyword(iline,9),*,iostat=ioerr) restpars(irest,7) + else if(keyword(iline,2).eq.'cylinder') then + ityperest(irest) = 12 + read(keyword(iline,3),*,iostat=ioerr) restpars(irest,1) + read(keyword(iline,4),*,iostat=ioerr) restpars(irest,2) + read(keyword(iline,5),*,iostat=ioerr) restpars(irest,3) + read(keyword(iline,6),*,iostat=ioerr) restpars(irest,4) + read(keyword(iline,7),*,iostat=ioerr) restpars(irest,5) + read(keyword(iline,8),*,iostat=ioerr) restpars(irest,6) + read(keyword(iline,9),*,iostat=ioerr) restpars(irest,7) + read(keyword(iline,10),*,iostat=ioerr) restpars(irest,9) + restpars(irest,8) = restpars(irest,4)**2 + & + restpars(irest,5)**2 + & + restpars(irest,6)**2 + if(restpars(irest,8).lt.1.d-10) then + write(*,*) ' ERROR: The norm of the director vector', & + ' of the cylinder constraint cannot be zero.' + ioerr = 1 + else + clen = dsqrt(restpars(irest,8)) + restpars(irest,4) = restpars(irest,4) / clen + restpars(irest,5) = restpars(irest,5) / clen + restpars(irest,6) = restpars(irest,6) / clen + end if + else + ioerr = 1 + end if + end if + + if(keyword(iline,1).eq.'outside') then + irest = irest + 1 + irestline(irest) = iline + if(keyword(iline,2).eq.'cube') then + ityperest(irest) = 6 + read(keyword(iline,3),*,iostat=ioerr) restpars(irest,1) + read(keyword(iline,4),*,iostat=ioerr) restpars(irest,2) + read(keyword(iline,5),*,iostat=ioerr) restpars(irest,3) + read(keyword(iline,6),*,iostat=ioerr) restpars(irest,4) + else if(keyword(iline,2).eq.'box') then + ityperest(irest) = 7 + read(keyword(iline,3),*,iostat=ioerr) restpars(irest,1) + read(keyword(iline,4),*,iostat=ioerr) restpars(irest,2) + read(keyword(iline,5),*,iostat=ioerr) restpars(irest,3) + read(keyword(iline,6),*,iostat=ioerr) restpars(irest,4) + read(keyword(iline,7),*,iostat=ioerr) restpars(irest,5) + read(keyword(iline,8),*,iostat=ioerr) restpars(irest,6) + else if(keyword(iline,2).eq.'sphere') then + ityperest(irest) = 8 + read(keyword(iline,3),*,iostat=ioerr) restpars(irest,1) + read(keyword(iline,4),*,iostat=ioerr) restpars(irest,2) + read(keyword(iline,5),*,iostat=ioerr) restpars(irest,3) + read(keyword(iline,6),*,iostat=ioerr) restpars(irest,4) + else if(keyword(iline,2).eq.'ellipsoid') then + ityperest(irest) = 9 + read(keyword(iline,3),*,iostat=ioerr) restpars(irest,1) + read(keyword(iline,4),*,iostat=ioerr) restpars(irest,2) + read(keyword(iline,5),*,iostat=ioerr) restpars(irest,3) + read(keyword(iline,6),*,iostat=ioerr) restpars(irest,4) + read(keyword(iline,7),*,iostat=ioerr) restpars(irest,5) + read(keyword(iline,8),*,iostat=ioerr) restpars(irest,6) + read(keyword(iline,9),*,iostat=ioerr) restpars(irest,7) + else if(keyword(iline,2).eq.'cylinder') then + ityperest(irest) = 13 + read(keyword(iline,3),*,iostat=ioerr) restpars(irest,1) + read(keyword(iline,4),*,iostat=ioerr) restpars(irest,2) + read(keyword(iline,5),*,iostat=ioerr) restpars(irest,3) + read(keyword(iline,6),*,iostat=ioerr) restpars(irest,4) + read(keyword(iline,7),*,iostat=ioerr) restpars(irest,5) + read(keyword(iline,8),*,iostat=ioerr) restpars(irest,6) + read(keyword(iline,9),*,iostat=ioerr) restpars(irest,7) + read(keyword(iline,10),*,iostat=ioerr) restpars(irest,9) + restpars(irest,8) = restpars(irest,4)**2 + & + restpars(irest,5)**2 + & + restpars(irest,6)**2 + if(restpars(irest,8).lt.1.d-10) then + write(*,*) ' ERROR: The norm of the director vector',& + ' of the cylinder constraint cannot be zero.' + ioerr = 1 + else + clen = dsqrt(restpars(irest,8)) + restpars(irest,4) = restpars(irest,4) / clen + restpars(irest,5) = restpars(irest,5) / clen + restpars(irest,6) = restpars(irest,6) / clen + end if + else + ioerr = 1 + end if + end if + + if(keyword(iline,1).eq.'over' .or. keyword(iline,1).eq.'above') then + irest = irest + 1 + irestline(irest) = iline + ityperest(irest) = 10 + read(keyword(iline,3),*,iostat=ioerr) restpars(irest,1) + read(keyword(iline,4),*,iostat=ioerr) restpars(irest,2) + read(keyword(iline,5),*,iostat=ioerr) restpars(irest,3) + read(keyword(iline,6),*,iostat=ioerr) restpars(irest,4) + if(keyword(iline,2).ne.'plane') ioerr = 1 + end if + + if(keyword(iline,1).eq.'below') then + irest = irest + 1 + irestline(irest) = iline + ityperest(irest) = 11 + read(keyword(iline,3),*,iostat=ioerr) restpars(irest,1) + read(keyword(iline,4),*,iostat=ioerr) restpars(irest,2) + read(keyword(iline,5),*,iostat=ioerr) restpars(irest,3) + read(keyword(iline,6),*,iostat=ioerr) restpars(irest,4) + if(keyword(iline,2).ne.'plane') ioerr = 1 + end if + + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Some restriction is not set correctly. ' + stop + end if + + end do + nrest = irest + write(*,*) ' Total number of restrictions: ', nrest + + ! Getting the tolerance + + ioerr = 1 + dism = -1.d0 + do iline = 1, nlines + if(keyword(iline,1).eq.'tolerance') then + read(keyword(iline,2),*,iostat=ioerr) dism + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Failed reading tolerance. ' + stop + end if + exit + end if + end do + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Overall tolerance not set. Use, for example: tolerance 2.0 ' + stop + end if + write(*,*) ' Distance tolerance: ', dism + + ! Reading, if defined, the short distance penalty parameters + + ioerr = 1 + short_tol_dist = dism/2.d0 + ! Reading short_tol_dist + do iline = 1, nlines + if(keyword(iline,1).eq.'short_tol_dist') then + read(keyword(iline,2),*,iostat=ioerr) short_tol_dist + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Failed reading short_tol_dist. ' + stop + end if + if ( short_tol_dist > dism ) then + write(*,*) ' ERROR: The short_tol_dist parameter must be smaller than the tolerance. ' + stop + end if + write(*,*) ' User defined short tolerance distance: ', short_tol_dist + short_tol_dist = short_tol_dist**2 + exit + end if + end do + ! Reading short_tol_scale + short_tol_scale = 3.d0 + do iline = 1, nlines + if(keyword(iline,1).eq.'short_tol_scale') then + read(keyword(iline,2),*,iostat=ioerr) short_tol_scale + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Failed reading short_tol_scale. ' + stop + end if + if ( short_tol_dist <= 0.d0 ) then + write(*,*) ' ERROR: The short_tol_scale parameter must be positive. ' + stop + end if + write(*,*) ' User defined short tolerance scale: ', short_tol_scale + exit + end if + end do + + ! Assigning the input lines that correspond to each structure + + itype = 0 + iline = 0 + do while(iline < nlines) + iline = iline + 1 + if(keyword(iline,1).eq.'structure') then + itype = itype + 1 + linestrut(itype,1) = iline + iline = iline + 1 + do while(keyword(iline,1).ne.'end'.or.& + keyword(iline,2).ne.'structure') + if(keyword(iline,1) == 'structure'.or.& + iline == nlines) then + write(*,*) ' ERROR: Structure specification not ending with "end structure"' + stop + end if + iline = iline + 1 + end do + linestrut(itype,2) = iline + end if + end do + + ! If pdb files, get the type of residue numbering output for each + ! molecule + + if(pdb) then + do itype = 1, ntype + connect(itype) = .true. + resnumbers(itype) = -1 + changechains(itype) = .false. + chain(itype) = "#" + segid(itype) = "" + maxmove(itype) = nmols(itype) + do iline = 1, nlines + if(iline.gt.linestrut(itype,1).and.& + iline.lt.linestrut(itype,2)) then + if(keyword(iline,1).eq.'changechains') then + changechains(itype) = .true. + end if + if(keyword(iline,1).eq.'maxmove') then + read(keyword(iline,2),*) maxmove(itype) + end if + if(keyword(iline,1).eq.'resnumbers') then + read(keyword(iline,2),*) resnumbers(itype) + end if + if(keyword(iline,1).eq.'connect') then + if(keyword(iline,2) == "no") then + connect(itype) = .false. + end if + end if + if(keyword(iline,1).eq.'chain') then + read(keyword(iline,2),*) chain(itype) + end if + if(keyword(iline,1).eq.'segid') then + read(keyword(iline,2),*) segid(itype) + end if + end if + end do + if (crd) then + if (itype.gt.1 .and. segid(itype)=="") then + if (segid(itype-1) /= "") then + write(*,*) ' Warning: Type of segid not defined for ', itype,'. Keeping it same as previous' + endif + segid(itype) = segid(itype-1) + endif + endif + if ( resnumbers(itype) == -1 ) then + write(*,*) ' Warning: Type of residue numbering not',& + ' set for structure ',itype + call setrnum(pdbfile(itype),imark) + if(imark.eq.1) resnumbers(itype) = 0 + if(imark.gt.1) resnumbers(itype) = 1 + end if + write(*,*) ' Residue numbering set for structure ',itype,':',& + resnumbers(itype) + write(*,*) ' Swap chains of molecules of structure ',& + itype,':', changechains(itype) + if ( chain(itype) /= "#" ) then + write(*,*) ' Specific chain identifier set for structure ',itype,':',chain(itype) + end if + if ( chain(itype) /= "#" .and. changechains(itype) ) then + write(*,*) " ERROR: 'changechains' and 'chain' input parameters are not compatible " + write(*,*) " for a single structure. " + stop + end if + end do + end if + + ! Write the number of molecules of each type + + do itype = 1, ntype + write(*,*) ' Number of molecules of type ', itype, ': ', nmols(itype) + if(pdb.and.nmols(itype).gt.9999) then + write(*,*) ' Warning: There will be more than 9999 molecules of type ',itype + if (.not. crd) write(*,*) ' Residue numbering is reset after 9999. ' + if (crd) write(*,*) ' Residue numbering is reset after 9999 in pdb but not in crd. ' + if ( chain(itype) == "#" ) then + write(*,*) ' Each set be will be assigned a different chain in the PDB output file. ' + end if + end if + if(crd.and.nmols(itype).gt.99999999) then + write(*,*) ' Warning: There will be more than 99999999 molecules of type ',itype + write(*,*) ' Residue numbering is reset after 99999999 in crd. ' + endif + end do + + ! Checking if restart files will be used for each structure or for the whole system + + restart_from(0) = "none" + restart_to(0) = "none" + do itype = 1, ntype + restart_from(itype) = "none" + restart_to(itype) = "none" + end do + lines: do iline = 1, nlines + if ( keyword(iline,1) == 'restart_from' ) then + do itype = 1, ntype + if(iline.gt.linestrut(itype,1).and.& + iline.lt.linestrut(itype,2)) then + restart_from(itype) = keyword(iline,2) + cycle lines + end if + end do + if( restart_from(0) == 'none' ) then + restart_from(0) = keyword(iline,2) + else + write(*,*) ' ERROR: More than one definition of restart_from file for all system. ' + stop + end if + end if + if ( keyword(iline,1) == 'restart_to' ) then + do itype = 1, ntype + if(iline.gt.linestrut(itype,1).and.& + iline.lt.linestrut(itype,2)) then + restart_to(itype) = keyword(iline,2) + cycle lines + end if + end do + if( restart_to(0) == 'none' ) then + restart_to(0) = keyword(iline,2) + else + write(*,*) ' ERROR: More than one definition of restart_to file for all system. ' + stop + end if + end if + end do lines + + return +end subroutine getinp + +! +! Subroutine that stops if failed to open file +! + +subroutine failopen(record) + use sizes + character(len=strl) :: record + write(*,*) + write(*,*) ' ERROR: Could not open file. ' + write(*,*) ' Could not find file: ',trim(record) + write(*,*) ' Please check if all the input and structure ' + write(*,*) ' files are in the current directory or if the' + write(*,*) ' correct paths are provided.' + write(*,*) + stop +end subroutine failopen + +! +! Subroutine that checks if a pdb structure has one or more than +! one residue +! + +subroutine setrnum(file,nres) + + use sizes + implicit none + integer :: iread, ires, ireslast, nres, ioerr + character(len=strl) :: file + character(len=strl) :: record + + open(10,file=file,status='old') + iread = 0 + nres = 1 + do while(nres.eq.1) + read(10,str_format,iostat=ioerr) record + if ( ioerr /= 0 ) exit + if(record(1:4).eq.'ATOM'.or.record(1:6).eq.'HETATM') then + read(record(23:26),*,iostat=ioerr) ires + if ( ioerr /= 0 ) cycle + iread = iread + 1 + if(iread.gt.1) then + if(ires.ne.ireslast) then + nres = 2 + close(10) + return + end if + end if + ireslast = ires + end if + end do + close(10) + + return +end subroutine setrnum + +! +! Subroutine that computes de number of connections of each atom +! for tinker xyz files +! + +subroutine setcon(xyzfile,idfirst) + + use sizes + use input, only : maxcon + implicit none + + integer :: idfirst + integer :: natoms, idatom, iatom, ic, i + character(len=64) :: xyzfile + character(len=120) :: record + + open(10, file = xyzfile, status='old') + read(10,*) natoms + idatom = idfirst - 1 + do iatom = 1, natoms + idatom = idatom + 1 + read(10,"( a120 )") record + ic = 0 + do i = 1, 119 + if(record(i:i).gt.' '.and.record(i+1:i+1).le.' ') ic = ic + 1 + end do + maxcon(idatom) = ic - 5 + end do + close(10) + + return +end subroutine setcon + +! +! Subroutine getkeywords: gets keywords and values from the input +! file in a more robust way +! + +subroutine getkeywords() + + use sizes + use input, only : keyword, nlines, inputfile, forbidden_char + implicit none + character(len=strl) :: record + integer :: iline, i, j, k, ilast, ival, ioerr + + ! Clearing keyword array + + do i = 1, nlines + do j = 1, maxkeywords + keyword(i,j) = 'none' + end do + end do + + ! Filling keyword array + do iline = 1, nlines + read(inputfile(iline),str_format,iostat=ioerr) record + if ( ioerr /= 0 ) exit + i = 0 + ival = 0 + do while(i < strl) + i = i + 1 + ilast = i + do while(record(i:i) > ' '.and. i < strl) + i = i + 1 + end do + if(i.gt.ilast) then + ival = ival + 1 + keyword(iline,ival) = record(ilast:i) + end if + end do + end do + + ! Remove quotes and the forbidden_char from keywords + do i = 1, nlines + do j = 1, maxkeywords + record = keyword(i,j) + do k = 1,strl + if (record(k:k) == forbidden_char .or. record(k:k) == '"') then + record(k:k) = " " + end if + end do + keyword(i,j) = trim(adjustl(record)) + end do + end do + + return +end subroutine getkeywords + +! Subroutine that returns the chain character given an index + +subroutine chainc(i,chain) + + implicit none + integer :: i + character :: chain + + if(i.eq.0) chain = ' ' + if(i.eq.1) chain = 'A' + if(i.eq.2) chain = 'B' + if(i.eq.3) chain = 'C' + if(i.eq.4) chain = 'D' + if(i.eq.5) chain = 'E' + if(i.eq.6) chain = 'F' + if(i.eq.7) chain = 'G' + if(i.eq.8) chain = 'H' + if(i.eq.9) chain = 'I' + if(i.eq.10) chain = 'J' + if(i.eq.11) chain = 'K' + if(i.eq.12) chain = 'L' + if(i.eq.13) chain = 'M' + if(i.eq.14) chain = 'N' + if(i.eq.15) chain = 'O' + if(i.eq.16) chain = 'P' + if(i.eq.17) chain = 'Q' + if(i.eq.18) chain = 'R' + if(i.eq.19) chain = 'S' + if(i.eq.20) chain = 'T' + if(i.eq.21) chain = 'U' + if(i.eq.22) chain = 'V' + if(i.eq.23) chain = 'W' + if(i.eq.24) chain = 'X' + if(i.eq.25) chain = 'Y' + if(i.eq.26) chain = 'Z' + if(i.eq.27) chain = '1' + if(i.eq.28) chain = '2' + if(i.eq.29) chain = '3' + if(i.eq.30) chain = '4' + if(i.eq.31) chain = '5' + if(i.eq.32) chain = '6' + if(i.eq.33) chain = '7' + if(i.eq.34) chain = '8' + if(i.eq.35) chain = '9' + if(i.eq.36) chain = '0' + if(i.gt.36) chain = '#' + + return +end subroutine chainc + +! Subroutine that clears a character variable + +subroutine clear(record) + + use sizes + integer :: i + character(len=strl) :: record + + do i = 1, strl + record(i:i) = ' ' + end do + + return +end subroutine clear + diff --git a/tests/packmol/gparc.f90 b/tests/packmol/gparc.f90 new file mode 100644 index 00000000..a604254e --- /dev/null +++ b/tests/packmol/gparc.f90 @@ -0,0 +1,87 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Compute gradient relative to atom-to-atom distances +! + +subroutine gparc(icart,firstjcart) + + use sizes + use compute_data + implicit none + + ! SCALAR ARGUMENTS + integer :: icart,firstjcart + + ! LOCAL SCALARS + integer :: jcart + double precision :: datom, dtemp, xdiff, tol, & + short_tol, short_tol_scale + + jcart = firstjcart + do while ( jcart .ne. 0 ) + ! + ! Cycle if this type is not to be computed + ! + if ( .not. comptype(ibtype(jcart))) then + jcart = latomnext(jcart) + cycle + end if + ! + ! Cycle if the atoms are from the same molecule + ! + if ( ibmol(icart) == ibmol(jcart) .and. & + ibtype(icart) == ibtype(jcart) ) then + jcart = latomnext(jcart) + cycle + end if + ! + ! Cycle if both atoms are from fixed molecules + ! + if ( fixedatom(icart) .and. fixedatom(jcart) ) then + jcart = latomnext(jcart) + cycle + end if + ! + ! Otherwise, compute distance and evaluate function for this pair + ! + tol = (radius(icart)+radius(jcart))**2 + datom = (xcart(icart, 1)-xcart(jcart, 1))**2 + & + (xcart(icart, 2)-xcart(jcart, 2))**2 + & + (xcart(icart, 3)-xcart(jcart, 3))**2 + if( datom < tol ) then + dtemp = fscale(icart)*fscale(jcart) * 4.d0 * (datom - tol) + xdiff = dtemp*(xcart(icart,1) - xcart(jcart,1)) + gxcar(icart,1)= gxcar(icart,1) + xdiff + gxcar(jcart,1)= gxcar(jcart,1) - xdiff + xdiff = dtemp*(xcart(icart,2) - xcart(jcart,2)) + gxcar(icart,2)= gxcar(icart,2) + xdiff + gxcar(jcart,2)= gxcar(jcart,2) - xdiff + xdiff = dtemp*(xcart(icart,3) - xcart(jcart,3)) + gxcar(icart,3)= gxcar(icart,3) + xdiff + gxcar(jcart,3)= gxcar(jcart,3) - xdiff + if ( use_short_radius(icart) .or. use_short_radius(jcart) ) then + short_tol = ( short_radius(icart) + short_radius(jcart) )**2 + if ( datom < short_tol ) then + short_tol_scale = dsqrt(short_radius_scale(icart)*short_radius_scale(jcart)) + short_tol_scale = short_tol_scale*( tol**2 / short_tol**2 ) + dtemp = fscale(icart)*fscale(jcart) * 4.d0 * short_tol_scale*(datom - short_tol) + xdiff = dtemp*(xcart(icart,1) - xcart(jcart,1)) + gxcar(icart,1)= gxcar(icart,1) + xdiff + gxcar(jcart,1)= gxcar(jcart,1) - xdiff + xdiff = dtemp*(xcart(icart,2) - xcart(jcart,2)) + gxcar(icart,2)= gxcar(icart,2) + xdiff + gxcar(jcart,2)= gxcar(jcart,2) - xdiff + xdiff = dtemp*(xcart(icart,3) - xcart(jcart,3)) + gxcar(icart,3)= gxcar(icart,3) + xdiff + gxcar(jcart,3)= gxcar(jcart,3) - xdiff + end if + end if + end if + jcart = latomnext(jcart) + end do + return +end subroutine gparc + diff --git a/tests/packmol/gwalls.f90 b/tests/packmol/gwalls.f90 new file mode 100644 index 00000000..9b632b4e --- /dev/null +++ b/tests/packmol/gwalls.f90 @@ -0,0 +1,264 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Gradient relative to restraints +! + +subroutine gwalls(icart,irest) + + use sizes + use compute_data + + implicit none + integer :: icart, irest + double precision :: a1, a2, a3, a4, a5, a6, xmin, ymin, zmin, & + xmax, ymax, zmax, & + clength, b1, b2, b3, c1, c2, w, d, rg(3), & + vnorm, vv1, vv2, vv3, frab, frac, frbc, & + dfra(3), dfrb(3), dfrc(3) + + if(ityperest(irest).eq.2) then + clength = restpars(irest,4) + xmin = restpars(irest,1) + ymin = restpars(irest,2) + zmin = restpars(irest,3) + xmax = restpars(irest,1) + clength + ymax = restpars(irest,2) + clength + zmax = restpars(irest,3) + clength + a1 = xcart(icart,1) - xmin + a2 = xcart(icart,2) - ymin + a3 = xcart(icart,3) - zmin + if(a1.lt.0.d0) gxcar(icart,1) = gxcar(icart,1) + scale * 2.d0 * a1 + if(a2.lt.0.d0) gxcar(icart,2) = gxcar(icart,2) + scale * 2.d0 * a2 + if(a3.lt.0.d0) gxcar(icart,3) = gxcar(icart,3) + scale * 2.d0 * a3 + a1 = xcart(icart,1) - xmax + a2 = xcart(icart,2) - ymax + a3 = xcart(icart,3) - zmax + if(a1.gt.0.d0) gxcar(icart,1) = gxcar(icart,1) + scale * 2.d0 * a1 + if(a2.gt.0.d0) gxcar(icart,2) = gxcar(icart,2) + scale * 2.d0 * a2 + if(a3.gt.0.d0) gxcar(icart,3) = gxcar(icart,3) + scale * 2.d0 * a3 + else if(ityperest(irest).eq.3) then + xmin = restpars(irest,1) + ymin = restpars(irest,2) + zmin = restpars(irest,3) + xmax = restpars(irest,4) + ymax = restpars(irest,5) + zmax = restpars(irest,6) + a1 = xcart(icart,1) - xmin + a2 = xcart(icart,2) - ymin + a3 = xcart(icart,3) - zmin + if(a1.lt.0.d0) gxcar(icart,1) = gxcar(icart,1) + scale * 2.d0 * a1 + if(a2.lt.0.d0) gxcar(icart,2) = gxcar(icart,2) + scale * 2.d0 * a2 + if(a3.lt.0.d0) gxcar(icart,3) = gxcar(icart,3) + scale * 2.d0 * a3 + a1 = xcart(icart,1) - xmax + a2 = xcart(icart,2) - ymax + a3 = xcart(icart,3) - zmax + if(a1.gt.0.d0) gxcar(icart,1) = gxcar(icart,1) + scale * 2.d0 * a1 + if(a2.gt.0.d0) gxcar(icart,2) = gxcar(icart,2) + scale * 2.d0 * a2 + if(a3.gt.0.d0) gxcar(icart,3) = gxcar(icart,3) + scale * 2.d0 * a3 + else if(ityperest(irest).eq.4) then + d = (xcart(icart,1)-restpars(irest,1))**2 + & + (xcart(icart,2)-restpars(irest,2))**2 + & + (xcart(icart,3)-restpars(irest,3))**2 - & + restpars(irest,4)**2 + if(d.gt.0.d0) then + gxcar(icart,1) = gxcar(icart,1) + 4.d0 * scale2 * & + (xcart(icart,1)-restpars(irest,1))*d + gxcar(icart,2) = gxcar(icart,2) + 4.d0 * scale2 * & + (xcart(icart,2)-restpars(irest,2))*d + gxcar(icart,3) = gxcar(icart,3) + 4.d0 * scale2 * & + (xcart(icart,3)-restpars(irest,3))*d + end if + else if(ityperest(irest).eq.5) then + a1 = xcart(icart,1)-restpars(irest,1) + b1 = xcart(icart,2)-restpars(irest,2) + c1 = xcart(icart,3)-restpars(irest,3) + a2 = restpars(irest,4)**2 + b2 = restpars(irest,5)**2 + c2 = restpars(irest,6)**2 + d = a1**2/a2+b1**2/b2+c1**2/c2-restpars(irest,7)**2 + if(d.gt.0) then + gxcar(icart,1) = gxcar(icart,1) + scale2*4.d0*d*a1/a2 + gxcar(icart,2) = gxcar(icart,2) + scale2*4.d0*d*b1/b2 + gxcar(icart,3) = gxcar(icart,3) + scale2*4.d0*d*c1/c2 + end if + else if(ityperest(irest).eq.6) then + xmin = restpars(irest,1) + ymin = restpars(irest,2) + zmin = restpars(irest,3) + xmax = restpars(irest,1) + restpars(irest,4) + ymax = restpars(irest,2) + restpars(irest,4) + zmax = restpars(irest,3) + restpars(irest,4) + a1 = dmax1(xcart(icart,1) - xmin,0.d0) + a2 = dmax1(xcart(icart,2) - ymin,0.d0) + a3 = dmax1(xcart(icart,3) - zmin,0.d0) + a4 = dmax1(xmax - xcart(icart,1),0.d0) + a5 = dmax1(ymax - xcart(icart,2),0.d0) + a6 = dmax1(zmax - xcart(icart,3),0.d0) + w = a1*a2*a3*a4*a5*a6 + if(w.gt.0.d0) then + gxcar(icart,1) = gxcar(icart,1) + a2*a3*a5*a6*(a4-a1) + gxcar(icart,2) = gxcar(icart,2) + a1*a3*a4*a6*(a5-a2) + gxcar(icart,3) = gxcar(icart,3) + a1*a2*a4*a5*(a6-a3) + end if + else if(ityperest(irest).eq.7) then + xmin = restpars(irest,1) + ymin = restpars(irest,2) + zmin = restpars(irest,3) + xmax = restpars(irest,4) + ymax = restpars(irest,5) + zmax = restpars(irest,6) + a1 = dmax1(xcart(icart,1) - xmin,0.d0) + a2 = dmax1(xcart(icart,2) - ymin,0.d0) + a3 = dmax1(xcart(icart,3) - zmin,0.d0) + a4 = dmax1(xmax - xcart(icart,1),0.d0) + a5 = dmax1(ymax - xcart(icart,2),0.d0) + a6 = dmax1(zmax - xcart(icart,3),0.d0) + w = a1*a2*a3*a4*a5*a6 + if(w.gt.0.d0) then + gxcar(icart,1) = gxcar(icart,1) + a2*a3*a5*a6*(a4-a1) + gxcar(icart,2) = gxcar(icart,2) + a1*a3*a4*a6*(a5-a2) + gxcar(icart,3) = gxcar(icart,3) + a1*a2*a4*a5*(a6-a3) + end if + else if(ityperest(irest).eq.8) then + d = (xcart(icart,1)-restpars(irest,1))**2 + & + (xcart(icart,2)-restpars(irest,2))**2 + & + (xcart(icart,3)-restpars(irest,3))**2 - & + restpars(irest,4)**2 + if(d.lt.0.d0) then + gxcar(icart,1) = gxcar(icart,1) + 4.d0 * scale2 * & + (xcart(icart,1)-restpars(irest,1))*d + gxcar(icart,2) = gxcar(icart,2) + 4.d0 * scale2 * & + (xcart(icart,2)-restpars(irest,2))*d + gxcar(icart,3) = gxcar(icart,3) + 4.d0 * scale2 * & + (xcart(icart,3)-restpars(irest,3))*d + end if + else if(ityperest(irest).eq.9) then + a1 = xcart(icart,1)-restpars(irest,1) + b1 = xcart(icart,2)-restpars(irest,2) + c1 = xcart(icart,3)-restpars(irest,3) + a2 = restpars(irest,4)**2 + b2 = restpars(irest,5)**2 + c2 = restpars(irest,6)**2 + d = a1**2/a2+b1**2/b2+c1**2/c2-restpars(irest,7)**2 + if(d.lt.0) then + d = scale2 * d + gxcar(icart,1) = gxcar(icart,1) + 4.d0*d*a1/a2 + gxcar(icart,2) = gxcar(icart,2) + 4.d0*d*b1/b2 + gxcar(icart,3) = gxcar(icart,3) + 4.d0*d*c1/c2 + end if + else if(ityperest(irest).eq.10) then + d = restpars(irest,1)*xcart(icart,1) + & + restpars(irest,2)*xcart(icart,2) + & + restpars(irest,3)*xcart(icart,3) - & + restpars(irest,4) + if(d.lt.0.d0) then + d = scale * d + gxcar(icart,1) = gxcar(icart,1) + 2.d0*restpars(irest,1)*d + gxcar(icart,2) = gxcar(icart,2) + 2.d0*restpars(irest,2)*d + gxcar(icart,3) = gxcar(icart,3) + 2.d0*restpars(irest,3)*d + end if + else if(ityperest(irest).eq.11) then + d = restpars(irest,1)*xcart(icart,1) + & + restpars(irest,2)*xcart(icart,2) + & + restpars(irest,3)*xcart(icart,3) - & + restpars(irest,4) + if(d.gt.0.d0) then + d = scale * d + gxcar(icart,1) = gxcar(icart,1) + 2.d0*restpars(irest,1)*d + gxcar(icart,2) = gxcar(icart,2) + 2.d0*restpars(irest,2)*d + gxcar(icart,3) = gxcar(icart,3) + 2.d0*restpars(irest,3)*d + end if + else if(ityperest(irest).eq.12) then + rg(1) = 0.0d0 + rg(2) = 0.0d0 + rg(3) = 0.0d0 + a1 = xcart(icart,1) - restpars(irest,1) + a2 = xcart(icart,2) - restpars(irest,2) + a3 = xcart(icart,3) - restpars(irest,3) + vnorm = sqrt(restpars(irest,4)**2 + restpars(irest,5)**2 & + + restpars(irest,6)**2) + vv1 = restpars(irest,4)/vnorm + vv2 = restpars(irest,5)/vnorm + vv3 = restpars(irest,6)/vnorm + b1 = vv1 * a1 + b2 = vv2 * a2 + b3 = vv3 * a3 + w = b1 + b2 + b3 + d = (a1 - vv1*w)**2 + (a2 - vv2*w)**2 + (a3 - vv3*w)**2 + rg(1) = scale2 * ( & + -2*dmax1(-w , 0.d0) * vv1 + & + 2*dmax1(w - restpars(irest,9), 0.d0) * vv1 + & + 2*dmax1(d - restpars(irest,7)**2 , 0.d0) * & + (2*(a1 - vv1*w)*(1 - vv1**2)+ & + 2*(a2 - vv2*w)*(-vv2*vv1)+ & + 2*(a3 - vv3*w)*(-vv3*vv1) )) + rg(2) = scale2 * ( & + -2*dmax1(-w , 0.d0) * vv2 + & + 2*dmax1(w - restpars(irest,9), 0.d0) * vv2 + & + 2*dmax1(d - restpars(irest,7)**2 , 0.d0) * & + (2*(a1 - vv1*w)*(-vv1*vv2)+ & + 2*(a2 - vv2*w)*(1 - vv2**2)+ & + 2*(a3 - vv3*w)*(-vv3*vv2) )) + rg(3) = scale2 * ( & + -2*dmax1(-w , 0.d0) * vv3 + & + 2*dmax1(w - restpars(irest,9), 0.d0) * vv3 + & + 2*dmax1(d - restpars(irest,7)**2 , 0.d0) * & + (2*(a1 - vv1*w)*(-vv1*vv3)+ & + 2*(a2 - vv2*w)*(-vv2*vv3)+ & + 2*(a3 - vv3*w)*(1 - vv3**2) )) + gxcar(icart,1) = gxcar(icart,1) + rg(1) + gxcar(icart,2) = gxcar(icart,2) + rg(2) + gxcar(icart,3) = gxcar(icart,3) + rg(3) + else if(ityperest(irest).eq.13) then + rg(1) = 0.0d0 + rg(2) = 0.0d0 + rg(3) = 0.0d0 + a1 = xcart(icart,1) - restpars(irest,1) + a2 = xcart(icart,2) - restpars(irest,2) + a3 = xcart(icart,3) - restpars(irest,3) + vnorm = sqrt(restpars(irest,4)**2 + restpars(irest,5)**2 & + + restpars(irest,6)**2) + vv1 = restpars(irest,4)/vnorm + vv2 = restpars(irest,5)/vnorm + vv3 = restpars(irest,6)/vnorm + b1 = vv1 * a1 + b2 = vv2 * a2 + b3 = vv3 * a3 + w = b1 + b2 + b3 + d = (a1 - vv1*w)**2 + (a2 - vv2*w)**2 + (a3 - vv3*w)**2 + frab = dmin1(-w , 0.d0)**2 * dmin1(w - restpars(irest,9), 0.d0)**2 + frac = dmin1(-w , 0.d0)**2 * dmin1(d - restpars(irest,7)**2 , 0.d0 )**2 + frbc = dmin1(w - restpars(irest,9), 0.d0)**2 * & + dmin1(d - restpars(irest,7)**2 , 0.d0 )**2 + dfra(1) = -2*dmin1(-w , 0.d0) * vv1 + dfrb(1) = 2*dmin1(w - restpars(irest,9), 0.d0) * vv1 + dfrc(1) = 2*dmin1(d - restpars(irest,7)**2 , 0.d0) * & + (2*(a1 - vv1*w)*(1 - vv1**2)+ & + 2*(a2 - vv2*w)*(-vv2*vv1)+ & + 2*(a3 - vv3*w)*(-vv3*vv1) ) + dfra(2) = -2*dmin1(-w , 0.d0) * vv2 + dfrb(2) = 2*dmin1(w - restpars(irest,9), 0.d0) * vv2 + dfrc(2) = 2*dmin1(d - restpars(irest,7)**2 , 0.d0) * & + (2*(a1 - vv1*w)*(-vv1*vv2)+ & + 2*(a2 - vv2*w)*(1 - vv2**2)+ & + 2*(a3 - vv3*w)*(-vv3*vv2) ) + dfra(3) = -2*dmin1(-w , 0.d0) * vv3 + dfrb(3) = 2*dmin1(w - restpars(irest,9), 0.d0) * vv3 + dfrc(3) = 2*dmin1(d - restpars(irest,7)**2 , 0.d0) * & + (2*(a1 - vv1*w)*(-vv1*vv3)+ & + 2*(a2 - vv2*w)*(-vv2*vv3)+ & + 2*(a3 - vv3*w)*(1 - vv3**2) ) + rg(1) = scale2 * ( dfra(1)*frbc + dfrb(1)*frac + dfrc(1)*frab) + rg(2) = scale2 * ( dfra(2)*frbc + dfrb(2)*frac + dfrc(2)*frab) + rg(3) = scale2 * ( dfra(3)*frbc + dfrb(3)*frac + dfrc(3)*frab) + gxcar(icart,1) = gxcar(icart,1) + rg(1) + gxcar(icart,2) = gxcar(icart,2) + rg(2) + gxcar(icart,3) = gxcar(icart,3) + rg(3) + end if + + return +end subroutine gwalls + diff --git a/tests/packmol/header b/tests/packmol/header new file mode 100644 index 00000000..b6f595f2 --- /dev/null +++ b/tests/packmol/header @@ -0,0 +1,5 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2011, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! diff --git a/tests/packmol/heuristics.f90 b/tests/packmol/heuristics.f90 new file mode 100644 index 00000000..02d2280e --- /dev/null +++ b/tests/packmol/heuristics.f90 @@ -0,0 +1,151 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! subroutine movebad: Move the worse molecules to new positions +! + +subroutine movebad(n,x,fx,movebadprint) + + use sizes + use compute_data + use input, only : movefrac, movebadrandom, precision, maxmove + use usegencan + use flashsort + use ahestetic + implicit none + + ! Internal variables + integer :: n, i, j, icart, itype, iatom, imol, ilubar, ilugan, & + ilubar2, ilugan2, nbad, igood, ibad, nmove + double precision :: x(n), fx, rnd, frac + double precision :: fdist_mol, frest_mol + logical :: movebadprint, hasbad + + if(movebadprint) write(*,*) ' Moving worst molecules ... ' + + icart = 0 + do itype = 1, ntype + if(.not.comptype(itype)) then + icart = icart + nmols(itype)*natoms(itype) + else + do imol = 1, nmols(itype) + do iatom = 1, natoms(itype) + icart = icart + 1 + fdist_atom(icart) = 0.d0 + frest_atom(icart) = 0.d0 + end do + end do + end if + end do + + move = .true. + if(movebadprint) write(*,*) ' Function value before moving molecules:',fx + do i = 1, ntotat + radiuswork(i) = radius(i) + radius(i) = radius_ini(i) + end do + call computef(n,x,fx) + move = .false. + + ! Moving the worst molecules + + hasbad = .false. + icart = 0 + do itype = 1, ntype + if(.not.comptype(itype)) then + icart = icart + nmols(itype)*natoms(itype) + else + + ! Checking the function value for each molecule + + nbad = 0 + do imol = 1, nmols(itype) + fdist_mol = 0.d0 + frest_mol = 0.d0 + do iatom = 1, natoms(itype) + icart = icart + 1 + fdist_mol = dmax1(fdist_mol,fdist_atom(icart)) + frest_mol = dmax1(frest_mol,frest_atom(icart)) + end do + if(fdist_mol > precision .or. & + frest_mol > precision ) then + hasbad = .true. + nbad = nbad + 1 + fmol(imol) = fdist_mol + frest_mol + else + fmol(imol) = 0.d0 + end if + end do + frac = dfloat(nbad)/dfloat(nmols(itype)) + if(movebadprint) write(*,"( a,i9,a,f8.2,a )") & + ' Type ',itype,' molecules with non-zero contributions:', & + 100.d0*frac,'%' + + if(nbad.gt.0) then + + frac = dmin1(movefrac,frac) + + ! Ordering molecules from best to worst + + mflash = 1 + nmols(itype)/10 + call flash1(fmol,nmols(itype),lflash,mflash,indflash) + + ! Moving molecules + + nmove = min0(maxmove(itype),max0(int(nmols(itype)*frac),1)) + if(movebadprint) then + write(*,"( a,i9,a,i9 )") ' Moving ',nmove,' molecules of type ',itype + if ( movebadrandom ) then + write(*,*) ' New positions will be aleatory (movebadrandom is set) ' + else + write(*,*) ' New positions will be based on good molecules (movebadrandom is not set) ' + end if + end if + imol = 0 + do i = 1, itype - 1 + if(comptype(i)) imol = imol + nmols(i) + end do + write(*,prog2_line) + write(*,"( ' |',$)") + j = 0 + do i = 1, nmove + ibad = nmols(itype) - i + 1 + igood = int(rnd()*nmols(itype)*frac) + 1 + ilubar = 3*(indflash(ibad)+imol-1) + ilugan = 3*(indflash(ibad)+imol-1)+3*ntotmol + ilubar2 = 3*(indflash(igood)+imol-1) + ilugan2 = 3*(indflash(igood)+imol-1)+3*ntotmol + if ( movebadrandom ) then + x(ilubar+1) = sizemin(1) + rnd()*(sizemax(1)-sizemin(1)) + x(ilubar+2) = sizemin(2) + rnd()*(sizemax(2)-sizemin(2)) + x(ilubar+3) = sizemin(3) + rnd()*(sizemax(3)-sizemin(3)) + else + x(ilubar+1) = x(ilubar2+1) - 0.3*dmax(itype)+0.6*rnd()*dmax(itype) + x(ilubar+2) = x(ilubar2+2) - 0.3*dmax(itype)+0.6*rnd()*dmax(itype) + x(ilubar+3) = x(ilubar2+3) - 0.3*dmax(itype)+0.6*rnd()*dmax(itype) + end if + x(ilugan+1) = x(ilugan2+1) + x(ilugan+2) = x(ilugan2+2) + x(ilugan+3) = x(ilugan2+3) + call restmol(itype,ilubar,n,x,fx,.true.) + do while( j <= 65.d0*i/nmove ) + write(*,"('*',$)") + j = j + 1 + end do + end do + write(*,"('|')") + end if + end if + end do + + call computef(n,x,fx) + if(movebadprint) write(*,*) ' Function value after moving molecules:', fx + do i = 1, ntotat + radius(i) = radiuswork(i) + end do + + return +end subroutine movebad + diff --git a/tests/packmol/initial.f90 b/tests/packmol/initial.f90 new file mode 100644 index 00000000..5055de51 --- /dev/null +++ b/tests/packmol/initial.f90 @@ -0,0 +1,590 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Subroutine initial: Subroutine that reset parameters and +! builds the initial point +! + +subroutine initial(n,x) + + use sizes + use compute_data + use input, only : randini, ntfix, fix, moldy, chkgrad, avoidoverlap,& + discale, precision, sidemax, restart_from, input_itype,& + nloop0_type + use usegencan + use ahestetic + implicit none + integer :: n, i, j, k, idatom, iatom, ilubar, ilugan, icart, itype, & + imol, ntry, nb, iboxx, iboxy, iboxz, ifatom, & + idfatom, iftype, jatom, ioerr + + double precision :: x(n), cmx, cmy, beta, gamma, theta, & + cmz, fx, xlength, dbox, rnd, & + radmax, v1(3), v2(3), v3(3), xbar, ybar, zbar + double precision, parameter :: twopi = 8.d0*datan(1.d0) + + logical :: overlap, movebadprint, hasbad + logical, allocatable :: hasfixed(:,:,:) + + character(len=strl) :: record + + ! Allocate hasfixed array + + allocate(hasfixed(0:nbp+1,0:nbp+1,0:nbp+1)) + + ! We need to initialize the move logical variable + + move = .false. + + ! Default status of the function evaluation + + init1 = .false. + + ! Initialize the comptype logical array + + do i = 1, ntfix + comptype(i) = .true. + end do + + ! Penalty factors for the objective function relative to restrictions + ! Default values: scale = 1.d2, scale2 = 1.d1 + + scale = 1.d0 + scale2 = 1.d-2 + + ! Move molecules to their center of mass (not for moldy) + if(.not.moldy) call tobar() + + ! Compute maximum internal distance within each type of molecule + + do itype = 1, ntype + dmax(itype) = 0.d0 + idatom = idfirst(itype) - 1 + do iatom = 1, natoms(itype) - 1 + do jatom = iatom + 1, natoms(itype) + dmax(itype) = dmax1 ( dmax(itype),& + (coor(idatom+iatom,1)-coor(idatom+jatom,1))**2+& + (coor(idatom+iatom,2)-coor(idatom+jatom,2))**2+& + (coor(idatom+iatom,3)-coor(idatom+jatom,3))**2 ) + end do + end do + dmax(itype) = dsqrt(dmax(itype)) + write(*,*) ' Maximum internal distance of type ',itype,': ',& + dmax(itype) + if(dmax(itype).eq.0.) dmax(itype) = 1.d0 + end do + + ! Maximum size of the system: if you system is very large (about + ! 80 nm wide), increase the sidemax parameter. + ! Otherwise, the packing can be slow and unsucesful + + cmxmin(1) = -sidemax + cmymin(1) = -sidemax + cmzmin(1) = -sidemax + cmxmax(1) = sidemax + cmymax(1) = sidemax + cmzmax(1) = sidemax + do i = 1, 3 + x(i) = 0.d0 + x(i+ntotmol*3) = 0.d0 + end do + call restmol(1,0,n,x,fx,.true.) + sizemin(1) = x(1) - sidemax + sizemax(1) = x(1) + sidemax + sizemin(2) = x(2) - sidemax + sizemax(2) = x(2) + sidemax + sizemin(3) = x(3) - sidemax + sizemax(3) = x(3) + sidemax + write(*,*) ' All atoms must be within these coordinates: ' + write(*,*) ' x: [ ', sizemin(1),', ', sizemax(1), ' ] ' + write(*,*) ' y: [ ', sizemin(2),', ', sizemax(2), ' ] ' + write(*,*) ' z: [ ', sizemin(3),', ', sizemax(3), ' ] ' + write(*,*) ' If the system is larger than this, increase the sidemax parameter. ' + + ! Create first aleatory guess + + i = 0 + j = ntotmol*3 + do itype = 1, ntype + do imol = 1, nmols(itype) + x(i+1) = sizemin(1) + rnd()*(sizemax(1)-sizemin(1)) + x(i+2) = sizemin(2) + rnd()*(sizemax(2)-sizemin(2)) + x(i+3) = sizemin(3) + rnd()*(sizemax(3)-sizemin(3)) + if ( constrain_rot(itype,1) ) then + x(j+1) = ( rot_bound(itype,1,1) - dabs(rot_bound(itype,1,2)) ) + & + 2.d0*rnd()*dabs(rot_bound(itype,1,2)) + else + x(j+1) = twopi*rnd() + end if + if ( constrain_rot(itype,2) ) then + x(j+2) = ( rot_bound(itype,2,1) - dabs(rot_bound(itype,2,2)) ) + & + 2.d0*rnd()*dabs(rot_bound(itype,2,2)) + else + x(j+2) = twopi*rnd() + end if + if ( constrain_rot(itype,3) ) then + x(j+3) = ( rot_bound(itype,3,1) - dabs(rot_bound(itype,3,2)) ) + & + 2.d0*rnd()*dabs(rot_bound(itype,3,2)) + else + x(j+3) = twopi*rnd() + end if + i = i + 3 + j = j + 3 + end do + end do + + ! Initialize cartesian coordinate array for the first time + + ilubar = 0 + ilugan = ntotmol*3 + icart = 0 + do itype = 1, ntype + do imol = 1, nmols(itype) + xbar = x(ilubar+1) + ybar = x(ilubar+2) + zbar = x(ilubar+3) + beta = x(ilugan+1) + gamma = x(ilugan+2) + theta = x(ilugan+3) + call eulerrmat(beta,gamma,theta,v1,v2,v3) + idatom = idfirst(itype) - 1 + do iatom = 1, natoms(itype) + icart = icart + 1 + idatom = idatom + 1 + call compcart(icart,xbar,ybar,zbar,& + coor(idatom,1),coor(idatom,2),coor(idatom,3),& + v1,v2,v3) + fixedatom(icart) = .false. + end do + end do + end do + if(fix) then + icart = ntotat - natfix + do iftype = ntype + 1, ntfix + idfatom = idfirst(iftype) - 1 + do ifatom = 1, natoms(iftype) + idfatom = idfatom + 1 + icart = icart + 1 + xcart(icart,1) = coor(idfatom,1) + xcart(icart,2) = coor(idfatom,2) + xcart(icart,3) = coor(idfatom,3) + fixedatom(icart) = .true. + end do + end do + end if + + ! Use the largest radius as the reference for binning the box + + radmax = 0.d0 + do i = 1, ntotat + radmax = dmax1(radmax,2.d0*radius(i)) + end do + + ! Performing some steps of optimization for the restrictions only + + write(*,hash3_line) + write(*,"(' Building initial approximation ... ' )") + write(*,hash3_line) + write(*,"(' Adjusting initial point to fit the constraints ')") + write(*,dash2_line) + init1 = .true. + call swaptype(n,x,itype,0) ! Initialize swap arrays + itype = 0 + do while( itype <= ntype ) + itype = itype + 1 + if ( itype <= ntype ) then + call swaptype(n,x,itype,1) ! Set arrays for this type + else + call swaptype(n,x,itype,3) ! Restore arrays if itype = ntype + 1 + exit + end if + write(*,dash3_line) + write(*,*) ' Molecules of type: ', input_itype(itype) + write(*,*) + i = 0 + hasbad = .true. + call computef(n,x,fx) + do while( frest > precision .and. i.le. nloop0_type(itype)-1 .and. hasbad) + i = i + 1 + write(*,prog1_line) + call pgencan(n,x,fx) + call computef(n,x,fx) + if(frest > precision) then + write(*,"( a,i6,a,i6 )")' Fixing bad orientations ... ', i,' of ', nloop0_type(itype) + movebadprint = .true. + call movebad(n,x,fx,movebadprint) + end if + end do + write(*,*) + write(*,*) ' Restraint-only function value: ', fx + write(*,*) ' Maximum violation of the restraints: ', frest + call swaptype(n,x,itype,2) ! Save current type results + + if( hasbad .and. frest > precision ) then + write(*,*) ' ERROR: Packmol was unable to put the molecules' + write(*,*) ' in the desired regions even without' + write(*,*) ' considering distance tolerances. ' + write(*,*) ' Probably there is something wrong with' + write(*,*) ' the constraints, since it seems that' + write(*,*) ' the molecules cannot satisfy them at' + write(*,*) ' at all. ' + write(*,*) ' Please check the spatial constraints and' + write(*,*) ' try again.' + if ( i .ge. nloop0_type(itype)-1 ) then + end if + write(*,*) ' >The maximum number of cycles (',nloop0_type(itype),') was achieved.' + write(*,*) ' You may try increasing it with the',' nloop0 keyword, as in: nloop0 1000 ' + stop + end if + end do + init1 = .false. + + ! Rescaling sizemin and sizemax in order to build the patch of boxes + + write(*,dash3_line) + write(*,*) ' Rescaling maximum and minimum coordinates... ' + do i = 1, 3 + sizemin(i) = 1.d20 + sizemax(i) = -1.d20 + end do + + icart = 0 + do itype = 1, ntfix + do imol = 1, nmols(itype) + do iatom = 1, natoms(itype) + icart = icart + 1 + sizemin(1) = dmin1(sizemin(1),xcart(icart,1)) + sizemin(2) = dmin1(sizemin(2),xcart(icart,2)) + sizemin(3) = dmin1(sizemin(3),xcart(icart,3)) + sizemax(1) = dmax1(sizemax(1),xcart(icart,1)) + sizemax(2) = dmax1(sizemax(2),xcart(icart,2)) + sizemax(3) = dmax1(sizemax(3),xcart(icart,3)) + end do + end do + end do + + ! Computing the size of the patches + + write(*,*) ' Computing size of patches... ' + dbox = discale * radmax + 0.01d0 * radmax + do i = 1, 3 + xlength = sizemax(i) - sizemin(i) + nb = int(xlength/dbox + 1.d0) + if(nb.gt.nbp) nb = nbp + boxl(i) = dmax1(xlength/dfloat(nb),dbox) + nboxes(i) = nb + nb2(i) = nboxes(i) + 2 + end do + + ! Reseting latomfix array + + do i = 0, nbp + 1 + do j = 0, nbp + 1 + do k = 0, nbp + 1 + latomfix(i,j,k) = 0 + latomfirst(i,j,k) = 0 + hasfixed(i,j,k) = .false. + hasfree(i,j,k) = .false. + end do + end do + end do + + ! If there are fixed molecules, add them permanently to the latomfix array + + write(*,*) ' Add fixed molecules to permanent arrays... ' + if(fix) then + icart = ntotat - natfix + do iftype = ntype + 1, ntfix + idfatom = idfirst(iftype) - 1 + do ifatom = 1, natoms(iftype) + idfatom = idfatom + 1 + icart = icart + 1 + call setibox(xcart(icart,1),xcart(icart,2),xcart(icart,3),& + sizemin,boxl,nboxes,iboxx,iboxy,iboxz) + latomnext(icart) = latomfix(iboxx,iboxy,iboxz) + latomfix(iboxx,iboxy,iboxz) = icart + latomfirst(iboxx,iboxy,iboxz) = icart + ibtype(icart) = iftype + ibmol(icart) = 1 + hasfixed(iboxx,iboxy,iboxz) = .true. + end do + end do + end if + + ! Reseting mass centers to be within the regions + + write(*,*) ' Reseting center of mass... ' + do itype = 1, ntype + cmxmin(itype) = 1.d20 + cmymin(itype) = 1.d20 + cmzmin(itype) = 1.d20 + cmxmax(itype) = -1.d20 + cmymax(itype) = -1.d20 + cmzmax(itype) = -1.d20 + end do + + icart = 0 + do itype = 1, ntype + do imol = 1, nmols(itype) + cmx = 0.d0 + cmy = 0.d0 + cmz = 0.d0 + do iatom = 1, natoms(itype) + icart = icart + 1 + cmx = cmx + xcart(icart,1) + cmy = cmy + xcart(icart,2) + cmz = cmz + xcart(icart,3) + end do + cmx = cmx / dfloat(natoms(itype)) + cmy = cmy / dfloat(natoms(itype)) + cmz = cmz / dfloat(natoms(itype)) + cmxmin(itype) = dmin1(cmxmin(itype),cmx) + cmymin(itype) = dmin1(cmymin(itype),cmy) + cmzmin(itype) = dmin1(cmzmin(itype),cmz) + cmxmax(itype) = dmax1(cmxmax(itype),cmx) + cmymax(itype) = dmax1(cmymax(itype),cmy) + cmzmax(itype) = dmax1(cmzmax(itype),cmz) + end do + end do + + ! If there is a restart file for all system, read it + + if ( restart_from(0) /= 'none' ) then + record = restart_from(0) + write(*,*) ' Restarting all system from file: ', trim(adjustl(record)) + open(10,file=restart_from(0),status='old',action='read',iostat=ioerr) + ilubar = 0 + ilugan = ntotmol*3 + do i = 1, ntotmol + read(10,*,iostat=ioerr) x(ilubar+1), x(ilubar+2), x(ilubar+3), & + x(ilugan+1), x(ilugan+2), x(ilugan+3) + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Could not read restart file: ', trim(adjustl(record)) + stop + end if + ilubar = ilubar + 3 + ilugan = ilugan + 3 + end do + close(10) + return + end if + + ! Building random initial point + + write(*,dash3_line) + write(*,*) ' Setting initial trial coordinates ... ' + write(*,dash2_line) + + if ( chkgrad ) then + write(*,*) ' For checking gradient, will set avoidoverlap to false. ' + avoidoverlap = .false. + end if + + ! Setting random center of mass coordinates, within size limits + + ilubar = 0 + do itype = 1, ntype + if ( restart_from(itype) /= 'none' ) then + ilubar = ilubar + nmols(itype)*3 + cycle + end if + do imol = 1, nmols(itype) + if ( .not. avoidoverlap ) then + fx = 1.d0 + ntry = 0 + do while((fx.gt.precision).and.ntry.le.20) + ntry = ntry + 1 + x(ilubar+1) = cmxmin(itype) + rnd()*(cmxmax(itype)-cmxmin(itype)) + x(ilubar+2) = cmymin(itype) + rnd()*(cmymax(itype)-cmymin(itype)) + x(ilubar+3) = cmzmin(itype) + rnd()*(cmzmax(itype)-cmzmin(itype)) + call restmol(itype,ilubar,n,x,fx,.false.) + end do + else + fx = 1.d0 + ntry = 0 + overlap = .false. + do while((overlap.or.fx.gt.precision).and.ntry.le.20) + ntry = ntry + 1 + x(ilubar+1) = cmxmin(itype) + rnd()*(cmxmax(itype)-cmxmin(itype)) + x(ilubar+2) = cmymin(itype) + rnd()*(cmymax(itype)-cmymin(itype)) + x(ilubar+3) = cmzmin(itype) + rnd()*(cmzmax(itype)-cmzmin(itype)) + if(fix) then + call setibox(x(ilubar+1),x(ilubar+2),x(ilubar+3),& + sizemin,boxl,nboxes,iboxx,iboxy,iboxz) + if(hasfixed(iboxx, iboxy, iboxz ).or.& + hasfixed(iboxx+1,iboxy, iboxz ).or.& + hasfixed(iboxx, iboxy+1,iboxz ).or.& + hasfixed(iboxx, iboxy, iboxz+1).or.& + hasfixed(iboxx-1,iboxy, iboxz ).or.& + hasfixed(iboxx, iboxy-1,iboxz ).or.& + hasfixed(iboxx, iboxy, iboxz-1).or.& + hasfixed(iboxx+1,iboxy+1,iboxz ).or.& + hasfixed(iboxx+1,iboxy, iboxz+1).or.& + hasfixed(iboxx+1,iboxy-1,iboxz ).or.& + hasfixed(iboxx+1,iboxy, iboxz-1).or.& + hasfixed(iboxx, iboxy+1,iboxz+1).or.& + hasfixed(iboxx, iboxy+1,iboxz-1).or.& + hasfixed(iboxx, iboxy-1,iboxz+1).or.& + hasfixed(iboxx, iboxy-1,iboxz-1).or.& + hasfixed(iboxx-1,iboxy+1,iboxz ).or.& + hasfixed(iboxx-1,iboxy, iboxz+1).or.& + hasfixed(iboxx-1,iboxy-1,iboxz ).or.& + hasfixed(iboxx-1,iboxy, iboxz-1).or.& + hasfixed(iboxx+1,iboxy+1,iboxz+1).or.& + hasfixed(iboxx+1,iboxy+1,iboxz-1).or.& + hasfixed(iboxx+1,iboxy-1,iboxz+1).or.& + hasfixed(iboxx+1,iboxy-1,iboxz-1).or.& + hasfixed(iboxx-1,iboxy+1,iboxz+1).or.& + hasfixed(iboxx-1,iboxy+1,iboxz-1).or.& + hasfixed(iboxx-1,iboxy-1,iboxz+1).or.& + hasfixed(iboxx-1,iboxy-1,iboxz-1)) then + overlap = .true. + else + overlap = .false. + end if + end if + if(.not.overlap) call restmol(itype,ilubar,n,x,fx,.false.) + end do + end if + ilubar = ilubar + 3 + end do + end do + + ! Setting random angles, except if the rotations were constrained + + ilugan = ntotmol*3 + do itype = 1, ntype + if ( restart_from(itype) /= 'none' ) then + ilugan = ilugan + nmols(itype)*3 + cycle + end if + do imol = 1, nmols(itype) + if ( constrain_rot(itype,1) ) then + x(ilugan+1) = ( rot_bound(itype,1,1) - dabs(rot_bound(itype,1,2)) ) + & + 2.d0*rnd()*dabs(rot_bound(itype,1,2)) + else + x(ilugan+1) = twopi*rnd() + end if + if ( constrain_rot(itype,2) ) then + x(ilugan+2) = ( rot_bound(itype,2,1) - dabs(rot_bound(itype,2,2)) ) + & + 2.d0*rnd()*dabs(rot_bound(itype,2,2)) + else + x(ilugan+2) = twopi*rnd() + end if + if ( constrain_rot(itype,3) ) then + x(ilugan+3) = ( rot_bound(itype,3,1) - dabs(rot_bound(itype,3,2)) ) + & + 2.d0*rnd()*dabs(rot_bound(itype,3,2)) + else + x(ilugan+3) = twopi*rnd() + end if + ilugan = ilugan + 3 + end do + end do + + ! Compare analytical and finite-difference gradients + + if(chkgrad) then + dbox = discale * radmax + 0.01d0 * radmax + do i = 1, 3 + xlength = sizemax(i) - sizemin(i) + nb = int(xlength/dbox + 1.d0) + if(nb.gt.nbp) nb = nbp + boxl(i) = dmax1(xlength/dfloat(nb),dbox) + nboxes(i) = nb + nb2(i) = nboxes(i) + 2 + end do + call comparegrad(n,x) + stop + end if + + ! + ! Reading restart files of specific molecule types, if available + ! + + ilubar = 0 + ilugan = ntotmol*3 + do itype = 1, ntype + if ( restart_from(itype) /= 'none' ) then + record = restart_from(itype) + write(*,dash3_line) + write(*,*) ' Molecules of type: ', input_itype(itype) + write(*,*) ' Will restart coordinates from: ', trim(adjustl(record)) + open(10,file=record,status='old',action='read',iostat=ioerr) + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Could not open restart file: ', trim(adjustl(record)) + stop + end if + do i = 1, nmols(itype) + read(10,*,iostat=ioerr) x(ilubar+1), x(ilubar+2), x(ilubar+3), & + x(ilugan+1), x(ilugan+2), x(ilugan+3) + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Could not read restart file: ', trim(adjustl(record)) + stop + end if + ilubar = ilubar + 3 + ilugan = ilugan + 3 + end do + close(10) + call swaptype(n,x,itype,0) ! Initialize swap arrays + call swaptype(n,x,itype,1) ! Set arrays for this type + call computef(n,x,fx) + write(*,*) ' Maximum violation of the restraints: ', frest + write(*,*) ' Maximum violation of minimum atom distances: ', fdist + call swaptype(n,x,itype,3) ! Restore all-molecule arrays + else + ilubar = ilubar + nmols(itype)*3 + ilugan = ilugan + nmols(itype)*3 + end if + end do + + ! Return with current random point (not default) + + if(randini) return + + ! Adjusting current point to fit the constraints + + init1 = .true. + call swaptype(n,x,itype,0) ! Initialize swap arrays + itype = 0 + do while( itype <= ntype ) + itype = itype + 1 + if ( itype == ntype + 1 ) then + call swaptype(n,x,itype,3) ! Restore arrays for all molecules + exit + end if + if ( restart_from(itype) /= 'none' ) cycle + call swaptype(n,x,itype,1) ! Set arrays for this type + write(*,dash3_line) + write(*,*) ' Molecules of type: ', input_itype(itype) + write(*,*) ' Adjusting random positions to fit the constraints. ' + i = 0 + call computef(n,x,fx) + hasbad = .true. + do while( frest > precision .and. i <= nloop0_type(itype)-1 .and. hasbad) + i = i + 1 + write(*,prog1_line) + call pgencan(n,x,fx) + call computef(n,x,fx) + if(frest > precision) then + write(*,"( a,i6,a,i6 )")' Fixing bad orientations ... ', i,' of ', nloop0_type(itype) + movebadprint = .true. + call movebad(n,x,fx,movebadprint) + end if + end do + write(*,*) ' Restraint-only function value: ', fx + write(*,*) ' Maximum violation of the restraints: ', frest + call swaptype(n,x,itype,2) ! Save results for this type + end do + init1 = .false. + write(*,hash3_line) + + ! Deallocate hasfixed array + + deallocate(hasfixed) + + return +end subroutine initial + diff --git a/tests/packmol/input.f90 b/tests/packmol/input.f90 new file mode 100644 index 00000000..de9135f0 --- /dev/null +++ b/tests/packmol/input.f90 @@ -0,0 +1,80 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Module that carries the input parameters read from the input file +! + +module input + + use sizes + implicit none + + integer :: nlines + integer :: nrest + integer :: seed + integer :: nloop, nloop_all + integer :: writeout + integer :: ntfix + integer :: ntcon(9) + + integer, allocatable :: nconnect(:,:) ! (ntotat,9) + integer, allocatable :: irestline(:) ! (maxrest) + integer, allocatable :: linestrut(:,:) ! (ntype,2) + integer, allocatable :: resnumbers(:) ! (ntype) + integer, allocatable :: maxcon(:) ! (ntotat) + integer, allocatable :: input_itype(:) ! (ntype) + integer, allocatable :: nloop_type(:) ! (ntype) + integer, allocatable :: nloop0_type(:) ! (ntype) + integer, allocatable :: maxmove(:) ! (ntype) + + double precision :: dism + double precision :: precison + double precision :: sidemax + double precision :: discale + double precision :: movefrac + double precision :: add_sides_fix + double precision :: precision + double precision :: fbins + double precision :: short_tol_dist + double precision :: short_tol_scale + + double precision, allocatable :: amass(:) ! (ntotat) + double precision, allocatable :: charge(:) ! (ntotat) + + logical :: writebad + logical :: tinker + logical :: pdb + logical :: crd + logical :: xyz + logical :: moldy + logical :: check + logical :: chkgrad + logical :: randini + logical :: movebadrandom + logical :: add_amber_ter + logical :: add_box_sides + logical :: fix + logical :: avoidoverlap + logical :: packall + logical :: use_short_tol + + logical, allocatable :: changechains(:) ! (ntype) + logical, allocatable :: fixedoninput(:) ! (ntype) + logical, allocatable :: connect(:) ! (ntype) + + character(len=1), parameter :: forbidden_char = '~' + character(len=strl) :: xyzout + character(len=strl) :: crdfile + + character(len=1), allocatable :: chain(:) ! (ntype) + character(len=3), allocatable :: ele(:) ! (ntotat) + character(len=8), allocatable :: segid(:) ! (segment identifier) + character(len=strl), allocatable :: pdbfile(:) ! (ntype) + character(len=strl), allocatable :: name(:) ! (ntype) + character(len=strl), allocatable :: keyword(:,:) ! (nlines,maxkeywords) + character(len=strl), allocatable :: inputfile(:) ! (nlines) + character(len=strl), allocatable :: restart_from(:), restart_to(:) ! (0:ntype) + +end module input diff --git a/tests/packmol/jacobi.f90 b/tests/packmol/jacobi.f90 new file mode 100644 index 00000000..04ef83f3 --- /dev/null +++ b/tests/packmol/jacobi.f90 @@ -0,0 +1,106 @@ +! +! JACOBI +! Jacobi diagonalizer with sorted output. Same calling sequence as +! EISPACK routine, but must specify nrot! +! + SUBROUTINE jacobi (a, n, np, d, v, nrot) + IMPLICIT CHARACTER (A-Z) +! + INTEGER n, np, nrot + DOUBLEPRECISION a (np, n) + DOUBLEPRECISION d (n) + DOUBLEPRECISION v (np, n) +! + DOUBLEPRECISION onorm, dnorm + DOUBLEPRECISION b, dma, q, t, c, s + DOUBLEPRECISION atemp, vtemp, dtemp + INTEGER i, j, k, l +! + DO 10000 j = 1, n + DO 10010 i = 1, n + v (i, j) = 0.0D0 +10010 CONTINUE + v (j, j) = 1.0D0 + d (j) = a (j, j) +10000 CONTINUE +! + DO 20000 l = 1, nrot + dnorm = 0.0D0 + onorm = 0.0D0 + DO 20100 j = 1, n + dnorm = dnorm + ABS (d (j)) + DO 20110 i = 1, j - 1 + onorm = onorm + ABS (a (i, j)) +20110 CONTINUE +20100 CONTINUE + IF (onorm / dnorm .LE. 0.0D0) GOTO 19999 + DO 21000 j = 2, n + DO 21010 i = 1, j - 1 + b = a (i, j) + IF (ABS (b) .GT. 0.0D0) THEN + dma = d (j) - d (i) + IF (ABS (dma) + ABS (b) .LE. ABS (dma)) THEN + t = b / dma + ELSE + q = 0.5D0 * dma / b + t = SIGN (1.0D0 / (ABS (q) + SQRT (1.0D0 + q * q)), q) + ENDIF + c = 1.0D0 / SQRT (t * t + 1.0D0) + s = t * c + a (i, j) = 0.0D0 + DO 21110 k = 1, i - 1 + atemp = c * a (k, i) - s * a (k, j) + a (k, j) = s * a (k, i) + c * a (k, j) + a (k, i) = atemp +21110 CONTINUE + DO 21120 k = i + 1, j - 1 + atemp = c * a (i, k) - s * a (k, j) + a (k, j) = s * a (i, k) + c * a (k, j) + a (i, k) = atemp +21120 CONTINUE + DO 21130 k = j + 1, n + atemp = c * a (i, k) - s * a (j, k) + a (j, k) = s * a (i, k) + c * a (j, k) + a (i, k) = atemp +21130 CONTINUE + DO 21140 k = 1, n + vtemp = c * v (k, i) - s * v (k, j) + v (k, j) = s * v (k, i) + c * v (k, j) + v (k, i) = vtemp +21140 CONTINUE + dtemp = c * c * d (i) + s * s * d (j) -& + 2.0D0 * c * s * b + d (j) = s * s * d (i) + c * c * d (j) +& + 2.0D0 * c * s * b + d (i) = dtemp + ENDIF +21010 CONTINUE +21000 CONTINUE +20000 CONTINUE +19999 CONTINUE + nrot = l +! + DO 30000 j = 1, n - 1 + k = j + dtemp = d (k) + DO 30100 i = j + 1, n + IF (d (i) .LT. dtemp) THEN + k = i + dtemp = d (k) + ENDIF +30100 CONTINUE + IF (k .GT. j) THEN + d (k) = d (j) + d (j) = dtemp + DO 30200 i = 1, n + dtemp = v (i, k) + v (i, k) = v (i, j) + v (i, j) = dtemp +30200 CONTINUE + ENDIF +30000 CONTINUE +! +RETURN +END subroutine jacobi + + diff --git a/tests/packmol/output.f90 b/tests/packmol/output.f90 new file mode 100644 index 00000000..d4bf02d8 --- /dev/null +++ b/tests/packmol/output.f90 @@ -0,0 +1,797 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Subroutine output: Subroutine that writes the output file +! + +subroutine output(n,x) + + use sizes + use compute_data + use input + + implicit none + integer :: n, k, i, ilugan, ilubar, itype, imol, idatom,& + irest, iimol, ichain, iatom, irec, ilres, ifres,& + iires, ciires, irescount,& + icart, i_ref_atom, ioerr, ifirst_mol + integer :: nr, nres, imark + integer :: i_fixed, i_not_fixed + + double precision :: x(n) + double precision :: tens(4,4), v(4,4), dv(4) + double precision :: v1(3), v2(3), v3(3) + double precision :: xbar, ybar, zbar, beta, gama, teta, xcm, ycm, zcm + double precision :: xlength, ylength, zlength + double precision :: xxyx, xxyy, xxyz, xyyz, xyyy, xzyx,& + xzyy, xzyz, xyyx, xq, yq, zq, q0, q1, q2, q3 + double precision :: xtemp, ytemp, ztemp + double precision :: sxmin, symin, szmin, sxmax, symax, szmax + + character :: write_chain, even_chain, odd_chain + character(len=64) :: title + character(len=strl) :: pdb_atom_line, tinker_atom_line, crd_format + character(len=8) :: crdires,crdresn,crdsegi,atmname + character(len=strl) :: record + character(len=5) :: i5hex + + ! Job title + + title = ' Built with Packmol ' + + ! + ! Write restart files, if required + ! + + ! Restart file for all system + + if ( restart_to(0) /= 'none' ) then + record = restart_to(0) + open(10,file=restart_to(0),iostat=ioerr) + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Could not open restart_to file: ', trim(adjustl(record)) + stop + end if + ilubar = 0 + ilugan = ntotmol*3 + do i = 1, ntotmol + write(10,"(6(tr1,es23.16))") x(ilubar+1), x(ilubar+2), x(ilubar+3), & + x(ilugan+1), x(ilugan+2), x(ilugan+3) + ilubar = ilubar + 3 + ilugan = ilugan + 3 + end do + close(10) + write(*,*) ' Wrote restart file for all system: ', trim(adjustl(record)) + end if + + ! Restart files for specific molecule types + + ilubar = 0 + ilugan = ntotmol*3 + do itype = 1, ntype + if ( restart_to(itype) /= 'none' ) then + record = restart_to(itype) + open(10,file=record,iostat=ioerr) + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Could not open restart_to file: ', trim(adjustl(record)) + stop + end if + do i = 1, nmols(itype) + write(10,"(6(tr1,es23.16))") x(ilubar+1), x(ilubar+2), x(ilubar+3), & + x(ilugan+1), x(ilugan+2), x(ilugan+3) + ilubar = ilubar + 3 + ilugan = ilugan + 3 + end do + close(10) + write(*,*) ' Wrote restart file: ', trim(adjustl(record)) + else + ilubar = ilubar + nmols(itype)*3 + ilugan = ilugan + nmols(itype)*3 + end if + end do + + ! Write the output (xyz file) + + if(xyz) then + open(30,file=xyzout,status='unknown') + write(30,*) ntotat + write(30,*) title + ilubar = 0 + ilugan = ntotmol*3 + icart = 0 + i_not_fixed = 0 + i_fixed = ntype + do itype = 1, ntfix + if ( .not. fixedoninput(itype) ) then + i_not_fixed = i_not_fixed + 1 + do imol = 1, nmols(i_not_fixed) + xbar = x(ilubar+1) + ybar = x(ilubar+2) + zbar = x(ilubar+3) + beta = x(ilugan+1) + gama = x(ilugan+2) + teta = x(ilugan+3) + call eulerrmat(beta,gama,teta,v1,v2,v3) + idatom = idfirst(i_not_fixed) - 1 + do iatom = 1, natoms(i_not_fixed) + icart = icart + 1 + idatom = idatom + 1 + call compcart(icart,xbar,ybar,zbar,& + coor(idatom,1),coor(idatom,2),& + coor(idatom,3),& + v1,v2,v3) + write(30,"( tr2,a3,tr2,3(tr2,f14.6) )") ele(idatom), (xcart(icart, k), k = 1, 3) + end do + ilugan = ilugan + 3 + ilubar = ilubar + 3 + end do + else + i_fixed = i_fixed + 1 + idatom = idfirst(i_fixed) - 1 + do iatom = 1, natoms(i_fixed) + idatom = idatom + 1 + write(30,"( tr2,a3,tr2,3(tr2,f14.6) )") ele(idatom), (coor(idatom,k),k=1,3) + end do + end if + end do + close(30) + end if + + ! write the output as a MOLDY file + + if(moldy) then + open(30,file=xyzout,status='unknown') + ! For square moldy boxes, this must be the side dimensions of the box + sxmin = 1.d30 + symin = 1.d30 + szmin = 1.d30 + sxmax = -1.d30 + symax = -1.d30 + szmax = -1.d30 + do irest = 1, nrest + if(ityperest(irest).eq.2) then + sxmin = dmin1(restpars(irest,1),sxmin) + symin = dmin1(restpars(irest,2),symin) + szmin = dmin1(restpars(irest,3),szmin) + sxmax = dmax1(restpars(irest,4)+restpars(irest,1),sxmax) + symax = dmax1(restpars(irest,4)+restpars(irest,2),symax) + szmax = dmax1(restpars(irest,4)+restpars(irest,3),szmax) + else if(ityperest(irest).eq.3) then + sxmin = dmin1(restpars(irest,1),sxmin) + symin = dmin1(restpars(irest,2),symin) + szmin = dmin1(restpars(irest,3),szmin) + sxmax = dmax1(restpars(irest,4),sxmax) + symax = dmax1(restpars(irest,5),symax) + szmax = dmax1(restpars(irest,6),szmax) + else + write(*,*) ' WARNING: The first line of the moldy output' + write(*,*) ' file contains the size of the sides of the' + write(*,*) ' paralelogram that defines the system. ' + write(*,*) ' The numbers printed may not be correct in ' + write(*,*) ' this case because regions other than cubes ' + write(*,*) ' or boxes were used. ' + sxmin = dmin1(sxmin,sizemin(1)) + symin = dmin1(symin,sizemin(2)) + szmin = dmin1(szmin,sizemin(3)) + sxmax = dmax1(sxmax,sizemax(1)) + symax = dmax1(symax,sizemax(2)) + szmax = dmax1(szmax,sizemax(3)) + end if + end do + xlength = sxmax - sxmin + ylength = symax - symin + zlength = szmax - szmin + write(30,"( 3(tr1,f12.6),' 90 90 90 1 1 1 ' )") xlength, ylength, zlength + ilubar = 0 + ilugan = ntotmol*3 + i_not_fixed = 0 + i_fixed = ntype + do itype = 1, ntfix + if ( .not. fixedoninput(itype) ) then + i_not_fixed = i_not_fixed + 1 + record = name(i_not_fixed) + do imol = 1, nmols(i_not_fixed) + xbar = (x(ilubar+1) - sxmin) / xlength + ybar = (x(ilubar+2) - symin) / ylength + zbar = (x(ilubar+3) - szmin) / zlength + beta = x(ilugan+1) + gama = x(ilugan+2) + teta = x(ilugan+3) + call eulerrmat(beta,gama,teta,v1,v2,v3) + + ! Computing cartesian coordinates and quaternions + + xxyx = 0.d0 + xxyy = 0.d0 + xxyz = 0.d0 + xyyx = 0.d0 + xyyy = 0.d0 + xyyz = 0.d0 + xzyx = 0.d0 + xzyy = 0.d0 + xzyz = 0.d0 + idatom = idfirst(i_not_fixed) - 1 + do iatom = 1, natoms(i_not_fixed) + idatom = idatom + 1 + xq = coor(idatom, 1)*v1(1) & + + coor(idatom, 2)*v2(1) & + + coor(idatom, 3)*v3(1) + yq = coor(idatom, 1)*v1(2) & + + coor(idatom, 2)*v2(2) & + + coor(idatom, 3)*v3(2) + zq = coor(idatom, 1)*v1(3) & + + coor(idatom, 2)*v2(3) & + + coor(idatom, 3)*v3(3) + + ! Recovering quaternions for molecule imol + + xxyx = xxyx + xq * coor(idatom,1) * amass(idatom) + xxyy = xxyy + xq * coor(idatom,2) * amass(idatom) + xxyz = xxyz + xq * coor(idatom,3) * amass(idatom) + xyyx = xyyx + yq * coor(idatom,1) * amass(idatom) + xyyy = xyyy + yq * coor(idatom,2) * amass(idatom) + xyyz = xyyz + yq * coor(idatom,3) * amass(idatom) + xzyx = xzyx + zq * coor(idatom,1) * amass(idatom) + xzyy = xzyy + zq * coor(idatom,2) * amass(idatom) + xzyz = xzyz + zq * coor(idatom,3) * amass(idatom) + end do + + tens(1,1) = xxyx + xyyy + xzyz + tens(1,2) = xzyy - xyyz + tens(2,2) = xxyx - xyyy - xzyz + tens(1,3) = xxyz - xzyx + tens(2,3) = xxyy + xyyx + tens(3,3) = xyyy - xzyz - xxyx + tens(1,4) = xyyx - xxyy + tens(2,4) = xzyx + xxyz + tens(3,4) = xyyz + xzyy + tens(4,4) = xzyz - xxyx - xyyy + nr = 16 + call jacobi (tens, 4, 4, dv, v, nr) + q0 = v(1,4) + q1 = v(2,4) + q2 = v(3,4) + q3 = v(4,4) + record = name(i_not_fixed) + xbar = dmin1(0.999999d0,xbar) + ybar = dmin1(0.999999d0,ybar) + zbar = dmin1(0.999999d0,zbar) + write(30,"( a10,tr1,7(f12.6) )") trim(adjustl(record)), xbar, ybar, zbar, & + q0, q1, q2, q3 + ilugan = ilugan + 3 + ilubar = ilubar + 3 + end do + else + i_fixed = i_fixed + 1 + idatom = idfirst(i_fixed) - 1 + + ! Getting the specified position of the molecule + + do irest = 1, nrest + if(irestline(irest).gt.linestrut(i_fixed,1).and.& + irestline(irest).lt.linestrut(i_fixed,2)) then + xcm = restpars(irest,1) - sxmin + ycm = restpars(irest,2) - symin + zcm = restpars(irest,3) - szmin + beta = -restpars(irest,4) + gama = -restpars(irest,5) + teta = -restpars(irest,6) + end if + end do + call eulerrmat(beta,gama,teta,v1,v2,v3) + + ! Computing cartesian coordinates and quaternions + + xxyx = 0.d0 + xxyy = 0.d0 + xxyz = 0.d0 + xyyx = 0.d0 + xyyy = 0.d0 + xyyz = 0.d0 + xzyx = 0.d0 + xzyy = 0.d0 + xzyz = 0.d0 + idatom = idfirst(i_fixed) - 1 + do iatom = 1, natoms(i_fixed) + idatom = idatom + 1 + xtemp = coor(idatom,1) - xcm + ytemp = coor(idatom,2) - ycm + ztemp = coor(idatom,3) - zcm + xq = xtemp*v1(1) + ytemp*v2(1) + ztemp*v3(1) + yq = xtemp*v1(2) + ytemp*v2(2) + ztemp*v3(2) + zq = xtemp*v1(3) + ytemp*v2(3) + ztemp*v3(3) + xxyx = xxyx + xtemp * xq * amass(idatom) + xxyy = xxyy + xtemp * yq * amass(idatom) + xxyz = xxyz + xtemp * zq * amass(idatom) + xyyx = xyyx + ytemp * xq * amass(idatom) + xyyy = xyyy + ytemp * yq * amass(idatom) + xyyz = xyyz + ytemp * zq * amass(idatom) + xzyx = xzyx + ztemp * xq * amass(idatom) + xzyy = xzyy + ztemp * yq * amass(idatom) + xzyz = xzyz + ztemp * zq * amass(idatom) + end do + tens(1,1) = xxyx + xyyy + xzyz + tens(1,2) = xzyy - xyyz + tens(2,2) = xxyx - xyyy - xzyz + tens(1,3) = xxyz - xzyx + tens(2,3) = xxyy + xyyx + tens(3,3) = xyyy - xzyz - xxyx + tens(1,4) = xyyx - xxyy + tens(2,4) = xzyx + xxyz + tens(3,4) = xyyz + xzyy + tens(4,4) = xzyz - xxyx - xyyy + nr = 16 + call jacobi (tens, 4, 4, dv, v, nr) + q0 = v(1,4) + q1 = v(2,4) + q2 = v(3,4) + q3 = v(4,4) + xcm = xcm / xlength + ycm = ycm / ylength + zcm = zcm / zlength + record = name(itype) + xcm = dmin1(0.999999d0,xcm) + ycm = dmin1(0.999999d0,ycm) + zcm = dmin1(0.999999d0,zcm) + write(30,"( a10,tr1,7(f12.6) )") trim(adjustl(record)),& + xcm, ycm, zcm, q0, q1, q2, q3 + end if + end do + close(30) + end if + + ! write the output as pdb file + + if(pdb) then + pdb_atom_line = "( t1,a6,t7,a5,t12,a10,t22,a1,t23,& + &i4,t27,a1,t31,f8.3,t39,f8.3,t47,& + &f8.3,t55,a26 )" + crd_format='(2I10,2X,A8,2X,A8,3F20.10,2X,A8,2X,A8,F20.10)' + + open(30,file=xyzout,status='unknown') + if ( crd ) then + open(40,file=crdfile,status='unknown') + write(40,'("* TITLE ", a64,/& + &"* Packmol generated CHARMM CRD File",/& + &"* Home-Page:",/& + &"* http://m3g.iqm.unicamp.br/packmol",/& + &"* ")') title + write(40,'(i10,2x,a)') ntotat,'EXT' + end if + + write(30,"( & + &'HEADER ',/& + &'TITLE ', a64,/& + &'REMARK Packmol generated pdb file ',/& + &'REMARK Home-Page: ',& + &'http://m3g.iqm.unicamp.br/packmol',/,& + &'REMARK' )" ) title + + if(add_box_sides) then + write(30,"( 'CRYST1',t7,f9.2,t16,f9.2,t25,f9.2,& + &t34,f7.2,t41,f7.2,t48,f7.2,& + &t56,'P 1 1' )") & + sizemax(1)-sizemin(1) + add_sides_fix,& + sizemax(2)-sizemin(2) + add_sides_fix,& + sizemax(3)-sizemin(3) + add_sides_fix,& + 90., 90., 90. + end if + + ilubar = 0 + ilugan = ntotmol*3 + icart = 0 + i_ref_atom = 0 + iimol = 0 + ichain = 0 + i_not_fixed = 0 + i_fixed = ntype + irescount = 1 + do itype = 1, ntfix + if ( .not. fixedoninput(itype) ) then + i_not_fixed = i_not_fixed + 1 + + ! Counting the number of residues of this molecule + + open(15,file=pdbfile(i_not_fixed),status='old') + ifres = 0 + do + read(15,str_format,iostat=ioerr) record + if ( ioerr /= 0 ) exit + if ( record(1:4).eq.'ATOM'.or.record(1:6).eq.'HETATM' ) then + read(record(23:26),*,iostat=ioerr) imark + if ( ioerr /= 0 ) then + record = pdbfile(i_not_fixed) + write(*,*) ' ERROR: Failed reading residue number ',& + ' from PDB file: ', trim(adjustl(record)) + write(*,*) ' Residue numbers are integers that must',& + ' be between columns 23 and 26. ' + write(*,*) ' Other characters within these columns',& + ' will cause input/output errors. ' + write(*,*) ' Standard PDB format specifications can',& + ' be found at: ' + write(*,*) ' www.rcsb.org/pdb ' + stop + end if + if ( ifres .eq. 0 ) ifres = imark + ilres = imark + end if + end do + nres = ilres - ifres + 1 + + do irec = 1, strl + record(irec:irec) = ' ' + end do + + mol: do imol = 1, nmols(i_not_fixed) + iimol = iimol + 1 + + if( chain(i_not_fixed) == "#" ) then + if(imol.eq.1.or.mod(imol,9999).eq.1) then + ichain = ichain + 1 + if( changechains(i_not_fixed) ) then + call chainc(ichain,odd_chain) + ichain = ichain + 1 + call chainc(ichain,even_chain) + else + call chainc(ichain,even_chain) + odd_chain = even_chain + end if + end if + if ( mod(imol,2) == 0 ) write_chain = even_chain + if ( mod(imol,2) /= 0 ) write_chain = odd_chain + else + write_chain = chain(i_not_fixed) + end if + + xbar = x(ilubar+1) + ybar = x(ilubar+2) + zbar = x(ilubar+3) + beta = x(ilugan+1) + gama = x(ilugan+2) + teta = x(ilugan+3) + + call eulerrmat(beta,gama,teta,v1,v2,v3) + + rewind(15) + idatom = idfirst(i_not_fixed) - 1 + iatom = 0 + do while(iatom.lt.natoms(i_not_fixed)) + + read(15,str_format,iostat=ioerr) record + if ( ioerr /= 0 ) exit mol + if(record(1:4).ne.'ATOM'.and.record(1:6).ne.'HETATM') then + cycle + end if + + iatom = iatom + 1 + icart = icart + 1 + idatom = idatom + 1 + i_ref_atom = i_ref_atom + 1 + call compcart(icart,xbar,ybar,zbar,& + coor(idatom,1),coor(idatom,2),& + coor(idatom,3),v1,v2,v3) + + ! Setting residue numbers for this molecule + + imark = 0 + read(record(23:26),*,iostat=ioerr) imark + if ( ioerr /= 0 ) imark = 1 + if(resnumbers(i_not_fixed).eq.0) then + iires = mod(imol,9999) + ciires = mod(imol,99999999) + else if(resnumbers(i_not_fixed).eq.1) then + iires = imark + ciires = imark + else if(resnumbers(i_not_fixed).eq.2) then + iires = mod(imark-ifres+irescount,9999) + ciires = mod(imark-ifres+irescount,99999999) + else if(resnumbers(i_not_fixed).eq.3) then + iires = mod(iimol,9999) + ciires = mod(iimol,99999999) + end if + if(iires.eq.0) iires = 9999 + if(ciires.eq.0) ciires = 99999999 + + ! Writing output line + + if(record(1:4).eq.'ATOM') then + write(30,pdb_atom_line) "ATOM ",i5hex(i_ref_atom),& + record(12:21), write_chain, iires,& + record(27:27),& + (xcart(icart,k), k = 1, 3),& + record(55:80) + end if + if(record(1:6).eq.'HETATM') then + write(30,pdb_atom_line) "HETATM", i5hex(i_ref_atom),& + record(12:21), write_chain, iires,& + record(27:27),& + (xcart(icart,k), k = 1, 3),& + record(55:80) + end if + + if ( crd ) then + write(crdires,'(I8)') ciires + crdires = adjustl(crdires) + crdresn = trim(adjustl(record(18:21))) + crdsegi = crdresn + if (len(trim(adjustl(segid(i_not_fixed))))/=0) crdsegi = trim(adjustl(segid(i_not_fixed))) + atmname = adjustl(record(13:16)) + write(40,crd_format) i_ref_atom, ciires,crdresn, atmname, & + (xcart(icart,k), k = 1, 3), crdsegi,& + crdires, 0. + end if + + end do + irescount = irescount + nres + ilugan = ilugan + 3 + ilubar = ilubar + 3 + + if(add_amber_ter) write(30,"('TER')") + end do mol + close(15) + + ! If fixed molecule on input: + else + i_fixed = i_fixed + 1 + + ! Counting the number of residues of this molecule + + open(15,file=pdbfile(i_fixed),status='old') + ifres = 0 + do + read(15,str_format,iostat=ioerr) record + if ( ioerr /= 0 ) exit + if ( record(1:4).eq.'ATOM'.or.record(1:6).eq.'HETATM' ) then + read(record(23:26),*,iostat=ioerr) imark + if ( ioerr /= 0 ) then + record = pdbfile(i_not_fixed) + write(*,*) ' ERROR: Failed reading residue number ',& + ' from PDB file: ', trim(adjustl(record)) + write(*,*) ' Residue numbers are integers that must',& + ' be between columns 23 and 26. ' + write(*,*) ' Other characters within these columns',& + ' will cause input/output errors. ' + write(*,*) ' Standard PDB format specifications can',& + ' be found at: ' + write(*,*) ' www.rcsb.org/pdb ' + stop + end if + if ( ifres .eq. 0 ) ifres = imark + ilres = imark + end if + end do + nres = ilres - ifres + 1 + + iimol = iimol + 1 + idatom = idfirst(i_fixed) - 1 + + rewind(15) + iatom = 0 + do while(iatom.lt.natoms(i_fixed)) + + read(15,str_format,iostat=ioerr) record + if ( ioerr /= 0 ) exit + if(record(1:4).ne.'ATOM'.and.record(1:6).ne.'HETATM') then + !write(30,"( a80 )") record(1:80) + cycle + end if + + iatom = iatom + 1 + idatom = idatom + 1 + i_ref_atom = i_ref_atom + 1 + + read(record(23:26),*) imark + if(resnumbers(i_fixed).eq.0) then + iires = 1 + ciires = 1 + else if(resnumbers(i_fixed).eq.1) then + iires = imark + ciires = imark + else if(resnumbers(i_fixed).eq.2) then + iires = mod(imark-ifres+irescount,9999) + ciires = mod(imark-ifres+irescount,99999999) + else if(resnumbers(i_fixed).eq.3) then + iires = mod(iimol,9999) + ciires = mod(iimol,99999999) + end if + + if ( chain(i_fixed) == "#" ) then + write_chain = record(22:22) + else + write_chain = chain(i_fixed) + end if + + if(record(1:4).eq.'ATOM') then + write(30,pdb_atom_line) "ATOM ", i5hex(i_ref_atom),& + record(12:21), write_chain, iires,& + record(27:27),& + (coor(idatom,k), k = 1, 3),& + record(55:80) + end if + if(record(1:6).eq.'HETATM') then + write(30,pdb_atom_line) "HETATM", i5hex(i_ref_atom),& + record(12:21), write_chain, iires,& + record(27:27),& + (coor(idatom,k), k = 1, 3),& + record(55:80) + end if + + if ( crd ) then + write(crdires,'(I8)') ciires + crdires = adjustl(crdires) + crdresn = trim(adjustl(record(18:21))) + crdsegi = crdresn + if (len(trim(adjustl(segid(i_fixed))))/=0) crdsegi = trim(adjustl(segid(i_fixed))) + atmname = adjustl(record(13:16)) + write(40,crd_format) i_ref_atom, iires,crdresn, atmname, & + (xcart(icart,k), k = 1, 3), crdsegi,& + crdires, 0. + end if + + end do + irescount = irescount + nres + close(15) + if(add_amber_ter) write(30,"('TER')") + end if + end do + ! + ! Write connectivity if available + ! + i_ref_atom = 0 + i_not_fixed = 0 + i_fixed = ntype + do itype = 1, ntfix + if ( .not. fixedoninput(itype) ) then + i_not_fixed = i_not_fixed + 1 + idatom = idfirst(i_not_fixed) - 1 + do imol = 1, nmols(i_not_fixed) + iatom = 0 + ifirst_mol = i_ref_atom + 1 + do while(iatom.lt.natoms(i_not_fixed)) + iatom = iatom + 1 + i_ref_atom = i_ref_atom + 1 + if(connect(itype)) then + call write_connect(30,idatom,iatom,ifirst_mol) + end if + end do + end do + close(15) + ! If fixed molecule on input: + else + i_fixed = i_fixed + 1 + idatom = idfirst(i_fixed) - 1 + iatom = 0 + ifirst_mol = i_ref_atom + 1 + idatom = idfirst(i_fixed) - 1 + do while(iatom.lt.natoms(i_fixed)) + iatom = iatom + 1 + i_ref_atom = i_ref_atom + 1 + if(connect(itype)) then + call write_connect(30,idatom,iatom,ifirst_mol) + end if + end do + end if + end do + write(30,"('END')") + close(30) + if ( crd ) close(40) + end if + + ! Write the output (tinker xyz file) + + if(tinker) then + + tinker_atom_line = "( i7,tr2,a3,3(tr2,f10.6),9(tr2,i7) )" + + open(30, file = xyzout,status='unknown') + + write(30,"( i6,tr2,a64 )") ntotat, title + + ilubar = 0 + ilugan = ntotmol*3 + icart = 0 + i_ref_atom = 0 + i_not_fixed = 0 + i_fixed = ntype + + do itype = 1, ntfix + + if ( .not. fixedoninput(itype) ) then + i_not_fixed = i_not_fixed + 1 + + do imol = 1, nmols(i_not_fixed) + + xbar = x(ilubar+1) + ybar = x(ilubar+2) + zbar = x(ilubar+3) + beta = x(ilugan+1) + gama = x(ilugan+2) + teta = x(ilugan+3) + + call eulerrmat(beta,gama,teta,v1,v2,v3) + + idatom = idfirst(i_not_fixed) - 1 + do iatom = 1, natoms(i_not_fixed) + icart = icart + 1 + idatom = idatom + 1 + call compcart(icart,xbar,ybar,zbar,& + coor(idatom,1),coor(idatom,2),& + coor(idatom,3),& + v1,v2,v3) + + ntcon(1) = nconnect(idatom,1) + do k = 2, maxcon(idatom) + ntcon(k) = nconnect(idatom,k) + i_ref_atom + end do + write(30,tinker_atom_line) i_ref_atom+iatom,& + ele(idatom), (xcart(icart, k), k = 1, 3),& + (ntcon(k), k = 1, maxcon(idatom)) + end do + i_ref_atom = i_ref_atom + natoms(i_not_fixed) + + ilugan = ilugan + 3 + ilubar = ilubar + 3 + + end do + + else + + i_fixed = i_fixed + 1 + idatom = idfirst(i_fixed) - 1 + do iatom = 1, natoms(i_fixed) + idatom = idatom + 1 + ntcon(1) = nconnect(idatom,1) + do k = 2, maxcon(idatom) + ntcon(k) = nconnect(idatom,k) + i_ref_atom + end do + write(30,tinker_atom_line) i_ref_atom+iatom, ele(idatom),& + (coor(idatom,k), k = 1, 3),& + (ntcon(k), k = 1, maxcon(idatom)) + end do + i_ref_atom = i_ref_atom + natoms(i_fixed) + + end if + + end do + close(30) + end if + + return +end subroutine output + +function i5hex(i) + implicit none + integer :: i + character(len=5) i5hex + if(i <= 99999) then + write(i5hex,"(i5)") i + else + write(i5hex,"(z5)") i + end if +end + +subroutine write_connect(iostream,idatom,iatom,ifirst) + use sizes + use input + implicit none + integer :: i, j, iostream, iatom, idatom, ifirst + character(len=5) :: i5hex + character(len=strl) :: str + if(maxcon(iatom+idatom) == 0) return + str = "CONECT" + j=7 + write(str(j:j+4),"(a5)") i5hex(iatom+ifirst-1) + do i = 1, maxcon(iatom+idatom) + j = j + 5 + write(str(j:j+4),"(a5)") i5hex(nconnect(iatom+idatom,i)+ifirst-1) + end do + write(iostream,"(a)") trim(adjustl(str)) +end subroutine write_connect + + + + + + diff --git a/tests/packmol/packmol.f90 b/tests/packmol/packmol.f90 new file mode 100644 index 00000000..54954013 --- /dev/null +++ b/tests/packmol/packmol.f90 @@ -0,0 +1,942 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +!----------------------------------------------------------------------------- +! +! http://m3g.iqm.unicamp.br/packmol +! +! Usage (see the page above for further information): +! +! ./packmol < inputfile.inp +! +! References: +! +! L. Martinez, R. Andrade, E. G. Birgin, J. M. Martinez, +! PACKMOL: A package for building initial configurations for +! molecular dynamics simulations, J. Comp. Chem. 30:2157-2164, 2009. +! +! J. M. Martinez and L. Martinez, +! Packing optimization for the automated generation of complex +! system's initial configurations for molcular dynamics and +! docking. J. Comp. Chem. 24:819-825, 2003. +! +! This version of Packmol uses the optimization method GENCAN which +! is a part of the TANGO (Trustable Algorithms for Nonlinear General +! Optimization) project. +! Reference: +! E. G. Birgin, J. M. Martinez, Comp. Opt. Appl. 23:101-125, 2002. +! http://www.ime.usp.br/~egbirgin/tango +! +! + +program packmol + + use sizes + use compute_data + use input + use usegencan + use flashsort + use swaptypemod + use ahestetic + implicit none + + integer :: itype, irest, idatom, iatom + integer :: idtemp, nmtemp, natemp, input_itypetemp + integer :: linesttmp1, linesttmp2, jtype + integer :: ntmol, n, iftype, icart, imol, iicart, iline_atoms + integer :: i, iline, iiatom, iat, iirest, iratcount, ival + integer :: loop + integer :: resntemp, nloop_tmp + integer :: ioerr + integer :: maxmove_tmp + + double precision, allocatable :: x(:), xprint(:) ! (nn) + double precision :: v1(3),v2(3),v3(3) + double precision :: radscale, value + double precision :: cmx, cmy, cmz, beta, gama, teta + double precision :: xtemp, ytemp, ztemp + double precision :: fx, bestf, flast, fprint, all_type_fx + double precision :: fimp, fimprov + double precision, parameter :: pi=4.d0*datan(1.d0) + + real :: etime, tarray(2), time0 + + character(len=strl) :: record, restart_from_temp, restart_to_temp + character(len=strl) :: xyzfile + character(len=1) :: chain_tmp + + logical :: fixtmp + logical :: rests + logical :: movebadprint + logical :: changechains_tmp, connecttmp + + logical, allocatable :: fixed(:) ! ntype + + ! Printing title + + call title() + + ! Set dimensions of all arrays + + call setsizes() + + ! Allocate local array + + allocate(fixed(ntype),x(nn),xprint(nn),xfull(nn)) + + ! Start time computation + + time0 = etime(tarray) + + ! Reading input file + + call getinp() + + ! Put molecules in their center of mass + + call cenmass() + + ! Writting some input data + + write(*,*) ' Total number of atoms: ', ntotat + + ! Put fixed molecules in the specified position + + do itype = 1, ntype + fixed(itype) = .false. + end do + + do irest = 1, nrest + if(ityperest(irest).eq.1) then + do itype = 1, ntype + if(irestline(irest).gt.linestrut(itype,1).and.& + irestline(irest).lt.linestrut(itype,2)) then + cmx = restpars(irest,1) + cmy = restpars(irest,2) + cmz = restpars(irest,3) + beta = restpars(irest,4) + gama = restpars(irest,5) + teta = restpars(irest,6) + + ! Compute rotation matrix from euler angles + + call eulerfixed(beta,gama,teta,v1,v2,v3) + + idatom = idfirst(itype) - 1 + do iatom = 1, natoms(itype) + idatom = idatom + 1 + xtemp = coor(idatom,1)*v1(1) & + + coor(idatom,2)*v2(1) & + + coor(idatom,3)*v3(1) + ytemp = coor(idatom,1)*v1(2) & + + coor(idatom,2)*v2(2) & + + coor(idatom,3)*v3(2) + ztemp = coor(idatom,1)*v1(3) & + + coor(idatom,2)*v2(3) & + + coor(idatom,3)*v3(3) + coor(idatom, 1) = xtemp + cmx + coor(idatom, 2) = ytemp + cmy + coor(idatom, 3) = ztemp + cmz + end do + record = name(itype) + write(*,*) ' Molecule ',trim(adjustl(record)),'(',itype,') will be fixed.' + fixed(itype) = .true. + if(nmols(itype).gt.1) then + write(*,*)' ERROR: Cannot set number > 1',' for fixed molecules. ' + write(*,*) ' Structure: ', itype,': ', trim(adjustl(record)) + stop + end if + if ( restart_from(itype) /= 'none' .or. & + restart_to(itype) /= 'none' ) then + write(*,*) ' ERROR: Restart files cannot be used for fixed molecules. ' + write(*,*) ' Structure: ', itype,': ', trim(adjustl(record)) + stop + end if + end if + end do + end if + end do + + ! Reseting parameters for removing the fixed molecules + ! fix is the logical variable that informs that there are fixed molecules + + fix = .false. + ntemp = 0 + do itype = 1, ntype + + ! input_itype and fixedoninput vectors are used only to preserve the + ! order of input in the output files + + input_itype(itype) = itype + if(fixed(itype)) then + fix = .true. + fixedoninput(itype) = .true. + else + ntemp = ntemp + 1 + fixedoninput(itype) = .false. + end if + end do + ntfix = ntype + ntype = ntemp + + do i = 1, ntfix - ntype + do itype = 1, ntfix - 1 + if(fixed(itype)) then + record = name(itype) + restart_to_temp = restart_to(itype) + restart_from_temp = restart_from(itype) + fixtmp = fixed(itype) + idtemp = idfirst(itype) + input_itypetemp = input_itype(itype) + nmtemp = nmols(itype) + natemp = natoms(itype) + resntemp = resnumbers(itype) + connecttmp = connect(itype) + if(pdb) xyzfile = pdbfile(itype) + linesttmp1 = linestrut(itype,1) + linesttmp2 = linestrut(itype,2) + changechains_tmp = changechains(itype) + maxmove_tmp = maxmove(itype) + chain_tmp = chain(itype) + nloop_tmp = nloop_type(itype) + jtype = itype + 1 + if(.not.fixed(jtype)) then + name(itype) = name(jtype) + name(jtype) = record(1:10) + restart_to(itype) = restart_to(jtype) + restart_to(jtype) = restart_to_temp + restart_from(itype) = restart_from(jtype) + restart_from(jtype) = restart_from_temp + idfirst(itype) = idfirst(jtype) + idfirst(jtype) = idtemp + input_itype(itype) = input_itype(jtype) + input_itype(jtype) = input_itypetemp + fixed(itype) = fixed(jtype) + fixed(jtype) = fixtmp + nmols(itype) = nmols(jtype) + nmols(jtype) = nmtemp + natoms(itype) = natoms(jtype) + natoms(jtype) = natemp + resnumbers(itype) = resnumbers(jtype) + resnumbers(jtype) = resntemp + connect(itype) = connect(jtype) + connect(jtype) = connecttmp + changechains(itype) = changechains(jtype) + changechains(jtype) = changechains_tmp + maxmove(itype) = maxmove(jtype) + maxmove(jtype) = maxmove_tmp + chain(itype) = chain(jtype) + chain(jtype) = chain_tmp + nloop_type(itype) = nloop_type(jtype) + nloop_type(jtype) = nloop_tmp + if(pdb) then + pdbfile(itype) = pdbfile(jtype) + pdbfile(jtype) = xyzfile + end if + linestrut(itype,1) = linestrut(jtype,1) + linestrut(itype,2) = linestrut(jtype,2) + linestrut(jtype,1) = linesttmp1 + linestrut(jtype,2) = linesttmp2 + end if + end if + end do + end do + + ! Computing the number of variables + ! + ! ntype: 1...ntype (counter for the number of free structures) + ! + ! ntfix: 1...ntype...ntfix (counter for the total number of structures) + ! + + ntmol = 0 + do itype = 1, ntfix + ntmol = ntmol + nmols(itype) + end do + ntotmol = 0 + do itype = 1, ntype + ntotmol = ntotmol + nmols(itype) + end do + n = ntotmol * 6 + write(*,*) ' Total number of molecules: ', ntmol + write(*,*) ' Number of fixed molecules: ', ntmol - ntotmol + write(*,*) ' Number of free molecules: ', ntotmol + write(*,*) ' Number of variables: ', n + + ! Computing the total number of fixed atoms + + natfix = 0 + if(fix) then + do iftype = ntype + 1, ntfix + natfix = natfix + natoms(iftype) + end do + end if + write(*,*) ' Total number of fixed atoms: ', natfix + + ! Setting the array that contains the restrictions per atom + + icart = 0 + do itype = 1, ntype + rests = .false. + do imol = 1, nmols(itype) + idatom = idfirst(itype) - 1 + do iatom = 1, natoms(itype) + icart = icart + 1 + idatom = idatom + 1 + nratom(icart) = 0 + iratcount = 0 + do i = 1, mrperatom + iratom(icart,i) = 0 + end do + iline = linestrut(itype,1) + do while(iline.lt.linestrut(itype,2)) + iline = iline + 1 + if(keyword(iline,1).eq.'atoms') then + iiatom = -1 + do iat = 2, maxkeywords + read(keyword(iline,iat),*,iostat=ioerr) iiatom + if ( ioerr /= 0 ) then + if ( iiatom == -1 ) then + write(*,*) ' ERROR: Could not read atom selection for type: ', itype + stop + else + exit + end if + end if + if ( iiatom > natoms(itype) ) then + write(*,*) ' ERROR: atom selection with index greater than number of ' + write(*,*) ' atoms in structure ', itype + stop + end if + if(iatom.eq.iiatom) exit + end do + do while(keyword(iline,1).ne.'end'.and.& + keyword(iline,2).ne.'atoms') + iline = iline + 1 + if(iatom.eq.iiatom) then + if(keyword(iline,1).eq.'inside'.or.& + keyword(iline,1).eq.'outside'.or.& + keyword(iline,1).eq.'over'.or.& + keyword(iline,1).eq.'above'.or.& + keyword(iline,1).eq.'below') then + nratom(icart) = nratom(icart) + 1 + iratcount = iratcount + 1 + do irest = 1, nrest + if(irestline(irest).eq.iline) iirest = irest + end do + iratom(icart,iratcount) = iirest + end if + end if + end do + iline = iline - 1 + else if(keyword(iline,1).eq.'inside'.or.& + keyword(iline,1).eq.'outside'.or.& + keyword(iline,1).eq.'over'.or.& + keyword(iline,1).eq.'above'.or.& + keyword(iline,1).eq.'below') then + nratom(icart) = nratom(icart) + 1 + iratcount = iratcount + 1 + do irest = 1, nrest + if(irestline(irest).eq.iline) iirest = irest + end do + iratom(icart,iratcount) = iirest + end if + end do + if(nratom(icart).gt.0) rests = .true. + end do + if(.not.rests) then + write(*,*) ' ERROR: Some molecule has no geometrical',& + ' restriction defined: nothing to do.' + stop + end if + end do + end do + + ! Read the constraints to rotations about axis, if set + + do itype = 1, ntype + constrain_rot(itype,1) = .false. + constrain_rot(itype,2) = .false. + constrain_rot(itype,3) = .false. + iline = linestrut(itype,1) + do while(iline.lt.linestrut(itype,2)) + iline = iline + 1 + if(keyword(iline,1).eq.'constrain_rotation') then + if(iline.gt.linestrut(itype,1).and.& + iline.lt.linestrut(itype,2)) then + + ! Note that for movable molecules, teta is a rotation on the x-axis, + ! gama is a rotation on the z-axis, + ! beta is a rotation on the y-axis + ! (see eulerrmat routine) + + if(keyword(iline,2).eq.'x') then + constrain_rot(itype,3) = .true. + read(keyword(iline,3),*) rot_bound(itype,3,1) + read(keyword(iline,4),*) rot_bound(itype,3,2) + rot_bound(itype,3,1) = rot_bound(itype,3,1)*pi/180.d0 + rot_bound(itype,3,2) = rot_bound(itype,3,2)*pi/180.d0 + + write(*,*) ' Rotations about x axis of molecules of ',& + ' type ', itype, ' will be constrained. ' + end if + if(keyword(iline,2).eq.'y') then + constrain_rot(itype,1) = .true. + read(keyword(iline,3),*) rot_bound(itype,1,1) + read(keyword(iline,4),*) rot_bound(itype,1,2) + rot_bound(itype,1,1) = rot_bound(itype,1,1)*pi/180.d0 + rot_bound(itype,1,2) = rot_bound(itype,1,2)*pi/180.d0 + + write(*,*) ' Rotations about y axis of molecules of ',& + ' type ', itype, ' will be constrained. ' + end if + if(keyword(iline,2).eq.'z') then + constrain_rot(itype,2) = .true. + read(keyword(iline,3),*) rot_bound(itype,2,1) + read(keyword(iline,4),*) rot_bound(itype,2,2) + rot_bound(itype,2,1) = rot_bound(itype,2,1)*pi/180.d0 + rot_bound(itype,2,2) = rot_bound(itype,2,2)*pi/180.d0 + + write(*,*) ' Rotations about z axis of molecules of ',& + ' type ', itype, ' will be constrained. ' + end if + if ( keyword(iline,2) /= 'x' .and. & + keyword(iline,2) /= 'y' .and. & + keyword(iline,2) /= 'z' ) then + write(*,*) ' ERROR: constrain_rotation option not properly defined (not x, y, or z) ' + stop + end if + end if + end if + end do + end do + + ! Setting the vector that contains the default tolerances + + do i = 1, ntotat + radius(i) = dism/2.d0 + fscale(i) = 1.d0 + if ( use_short_tol ) then + use_short_radius(i) = .true. + else + use_short_radius(i) = .false. + end if + short_radius(i) = short_tol_dist/2.d0 + short_radius_scale(i) = short_tol_scale + end do + + ! Setting the radius defined for atoms of each molecule, + ! but not atom-specific, first + + icart = 0 + do itype = 1, ntfix + iline = linestrut(itype,1) + iline_atoms = 0 + do while( iline <= linestrut(itype,2) ) + if ( keyword(iline,1) == "atoms" ) then + iline_atoms = iline + iline = iline + 1 + cycle + end if + if ( keyword(iline,1) == "end" .and. & + keyword(iline,2) == "atoms" ) then + iline_atoms = 0 + iline = iline + 1 + cycle + end if + if ( iline_atoms == 0 ) then + ! + ! Read radius + ! + if ( keyword(iline,1) == "radius" ) then + read(keyword(iline,2),*,iostat=ioerr) value + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Could not read radius from keyword. ' + stop + end if + iicart = icart + do imol = 1, nmols(itype) + do iatom = 1, natoms(itype) + iicart = iicart + 1 + radius(iicart) = value + end do + end do + end if + ! + ! Read minimum-distance function scale + ! + if ( keyword(iline,1) == "fscale" ) then + read(keyword(iline,2),*,iostat=ioerr) value + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Could not read fscale value from keyword. ' + stop + end if + iicart = icart + do imol = 1, nmols(itype) + do iatom = 1, natoms(itype) + iicart = iicart + 1 + fscale(iicart) = value + end do + end do + end if + ! + ! Read short_radius + ! + if ( keyword(iline,1) == "short_radius" ) then + read(keyword(iline,2),*,iostat=ioerr) value + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Could not read short_radius value from keyword. ' + stop + end if + iicart = icart + do imol = 1, nmols(itype) + do iatom = 1, natoms(itype) + iicart = iicart + 1 + short_radius(iicart) = value + use_short_radius(iicart) = .true. + end do + end do + end if + ! + ! Read short_radius scale + ! + if ( keyword(iline,1) == "short_radius_scale" ) then + read(keyword(iline,2),*,iostat=ioerr) value + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Could not read short_radius_scale value from keyword. ' + stop + end if + iicart = icart + do imol = 1, nmols(itype) + do iatom = 1, natoms(itype) + iicart = iicart + 1 + short_radius_scale(iicart) = value + use_short_radius(iicart) = .true. + end do + end do + end if + end if + iline = iline + 1 + end do + icart = icart + nmols(itype)*natoms(itype) + end do + + ! If some radius was defined using atom-specific definitions, overwrite + ! the general radius defined for the molecule + + icart = 0 + do itype = 1, ntfix + iline = linestrut(itype,1) + iline_atoms = 0 + do while( iline <= linestrut(itype,2) ) + if ( keyword(iline,1) == "atoms" ) then + iline_atoms = iline + iline = iline + 1 + cycle + end if + if ( keyword(iline,1) == "end" .and. & + keyword(iline,2) == "atoms" ) then + iline_atoms = 0 + iline = iline + 1 + cycle + end if + if ( iline_atoms /= 0 ) then + ! + ! Read atom specific radius + ! + if ( keyword(iline,1) == "radius" ) then + read(keyword(iline,2),*,iostat=ioerr) value + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Could not read radius from keyword. ' + stop + end if + ival = 2 + do + read(keyword(iline_atoms,ival),*,iostat=ioerr) iat + if ( ioerr /= 0 ) exit + if ( iat > natoms(itype) ) then + write(*,*) ' ERROR: atom selection with index greater than number of ' + write(*,*) ' atoms in structure ', itype + stop + end if + radius(icart+iat) = value + ival = ival + 1 + end do + end if + ! + ! Read atom specific function scale + ! + if ( keyword(iline,1) == "fscale" ) then + read(keyword(iline,2),*,iostat=ioerr) value + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Could not read fscale value from keyword. ' + stop + end if + ival = 2 + do + read(keyword(iline_atoms,ival),*,iostat=ioerr) iat + if ( ioerr /= 0 ) exit + if ( iat > natoms(itype) ) then + write(*,*) ' ERROR: atom selection with index greater than number of ' + write(*,*) ' atoms in structure ', itype + stop + end if + fscale(icart+iat) = value + ival = ival + 1 + end do + end if + ! + ! Read atom specific short radius + ! + if ( keyword(iline,1) == "short_radius" ) then + read(keyword(iline,2),*,iostat=ioerr) value + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Could not read short_radius value from keyword. ' + stop + end if + ival = 2 + do + read(keyword(iline_atoms,ival),*,iostat=ioerr) iat + if ( ioerr /= 0 ) exit + if ( iat > natoms(itype) ) then + write(*,*) ' ERROR: atom selection with index greater than number of ' + write(*,*) ' atoms in structure ', itype + stop + end if + short_radius(icart+iat) = value + use_short_radius(icart+iat) = .true. + ival = ival + 1 + end do + end if + ! + ! Read atom specific short radius function scale + ! + if ( keyword(iline,1) == "short_radius_scale" ) then + read(keyword(iline,2),*,iostat=ioerr) value + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Could not read short_radius_scale value from keyword. ' + stop + end if + ival = 2 + do + read(keyword(iline_atoms,ival),*,iostat=ioerr) iat + if ( ioerr /= 0 ) exit + if ( iat > natoms(itype) ) then + write(*,*) ' ERROR: atom selection with index greater than number of ' + write(*,*) ' atoms in structure ', itype + stop + end if + short_radius_scale(icart+iat) = value + use_short_radius(icart+iat) = .true. + ival = ival + 1 + end do + end if + end if + iline = iline + 1 + end do + iicart = icart + icart = icart + natoms(itype) + do imol = 2, nmols(itype) + do iatom = 1, natoms(itype) + icart = icart + 1 + radius(icart) = radius(iicart+iatom) + fscale(icart) = fscale(iicart+iatom) + short_radius(icart) = short_radius(iicart+iatom) + short_radius_scale(icart) = short_radius_scale(iicart+iatom) + use_short_radius(icart) = use_short_radius(iicart+iatom) + end do + end do + end do + + ! Check if the short radii were set correctly, if the case + + ioerr = 0 + do i = 1, ntotat + if ( use_short_radius(i) ) then + if ( short_radius(i) >= radius(i) ) then + write(*,*) ' ERROR: The short radius must be smaller than the default radius. ' + write(*,*) ' (the default radius is one half of the default tolerance).' + stop + end if + end if + end do + + ! If there are no variables (only fixed molecules, stop) + + if(n.eq.0) then + call output(n,x) + write(*,dash1_line) + write(*,*) ' There are only fixed molecules, therefore there is nothing to do. ' + write(*,*) ' The output file contains the fixed molecules in the desired positions. ' + write(*,dash1_line) + write(*,*) ' Wrote output file: ', trim(adjustl(xyzout)) + if ( crd ) write(*,*) ' ... and to CRD file: ', trim(adjustl(crdfile)) + write(*,dash1_line) + stop + end if + + ! + ! (Re)setting parameters and building initial point + ! + + call initial(n,x) + + ! Computing the energy at the initial point + + radscale = 1.d0 + do i = 1, ntotat + radius_ini(i) = radius(i) + end do + call computef(n,x,all_type_fx) + write(*,*) ' Objective function at initial point: ', all_type_fx + fprint = all_type_fx + + ! Stop if only checking the initial approximation + + if(check) then + call output(n,x) + write(*,*) ' Wrote initial point to output file: ', trim(adjustl(xyzout)) + if ( crd ) write(*,*) ' ... and to CRD file: ', trim(adjustl(crdfile)) + stop + end if + + ! + ! Main loop: first pack types of molecules separately, then + ! pack all molecules together + ! + + call swaptype(n,x,itype,0) ! Save all-molecule vector data + itype = 0 + main : do while(itype <= ntype) + itype = itype + 1 + if ( packall ) itype = ntype + 1 + + ! Use larger tolerance than required to improve separation + + radscale = discale + do i = 1, ntotat + radius(i) = discale*radius_ini(i) + end do + + ! Set vectors for specific or all-molecule packing + + if ( itype <= ntype ) then + call swaptype(n,x,itype,1) ! Set vectors to pack only this type of molecule + else + call swaptype(n,x,itype,3) ! Restore all-molecule vectors + end if + + ! Print titles + + write(*,hash3_line) + if ( itype <= ntype ) then + write(*,*) ' Packing molecules of type: ', input_itype(itype) + else + write(*,*) ' Packing all molecules together ' + end if + write(*,hash3_line) + + ! Checking if first approximation is a solution + + call computef(n,x,fx) + + if ( fdist < precision .and. frest < precision ) then + + write(*,*) + write(*,*) ' Initial approximation is a solution. Nothing to do. ' + write(*,*) + call swaptype(n,x,itype,3) ! Restore all-molecule vectors + call output(n,x) + if( itype == ntype + 1 ) then + write(*,*) ' Solution written to file: ', trim(adjustl(xyzout)) + if ( crd ) write(*,*) ' ... and to CRD file: ', trim(adjustl(crdfile)) + else + write(*,*) ' Current point written to file: ', trim(adjustl(xyzout)) + if ( crd ) write(*,*) ' ... and to CRD file: ', trim(adjustl(crdfile)) + end if + call writesuccess(itype,fdist,frest,fx) + + ! Otherwise, pack the molecules + + else + + loop = -1 + gencanloop : do while(loop.lt.nloop) + loop = loop + 1 + + ! Reseting the parameters relative to the improvement of the function + + if(loop.eq.0) then + fimp = 1.d99 + fimprov = fimp + do i = 1, ntotat + radiuswork(i) = radius(i) + radius(i) = radius_ini(i) + end do + call computef(n,x,fx) + do i = 1, ntotat + radius(i) = radiuswork(i) + end do + bestf = fx + flast = fx + end if + + ! Moving bad molecules + + if(radscale == 1.d0 .and. fimp.le.10.d0) then + movebadprint = .true. + call movebad(n,x,fx,movebadprint) + flast = fx + end if + + + write(*,dash3_line) + write(*,*) ' Starting GENCAN loop: ', loop + write(*,*) ' Scaling radii by: ', radscale + write(*,*) + + ! CALL GENCAN + + write(*,prog1_line) + call pgencan(n,x,fx) + + ! + ! Compute the statistics of the last optimization loop + ! + + ! Use the user-specified radii for statistics + + do i = 1, ntotat + radiuswork(i) = radius(i) + radius(i) = radius_ini(i) + end do + call computef(n,x,fx) + + if(bestf.gt.0.d0) fimprov = -100.d0 * (fx - bestf) / bestf + if(bestf.eq.0.d0) fimprov = 100.d0 + if(flast.gt.0.d0) fimp = -100.d0 * (fx - flast) / flast + if(flast.eq.0.d0) fimp = 100.d0 + fimp = dmin1(99.99d0,dmax1(-99.99d0,fimp)) + fimprov = dmin1(99.99d0,dmax1(-99.99d0,fimprov)) + + write(*,"(/& + &' Function value from last GENCAN loop: f = ', e10.5, /& + &' Best function value before: f = ', e10.5, /& + &' Improvement from best function value: ', f8.2, ' %',/& + &' Improvement from last loop: ', f8.2, ' %', /& + &' Maximum violation of target distance: ', f12.6, /& + &' Maximum violation of the constraints: ', e10.5 & + &)") fx, bestf, fimprov, fimp, fdist, frest + flast = fx + + ! + ! Analysis of final loop packing and output data + ! + + if ( itype <= ntype ) then + + ! Save best function value for this packing + + if ( fx < bestf ) bestf = fx + + ! Check if this point is a solution + + call swaptype(n,x,itype,2) ! Save this type current point + ! If the solution was found for this type + if( fdist < precision .and. frest < precision ) then + call swaptype(n,x,itype,3) ! Restore all molecule vectors + call output(n,x) + write(*,*) ' Current structure written to file: ', trim(adjustl(xyzout)) + if ( crd ) write(*,*) ' ... and to CRD file: ', trim(adjustl(crdfile)) + call writesuccess(itype,fdist,frest,fx) + exit gencanloop + end if + + ! Compute and report function value for all-type packing + + call swaptype(n,x,itype,3) ! Restore all molecule vectors + call computef(n,x,all_type_fx) + write(*,"(' All-type function value: ', e10.5 )") all_type_fx + + else + + call computef(n,x,fx) + all_type_fx = fx + if ( fx < bestf ) bestf = fx + ! If solution was found for all system + if ( fdist < precision .and. frest < precision ) then + call output(n,x) + call writesuccess(itype,fdist,frest,fx) + write(*,*) ' Solution written to file: ', trim(adjustl(xyzout)) + if ( crd ) write(*,*) ' ... and to CRD file: ', trim(adjustl(crdfile)) + write(*,dash3_line) + exit main + end if + + end if + write(*,dash3_line) + + ! If this is the best structure so far + if( mod(loop+1,writeout) == 0 .and. all_type_fx < fprint ) then + call output(n,x) + write(*,*) ' Current solution written to file: ', trim(adjustl(xyzout)) + if ( crd ) write(*,*) ' ... and to CRD file: ', trim(adjustl(crdfile)) + fprint = all_type_fx + do i = 1, n + xprint(i) = x(i) + end do + + ! If the user required printing even bad structures + else if ( mod(loop+1,writeout) == 0 .and. writebad ) then + call output(n,x) + write(*,*) ' Writing current (perhaps bad) structure to file: ', trim(adjustl(xyzout)) + if ( crd ) write(*,*) ' ... and to CRD file: ', trim(adjustl(crdfile)) + end if + + ! Restore vector for packing this type of molecule, if the case + + if ( itype <= ntype ) then + call swaptype(n,x,itype,0) ! Reset type vectors + call swaptype(n,x,itype,1) ! Set vector for molecules of this type + call computef(n,x,fx) + end if + + ! Restore the working radii + + do i = 1, ntotat + radius(i) = radiuswork(i) + end do + if ( radscale > 1.d0 ) then + if( ( fdist < precision .and. fimp < 10.d0 ) .or. & + fimp < 2.d0 ) then + radscale = dmax1(0.9*radscale,1.d0) + do i = 1, ntotat + radius(i) = dmax1(radius_ini(i),0.9d0*radius(i)) + end do + end if + end if + + if(loop.eq.nloop) then + if ( itype .eq. ntype+1 ) then + write(*,*)' STOP: Maximum number of GENCAN loops achieved.' + call checkpoint(n,xprint) + exit main + else + write(*,*)' Maximum number of GENCAN loops achieved.' + end if + end if + + end do gencanloop + + end if + + end do main + + write(*,*) ' Running time: ', etime(tarray) - time0,' seconds. ' + write(*,dash3_line) + write(*,*) + +end program packmol + diff --git a/tests/packmol/pgencan.f90 b/tests/packmol/pgencan.f90 new file mode 100644 index 00000000..3da6df36 --- /dev/null +++ b/tests/packmol/pgencan.f90 @@ -0,0 +1,98 @@ +! +! Written by Ernesto G. Birgin, 2009-2011. +! Copyright (c) 2009-2018, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Subroutine pgencan: This is only a interface to set some +! parameters. What might be important here +! is the setup of the constraint_axis constraint. +! + +subroutine pgencan(n,x,fx) + + use sizes + use compute_data + use usegencan + implicit none + + double precision :: lambda(1), rho(1) + double precision :: epsgpsn,gpsupn,delmin + double precision :: x(n), fx + integer :: m,iprint,maxfc,ncomp,iter,fcnt,gcnt,cgcnt,inform + integer :: n, i + integer :: trtype1 + integer :: itype, imol + + ! Setup upper and lower bounds for variables. Usually there are none, + ! but one might want to restrict the rotation of the molecules in one + ! or more axis + + do i = 1,n/2 + l(i) = - 1.0d+20 + u(i) = 1.0d+20 + end do + i = n/2 + do itype = 1, ntype + do imol = 1, nmols(itype) + if ( constrain_rot(itype,1) ) then + l(i+1) = rot_bound(itype,1,1) - dabs(rot_bound(itype,1,2)) + u(i+1) = rot_bound(itype,1,1) + dabs(rot_bound(itype,1,2)) + else + l(i+1) = - 1.0d+20 + u(i+1) = 1.0d+20 + end if + if ( constrain_rot(itype,2) ) then + l(i+2) = rot_bound(itype,2,1) - dabs(rot_bound(itype,2,2)) + u(i+2) = rot_bound(itype,2,1) + dabs(rot_bound(itype,2,2)) + else + l(i+2) = - 1.0d+20 + u(i+2) = 1.0d+20 + end if + if ( constrain_rot(itype,3) ) then + l(i+3) = rot_bound(itype,3,1) - dabs(rot_bound(itype,3,2)) + u(i+3) = rot_bound(itype,3,1) + dabs(rot_bound(itype,3,2)) + else + l(i+3) = - 1.0d+20 + u(i+3) = 1.0d+20 + end if + i = i + 3 + end do + end do + + m = 0 + epsgpsn = 1.0d-06 + maxfc = 10 * maxit + if(init1) iprint = iprint1 + if(.not.init1) iprint = iprint2 + ncomp = 50 + delmin = 2.d0 + trtype1 = 1 + + call easygencan(n,x,l,u,m,lambda,rho,epsgpsn,maxit,maxfc,& + trtype1,iprint,ncomp,fx,g,gpsupn,iter,fcnt,& + gcnt,cgcnt,inform,wi,wd,delmin) + if( inform.ne.7 .and.(iprint1.gt.0 .or. iprint2.gt.0) ) write(*,*) + + return +end subroutine pgencan + +! +! Function that test convergence according to Packmol precision +! + +function packmolprecision(n,x) + use input, only : precision + use compute_data, only : fdist, frest + implicit none + integer :: n + double precision :: f, x(n) + logical :: packmolprecision + + call computef(n,x,f) + + packmolprecision = .false. + if ( fdist < precision .and. frest < precision ) then + packmolprecision = .true. + end if + +end function packmolprecision diff --git a/tests/packmol/polartocart.f90 b/tests/packmol/polartocart.f90 new file mode 100644 index 00000000..5007ff37 --- /dev/null +++ b/tests/packmol/polartocart.f90 @@ -0,0 +1,106 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Subroutine eulerrmat: Computes the rotation matrix from the +! Euler angles +! +! Note that: +! In this routine, beta is a rotation about the y-axis +! gama is a rotation about the z-axis +! teta is a rotation about the x-axis + +subroutine eulerrmat(beta,gama,teta,v1,v2,v3) + + implicit none + double precision :: beta, gama, teta + double precision :: cb, sb, cg, sg, ct, st + double precision :: v1(3), v2(3), v3(3) + + cb = dcos(beta) + sb = dsin(beta) + cg = dcos(gama) + sg = dsin(gama) + ct = dcos(teta) + st = dsin(teta) + + v1(1)=-sb * sg * ct + cb * cg + v1(2)=-sb * cg * ct - cb * sg + v1(3)= sb * st + + v2(1)= cb * sg * ct + sb * cg + v2(2)= cb * cg * ct - sb * sg + v2(3)=-cb * st + + v3(1)= sg * st + v3(2)= cg * st + v3(3)= ct + + return +end subroutine eulerrmat + +! +! Subroutine compcart: Compute cartesian coordinates using +! the center of mass, the canonical coordinates +! and the rotation matrix +! + +subroutine compcart(icart,xbar,ybar,zbar,& + xcoor,ycoor,zcoor,v1,v2,v3) + + use compute_data, only : xcart + implicit none + integer :: icart + double precision :: xbar, ybar, zbar + double precision :: xcoor, ycoor, zcoor + double precision :: v1(3), v2(3), v3(3) + + xcart(icart,1) = xbar + xcoor*v1(1) + ycoor*v2(1) + zcoor*v3(1) + xcart(icart,2) = ybar + xcoor*v1(2) + ycoor*v2(2) + zcoor*v3(2) + xcart(icart,3) = zbar + xcoor*v1(3) + ycoor*v2(3) + zcoor*v3(3) + + return +end subroutine compcart + +! +! Subroutine eulerfixed: This routine was added because it defines +! the rotation in the "human" way, an is thus used +! to set the position of the fixed molecules. +! That means: beta is a counterclockwise rotation around x axis. +! gama is a counterclockwise rotation around y axis. +! teta is a counterclockwise rotation around z axis. +! The other routine should better do this as well, but then we need to change +! all the derivative calculations, just for the sake of human interpretation +! of the rotation which, in that case, is not really important. Maybe some day. +! + +subroutine eulerfixed(beta,gama,teta,v1,v2,v3) + + implicit none + double precision :: beta, gama, teta + double precision :: c1, s1, c2, s2, c3, s3 + double precision :: v1(3), v2(3), v3(3) + + c1 = dcos(beta) + s1 = dsin(beta) + c2 = dcos(gama) + s2 = dsin(gama) + c3 = dcos(teta) + s3 = dsin(teta) + + v1(1) = c2*c3 + v1(2) = c1*s3 + c3*s1*s2 + v1(3) = s1*s3 - c1*c3*s2 + + v2(1) = -c2*s3 + v2(2) = c1*c3 - s1*s2*s3 + v2(3) = c1*s2*s3 + c3*s1 + + v3(1) = s2 + v3(2) = -c2*s1 + v3(3) = c1*c2 + + return +end subroutine eulerfixed + diff --git a/tests/packmol/random.f90 b/tests/packmol/random.f90 new file mode 100644 index 00000000..05beeacb --- /dev/null +++ b/tests/packmol/random.f90 @@ -0,0 +1,50 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! + +! +! Function that returns a real random number between 0. and 1. +! + +double precision function rnd() + + call random_number(rnd) + + return +end function rnd + +! +! Subroutine that initializes the random number generator given a seed +! + +subroutine init_random_number(iseed) + integer :: size + integer :: i, iseed + integer, allocatable :: seed(:) + call random_seed(size=size) + allocate(seed(size)) + do i = 1, size + seed(i) = i*iseed + end do + call random_seed(put=seed) + deallocate(seed) + return +end subroutine init_random_number + +! +! Subroutine that uses the date to create a random seed +! + +subroutine seed_from_time(seed) + + implicit none + integer :: seed, value(8) + character(len=10) :: b(3) + call date_and_time( b(1), b(2), b(3), value ) + seed = value(1)+value(2)+value(3)+value(4)+value(5)+value(6)+value(7)+value(8) + seed = seed + value(1)+value(2)+value(3)+value(4)+value(5)/100+value(6)*100+value(7)/10+value(8)*10 + +end subroutine seed_from_time + diff --git a/tests/packmol/release.sh b/tests/packmol/release.sh new file mode 100755 index 00000000..6816b73f --- /dev/null +++ b/tests/packmol/release.sh @@ -0,0 +1,69 @@ +#!/bin/bash +#################################################################################################### + +# Software name: + +package=packmol + +# Release version, read from command line: +version="$1" + +# GIT URL: + +giturl=https://github.com/m3g/packmol + +# Name of file containing version number + +versionfile=./title.f90 + +#################################################################################################### + +#git log --pretty=oneline 16.323...16.330 | awk '{$1=""; print "-"$0}' + +year=`date +%y` +day=`date +%j` +#version="${year:0:1}${year:1:1}.$day" +if [[ $version < " " ]]; then + echo "ERROR: Please provide version number, with: ./release.sh 20.1.1" + exit +fi + +file="$package-$version.tar.gz" +echo "Will create file: $file" + +cat $versionfile | sed -e "s/Version.*/Version\ $version \')\")/" > version_title_temp.f90 +\mv -f version_title_temp.f90 $versionfile + +git add -A . +git commit -m "Changed version file to $version" +git tag -a "v$version" -m "Release $version" +git push origin master tag "v$version" + +today=`date +"%b %d, %Y"` +changelog="https://github.com/m3g/$package/releases/tag/v$version" +newline=" $file Released on $today - [change log at github] " + +echo "------------------------------" +echo "CREATING RELEASE IN HOME-PAGE:" +echo "------------------------------" +mkdir TEMP +cd TEMP +wget https://github.com/m3g/packmol/archive/v$version.tar.gz +tar -xf v$version.tar.gz +mv packmol-$version packmol +tar -cf packmol.tar ./packmol +gzip packmol.tar +#scp packmol.tar.gz martinez@ssh.ime.unicamp.br:./public_html/packmol/ +\cp -f packmol.tar.gz ~/public_html/m3g/packmol/packmol.tar.gz +cd .. +\rm -rf ./TEMP + +echo "----------------------" +echo "CHANGE LOG:" +echo "----------------------" +range=`git tag | tail -n 2 | xargs | sed 's! !...!'` +git log --pretty=oneline $range | awk '{$1=""; print "-"$0}' +echo "----------------------" + +echo " Done. " + diff --git a/tests/packmol/resetboxes.f90 b/tests/packmol/resetboxes.f90 new file mode 100644 index 00000000..9598400c --- /dev/null +++ b/tests/packmol/resetboxes.f90 @@ -0,0 +1,30 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Subroutine resetboxes: Subroutine that resets the occupancy of +! linked cell boxes +! + +subroutine resetboxes() + + use sizes + use compute_data, only : latomfirst, latomfix, & + lboxfirst, lboxnext, hasfree + implicit none + integer :: i, j, k, ibox + + ! Reset data for boxes that contain fixed atom + + ibox = lboxfirst + do while( ibox > 0 ) + call ibox_to_ijk(ibox,i,j,k) + latomfirst(i,j,k) = latomfix(i,j,k) + hasfree(i,j,k) = .false. + ibox = lboxnext(ibox) + end do + lboxfirst = 0 + +end subroutine resetboxes + diff --git a/tests/packmol/restmol.f90 b/tests/packmol/restmol.f90 new file mode 100644 index 00000000..8466cb3d --- /dev/null +++ b/tests/packmol/restmol.f90 @@ -0,0 +1,86 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! subroutine restmol: either compute the restraint function +! value for a single molecule or solve +! the problem of puting this molecule +! in the restraint region +! + +subroutine restmol(itype,ilubar,n,x,fx,solve) + + use sizes + use compute_data + use usegencan + implicit none + + integer :: n, nsafe, ntotsafe, itype, i, ilubar, nmoltype, ip1, ip2 + double precision :: x(n), fx + logical :: solve, initsafe + + ! Saving global problem variables + + nsafe = n + ntotsafe = ntotmol + nmoltype = nmols(itype) + do i = 1, ntype + compsafe(i) = comptype(i) + end do + initsafe = init1 + + ! Preparing system to solve for this molecule + + n = 6 + ntotmol = 1 + nmols(itype) = 1 + xmol(1) = x(ilubar+1) + xmol(2) = x(ilubar+2) + xmol(3) = x(ilubar+3) + xmol(4) = x(ilubar+ntotsafe*3+1) + xmol(5) = x(ilubar+ntotsafe*3+2) + xmol(6) = x(ilubar+ntotsafe*3+3) + do i = 1, ntype + if(i.eq.itype) then + comptype(i) = .true. + else + comptype(i) = .false. + end if + end do + init1 = .true. + + ! If not going to solve the problem, compute energy and return + + if(.not.solve) then + call computef(n,xmol,fx) + ! Otherwise, put this molecule in its constraints + else + ip1 = iprint1 + ip2 = iprint2 + iprint1 = 0 + iprint2 = 0 + call pgencan(n,xmol,fx) + iprint1 = ip1 + iprint2 = ip2 + end if + + ! Restoring original problem data + + ntotmol = ntotsafe + n = nsafe + nmols(itype) = nmoltype + x(ilubar+1) = xmol(1) + x(ilubar+2) = xmol(2) + x(ilubar+3) = xmol(3) + x(ilubar+ntotmol*3+1) = xmol(4) + x(ilubar+ntotmol*3+2) = xmol(5) + x(ilubar+ntotmol*3+3) = xmol(6) + do i = 1, ntype + comptype(i) = compsafe(i) + end do + init1 = initsafe + + return +end subroutine restmol + diff --git a/tests/packmol/setibox.f90 b/tests/packmol/setibox.f90 new file mode 100644 index 00000000..36f9b940 --- /dev/null +++ b/tests/packmol/setibox.f90 @@ -0,0 +1,30 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Subroutine setibox: set box index for given coordinates +! + +subroutine setibox(x,y,z,sizemin,boxl,nboxes,iboxx,iboxy,iboxz) + + implicit none + double precision :: x, y, z, sizemin(3), boxl(3), xtemp, ytemp, ztemp + integer :: nboxes(3), iboxx, iboxy, iboxz + + xtemp = x - sizemin(1) + ytemp = y - sizemin(2) + ztemp = z - sizemin(3) + iboxx = int(xtemp/boxl(1)) + 1 + iboxy = int(ytemp/boxl(2)) + 1 + iboxz = int(ztemp/boxl(3)) + 1 + if(xtemp.le.0) iboxx = 1 + if(ytemp.le.0) iboxy = 1 + if(ztemp.le.0) iboxz = 1 + if(iboxx.gt.nboxes(1)) iboxx = nboxes(1) + if(iboxy.gt.nboxes(2)) iboxy = nboxes(2) + if(iboxz.gt.nboxes(3)) iboxz = nboxes(3) + + return +end subroutine setibox + diff --git a/tests/packmol/setijk.f90 b/tests/packmol/setijk.f90 new file mode 100644 index 00000000..dbfc14ef --- /dev/null +++ b/tests/packmol/setijk.f90 @@ -0,0 +1,46 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Subroutines that set the indexes of a three-dimensional array +! given the undimensional counter of the vector (for an array +! with dimensions (0:nboxes(1)+1,0:nboxes(2)+1,0:nboxes(3)+1), and +! vice-versa. +! + +subroutine ibox_to_ijk(ibox,i,j,k) + + use compute_data, only : nb2 + implicit none + integer :: ibox, i, j, k, iibox + + k = mod(ibox,nb2(3)) + if ( k == 0 ) k = nb2(3) + + iibox = ibox - k + iibox = iibox / nb2(3) + 1 + j = mod(iibox,nb2(2)) + if ( j == 0 ) j = nb2(2) + + iibox = iibox - j + iibox = iibox / nb2(2) + 1 + i = mod(iibox,nb2(1)) + if ( i == 0 ) i = nb2(1) + + k = k - 1 + j = j - 1 + i = i - 1 + +end subroutine ibox_to_ijk + +subroutine ijk_to_ibox(i,j,k,ibox) + + use compute_data, only : nb2 + implicit none + integer :: i, j, k, ibox + + ibox = i*nb2(2)*nb2(3) + j*nb2(3) + k + 1 + +end subroutine ijk_to_ibox + diff --git a/tests/packmol/setsizes.f90 b/tests/packmol/setsizes.f90 new file mode 100644 index 00000000..4c844b53 --- /dev/null +++ b/tests/packmol/setsizes.f90 @@ -0,0 +1,363 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Subroutine that sets the sizes of all allocatable arrays +! + +subroutine setsizes() + + use sizes + use compute_data + use input + use usegencan + use flashsort + + implicit none + integer :: i, ival, ilast, iline, itype + integer :: ioerr + integer :: strlength + character(len=strl) :: record, word, blank, alltospace + logical :: inside_structure + + ! Instructions on how to run packmol + + write(*,*) ' Packmol must be run with: packmol < inputfile.inp ' + write(*,*) + write(*,*) ' Userguide at: http://m3g.iqm.unicamp.br/packmol ' + write(*,*) + + ! Getting input lines from the input file + + write(*,*) ' Reading input file... (Control-C aborts)' + + do i = 1, strl + blank(i:i) = ' ' + end do + nlines = 0 + maxkeywords = 0 + ntype = 0 + do + read(5,str_format,iostat=ioerr) record + + ! Replace any strange blank character by spaces + record = alltospace(record) + + if ( ioerr /= 0 ) exit + + ! Remove comments + i = 0 + do while( i < strl ) + i = i + 1 + if ( record(i:i) == '#' ) exit + end do + i = i - 1 + if ( i > 0 ) then + record = record(1:i)//blank(i+1:strl) + else + cycle + end if + if ( strlength(record) < 1 ) cycle + record = trim(record) + + ! + ! Convert file name paths with spaces to single strings + ! + ! check for quotes and replace spaces by @ + call parse_spaces(record) + + ! Number of lines of the input file + + nlines = nlines + 1 + + ! Check the number of keywords in this line + + i = 0 + ival = 0 + do while(i < strl) + i = i + 1 + ilast = i + do while(record(i:i) > ' ' .and. i < strl) + i = i + 1 + end do + if(i > ilast) then + ival = ival + 1 + maxkeywords = max(maxkeywords,ival) + end if + end do + end do + rewind(5) + + allocate(inputfile(nlines),keyword(nlines,maxkeywords)) + + ! Read input to inputfile array + + iline = 0 + do + read(5,str_format,iostat=ioerr) record + if ( ioerr /= 0 ) exit + + ! Convert all strange blank characters to spaces + + record = alltospace(record) + call parse_spaces(record) + + ! Remove comments + + i = 0 + do while( i < strl ) + i = i + 1 + if ( record(i:i) == '#' ) exit + end do + i = i - 1 + if ( i > 0 ) then + record = record(1:i)//blank(i+1:strl) + else + cycle + end if + if ( strlength(record) < 1 ) cycle + + iline = iline + 1 + inputfile(iline) = record + end do + + ! Read all keywods into keyword array + + call getkeywords() + + ! Checking the filetype of coordinate files (default is pdb) + + tinker = .false. + pdb = .false. + xyz = .false. + moldy = .false. + fbins = dsqrt(3.d0) + do i = 1, nlines + if(keyword(i,1).eq.'filetype') then + if(keyword(i,2).eq.'tinker') tinker = .true. + if(keyword(i,2).eq.'pdb') pdb = .true. + if(keyword(i,2).eq.'xyz') xyz = .true. + if(keyword(i,2).eq.'moldy') moldy = .true. + end if + if(keyword(i,1).eq.'fbins') then + record = keyword(i,2) + read(record,*,iostat=ioerr) fbins + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Invalid value for fbins. ' + stop + end if + end if + end do + if(.not.pdb.and..not.tinker.and..not.xyz.and..not.moldy) then + pdb = .true. + write(*,*) + write(*,*)' WARNING: File type not (correctly?) specified, using PDB' + end if + + ! Getting the number of different types of molecules + + ntype = 0 + do iline = 1, nlines + if ( keyword(iline,1) == "structure" ) then + ntype = ntype + 1 + if ( keyword(iline,2) == "none" ) then + write(*,*) ' ERROR: structure without filename. ' + write(*,*) ' The syntax must be, for example: structure water.pdb ' + stop + end if + end if + end do + + allocate(nmols(ntype),natoms(ntype),idfirst(ntype),constrain_rot(ntype,3),& + rot_bound(ntype,3,2),dmax(ntype),& + cmxmin(ntype),cmymin(ntype),cmzmin(ntype),& + cmxmax(ntype),cmymax(ntype),cmzmax(ntype),& + comptype(ntype),compsafe(ntype),& + restart_from(0:ntype),restart_to(0:ntype),& + nloop_type(ntype),nloop0_type(ntype)) + + ! Reading the number of molecules of each type, and the number of atoms + ! of each molecule type + + itype = 0 + inside_structure = .false. + do iline = 1, nlines + if ( keyword(iline,1) == "structure" ) then + inside_structure = .true. + itype = itype + 1 + natoms(itype) = 0 + nmols(itype) = 0 + nloop_type(itype) = 0 + nloop0_type(itype) = 0 + + ! Read the number of atoms of this type of molecule + + open(10,file=keyword(iline,2),status='old',iostat=ioerr) + if( ioerr /= 0 ) call failopen(keyword(iline,2)) + if ( pdb ) then + do + read(10,str_format,iostat=ioerr) record + if ( ioerr /= 0 ) exit + if ( record(1:4) == "ATOM" .or. record(1:6) == "HETATM" ) then + natoms(itype) = natoms(itype) + 1 + end if + end do + end if + if ( tinker ) then + do + read(10,*,iostat=ioerr) i + if ( ioerr /= 0 ) cycle + natoms(itype) = i + exit + end do + end if + if ( xyz ) then + read(10,*,iostat=ioerr) i + if ( ioerr == 0 ) natoms(itype) = i + end if + if ( moldy ) then + read(10,*,iostat=ioerr) word, i + if ( ioerr == 0 ) natoms(itype) = i + end if + close(10) + if ( natoms(itype) == 0 ) then + write(*,*) ' ERROR: Could not read any atom from file: ', & + trim(adjustl(keyword(iline,2))) + end if + + end if + + if ( keyword(iline,1) == "end" .and. & + keyword(iline,2) == "structure" ) inside_structure = .false. + + ! Read number of molecules for each type + + if ( keyword(iline,1) == "number" ) then + read(keyword(iline,2),*,iostat=ioerr) nmols(itype) + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Error reading number of molecules of type ', itype + stop + end if + if ( nmols(itype) < 1 ) then + write(*,*) ' ERROR: Number of molecules of type ', itype, ' set to less than 1 ' + stop + end if + end if + + ! Read the (optional) number of gencan loops for this molecule + + if ( keyword(iline,1) == "nloop" ) then + if ( inside_structure ) then + read(keyword(iline,2),*,iostat=ioerr) nloop_type(itype) + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Error reading number of loops of type ', itype + stop + end if + if ( nloop_type(itype) < 1 ) then + write(*,*) ' ERROR: Number of loops of type ', itype, ' set to less than 1 ' + stop + end if + end if + end if + + ! Read the (optional) number of gencan loops for initial setup for this molecule + + if ( keyword(iline,1) == "nloop0" ) then + if ( inside_structure ) then + read(keyword(iline,2),*,iostat=ioerr) nloop0_type(itype) + if ( ioerr /= 0 ) then + write(*,*) ' ERROR: Error reading number of loops-0 of type ', itype + stop + end if + if ( nloop0_type(itype) < 1 ) then + write(*,*) ' ERROR: Number of loops-0 of type ', itype, ' set to less than 1 ' + stop + end if + end if + end if + + end do + do itype = 1, ntype + if ( nmols(itype) == 0 ) then + write(*,*) ' Warning: Number of molecules not set for type '& + ,itype,': assuming 1 ' + nmols(itype) = 1 + end if + end do + + ! Total number of atoms and molecules + + ntotat = 0 + ntotmol = 0 + do itype = 1, ntype + ntotat = ntotat + nmols(itype)*natoms(itype) + ntotmol = ntotmol + nmols(itype) + end do + + ! The number of variables of the problem + + nn = ntotmol*6 + + ! The number of bins of the linked cell method in each direction + + nbp = int((fbins*dble(ntotat))**(1.d0/3.d0)) + 1 + + ! Allocate arrays depending on nbp parameter + + allocate(latomfirst(0:nbp+1,0:nbp+1,0:nbp+1),& + latomfix(0:nbp+1,0:nbp+1,0:nbp+1),& + hasfree(0:nbp+1,0:nbp+1,0:nbp+1),& + lboxnext((nbp+2)**3)) + + ! Checking the total number of restrictions defined + + i = 0 + do iline = 1, nlines + if ( keyword(iline,1) == 'fixed' .or. & + keyword(iline,1) == 'inside' .or. & + keyword(iline,1) == 'outside' .or. & + keyword(iline,1) == 'over' .or. & + keyword(iline,1) == 'above' .or. & + keyword(iline,1) == 'below' .or. & + keyword(iline,1) == 'constrain_rotation' ) then + i = i + 1 + end if + end do + maxrest = i + mrperatom = i + + ! Allocate arrays depending on ntotat, nn, maxrest, and mrperatom + + allocate(nratom(ntotat),iratom(ntotat,mrperatom),ibmol(ntotat),& + ibtype(ntotat),xcart(ntotat,3),coor(ntotat,3),& + radius(ntotat),radius_ini(ntotat),fscale(ntotat),& + use_short_radius(ntotat), short_radius(ntotat), short_radius_scale(ntotat),& + gxcar(ntotat,3),& + latomnext(ntotat),& + fdist_atom(ntotat), frest_atom(ntotat),& + fmol(ntotat),radiuswork(ntotat),& + fixedatom(ntotat)) + allocate(ityperest(maxrest),restpars(maxrest,9)) + allocate(xmol(nn)) + + ! Allocate other arrays used for input and output data + + allocate(nconnect(ntotat,9),maxcon(ntotat),& + amass(ntotat),charge(ntotat),ele(ntotat)) + + allocate(irestline(maxrest),linestrut(ntype,2),resnumbers(ntype),& + input_itype(ntype),changechains(ntype),chain(ntype),& + fixedoninput(ntype),pdbfile(ntype),name(ntype),& + segid(ntype),maxmove(ntype),connect(ntype)) + + ! Allocate vectors for flashsort + + allocate(indflash(ntotat),lflash(ntotat)) + + ! Allocate arrays for GENCAN + + allocate(l(nn),u(nn),wd(8*nn),wi(nn),g(nn)) + +end subroutine setsizes + diff --git a/tests/packmol/sizes.f90 b/tests/packmol/sizes.f90 new file mode 100644 index 00000000..640b757b --- /dev/null +++ b/tests/packmol/sizes.f90 @@ -0,0 +1,31 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! +! sizes.i: Define the maximum dimensions of the problems +! +! maxrest: Maximum number of restrictions +! mrperatom: Maximum number of restrictions per atom +! maxtry: Number of tries for building the initial point +! nbp: Maximum number of boxes for fast function evaluation (nbp**3) +! nn: Maximum number of variables +! (at least the number of molecules*6) +! maxkeywords: Maximum number of keywords in input file +! + +module sizes + + integer :: maxrest + integer :: mrperatom + integer :: maxtry + integer :: nbp + integer :: nn + integer :: maxkeywords + + integer, parameter :: strl = 1000 + character(len=*), parameter :: str_format = "( a1000 )" + +end module sizes + diff --git a/tests/packmol/solvate.tcl b/tests/packmol/solvate.tcl new file mode 100755 index 00000000..df97b8a7 --- /dev/null +++ b/tests/packmol/solvate.tcl @@ -0,0 +1,7625 @@ +#!/usr/bin/tclsh +# +# This scripts writes a input file for packmol, and runs packmol, +# that automatically setup +# a solvation shell with 0.16 sodium and chloride concentrations such +# that the whole system is neutral, considering neutral histidines and +# charged +# +# Make it executable with: chmod +x solvate.tcl +# Run with: ./solvate.tcl structure.pdb -shell 15. -charge +5 -density 1.0 -o solvated.pdb +# +# Where: +# structure.pdb is the pdb file to be solvated (usually a protein) +# +# "15." is the size of the solvation shell. This +# is an optional parameter. If not set, 15. will be used. +# +# +5 is the total charge of the system, to be neutralized. +# This is also and optional parameter, if not used, the package +# considers histidine residues as neutral, Arg and Lys as +1 +# and Glu and Asp as -1, and sets up the Sodium and Chloride +# concentrations automatically. +# Alternatively, use the -noions to not add any ions, just water. +# +# 1.0 is the desired density. Optional. If not set, the density +# will be set to 1.0 g/ml. +# +# solvated.pdb: is the (optional) name for the solvated system output +# file. If this argument is not provided, it will be the default +# "solvated.pdb" file. +# +# pack.inp: is the (optional) name for the packmol input file that +# will be generated. If not provided, packmol_input.inp will be used. +# +# L. Martinez, Aug 2, 2011. (leandromartinez98@gmail.com) +# + +set args [ split $argv " " ] +set iarg 0 +foreach arg $args { + if { [ string trim $arg ] > " " } { + incr iarg + set input_argument($iarg) $arg + } +} +if { $iarg == 0 } { +puts " " +puts " Solvate.tcl script for Packmol " +puts " " +puts " Run with: " +puts " " +puts " solvate.tcl structure.pdb -shell 15. -charge +5 -density 1.0 -i pack.inp -o solvated.pdb" +puts " + Where: + structure.pdb is the pdb file to be solvated (usually a protein) + + \"15.\" is the size of the solvation shell. This + is an optional parameter. If not set, 15. will be used. + + +5 is the total charge of the system, to be neutralized. + This is also and optional parameter, if not used, the package + considers histidine residues as neutral, Arg and Lys as +1 + and Glu and Asp as -1. The Na+ and Cl- concentrations are set + the closest possible to 0.16M, approximately the physiological + concentration. + Alternatively, use the -noions to not add any ions, just water. + + 1.0 is the desired density. Optional. If not set, the density + will be set to 1.0 g/ml. + + solvated.pdb: is the (optional) name for the solvated system output + file. If this argument is not provided, it will be the default + solvated.pdb file. + + pack.inp: is the (optional) name for the packmol input file that + will be generated. If not provided, packmol_input.inp will be used. +" +exit +} + +set pdb_file $input_argument(1) +set charge "none" +set shell "none" +set density "none" +set output "solvated.pdb" +set packmol_input "packmol_input.inp" +set noions "false" +for { set i 2 } { $i <= $iarg } { incr i } { + if { $input_argument($i) == "-charge" } { set charge $input_argument([expr $i + 1]) } + if { $input_argument($i) == "-shell" } { set shell $input_argument([expr $i + 1]) } + if { $input_argument($i) == "-density" } { set density $input_argument([expr $i + 1]) } + if { $input_argument($i) == "-o" } { set output $input_argument([expr $i + 1]) } + if { $input_argument($i) == "-i" } { set packmol_input $input_argument([expr $i + 1]) } + if { $input_argument($i) == "-noions" } { set noions "true" } +} + +puts " ###########################################################################" +puts " solvate.tcl script: Solvates a (protein) structure with water and ions," +puts " using Packmol. " +puts " ###########################################################################" + +puts " Input pdb file to be solvated: $pdb_file " +puts -nonewline " User set structure charge: $charge " +if { $charge == "none" } { puts " - will compute from structure. " } else { puts " " } +puts -nonewline " User set shell size: $shell " +if { $shell == "none" } { puts " - using default: 15.0 Angs. " } else { puts " " } +puts -nonewline " User set density: $density " +if { $density == "none" } { puts " - using default: 1.0 g/ml " } else { puts " " } + +# If the user didn't set the sell size, use default one + +if { $shell == "none" } { set shell 15. } + +# +# Computing the size of the structure (maximum and minimum size on each direction) +# + +set pdb_file_name $pdb_file +set pdb_file [ open $pdb_file r ] +set pdb_file [ read $pdb_file ] +set pdb_file [ split $pdb_file "\n" ] + +set natoms 0 +foreach line $pdb_file { + if { [ string range $line 0 3 ] == "ATOM" | + [ string range $line 0 5 ] == "HETATM" } { + incr natoms + set x [ string trim [ string range $line 30 37 ] ] + set y [ string trim [ string range $line 38 45 ] ] + set z [ string trim [ string range $line 46 54 ] ] + if { [ info exists xmin ] == 1 } { + if { $x < $xmin } { set xmin $x } + if { $y < $ymin } { set ymin $y } + if { $z < $zmin } { set zmin $z } + if { $x > $xmax } { set xmax $x } + if { $y > $ymax } { set ymax $y } + if { $z > $zmax } { set zmax $z } + } else { + set xmin $x + set ymin $y + set zmin $z + set xmax $x + set ymax $y + set zmax $z + } + } +} + +set x_length [ expr $xmax - $xmin + 2.0*$shell ] +set y_length [ expr $ymax - $ymin + 2.0*$shell ] +set z_length [ expr $zmax - $zmin + 2.0*$shell ] + +puts " -------------------------------------------------------" +puts " Minimum and maximum coordinates of structure atoms " +puts " X_min = $xmin X_max = $xmax " +puts " Y_min = $ymin Y_max = $ymax " +puts " Z_min = $zmin Z_max = $zmax " +puts " -------------------------------------------------------" +puts " Box side length in each direction: " +puts " x: $x_length " +puts " y: $y_length " +puts " z: $z_length " +puts " -------------------------------------------------------" + +# +# If the user didn't set the total charge of the system, compute the charge +# + +if { $charge == "none" } { + set charge 0 + set number 0 + set nhis 0; set narg 0; set nlys 0; set nglu 0; set nasp 0 + foreach line $pdb_file { + set amino [string range $line 17 19] + if { [ string trim [ string range $line 12 15 ] ] == "N" } { + if { $amino == "HIS" } { incr nhis } + if { $amino == "HSD" } { incr nhis } + if { $amino == "ARG" } { set charge [expr $charge + 1]; incr narg } + if { $amino == "LYS" } { set charge [expr $charge + 1]; incr nlys } + if { $amino == "GLU" } { set charge [expr $charge - 1]; incr nglu } + if { $amino == "ASP" } { set charge [expr $charge - 1]; incr nasp } + } + } + puts " -------------------------------------------------------" + puts " HIS = $nhis (associated charge = 0) " + puts " ARG = $narg (associated charge = +$narg) " + puts " LYS = $nlys (associated charge = +$nlys) " + puts " GLU = $nglu (associated charge = -$nglu) " + puts " ASP = $nasp (associated charge = -$nasp) " + puts " -------------------------------------------------------" + puts " Total structure charge = $charge" + puts " -------------------------------------------------------" +} + +# +# Compute the molar mass of the structure +# + +foreach data { \ +"H 1.00800 " \ +"HC 1.00800 " \ +"HA 1.00800 " \ +"HT 1.00800 " \ +"HP 1.00800 " \ +"HB 1.00800 " \ +"HR1 1.00800 " \ +"HR2 1.00800 " \ +"HR3 1.00800 " \ +"HS 1.00800 " \ +"HE1 1.00800 " \ +"HE2 1.00800 " \ +"HA1 1.00800 " \ +"HA2 1.00800 " \ +"HA3 1.00800 " \ +"HF1 1.00800 " \ +"HF2 1.00800 " \ +"C 12.01100 " \ +"CA 12.01100 " \ +"CT1 12.01100 " \ +"CT2 12.01100 " \ +"CT3 12.01100 " \ +"CPH1 12.01100 " \ +"CPH2 12.01100 " \ +"CPT 12.01100 " \ +"CY 12.01100 " \ +"CP1 12.01100 " \ +"CP2 12.01100 " \ +"CP3 12.01100 " \ +"CC 12.01100 " \ +"CD 12.01100 " \ +"CPA 12.01100 " \ +"CPB 12.01100 " \ +"CPM 12.01100 " \ +"CM 12.01100 " \ +"CS 12.01100 " \ +"CE1 12.01100 " \ +"CE2 12.01100 " \ +"CST 12.01100 " \ +"CT 12.01100 " \ +"CT1x 12.01100 " \ +"CT2x 12.01100 " \ +"CT3x 12.01100 " \ +"CN 12.01100 " \ +"CAP 12.01100 " \ +"COA 12.01100 " \ +"C3 12.01100 " \ +"N 14.00700 " \ +"NR1 14.00700 " \ +"NR2 14.00700 " \ +"NR3 14.00700 " \ +"NH1 14.00700 " \ +"NH2 14.00700 " \ +"NH3 14.00700 " \ +"NC2 14.00700 " \ +"NY 14.00700 " \ +"NP 14.00700 " \ +"NPH 14.00700 " \ +"NC 14.00700 " \ +"O 15.99900 " \ +"OB 15.99900 " \ +"OC 15.99900 " \ +"OH1 15.99900 " \ +"OS 15.99940 " \ +"OT 15.99940 " \ +"OM 15.99900 " \ +"OST 15.99900 " \ +"OCA 15.99900 " \ +"S 32.06000 " \ +"SM 32.06000 " \ +"SS 32.06000 " \ +"HE 4.00260 " \ +"NE 20.17970 " \ +"CF1 12.01100 " \ +"CF2 12.01100 " \ +"CF3 12.01100 " \ +"FE 55.84700 " \ +"CLAL 35.45300 " \ +"FA 18.99800 " \ +"F1 18.99800 " \ +"F2 18.99800 " \ +"F3 18.99800 " \ +"DUM 0.00000 " \ +"SOD 22.989770 " \ +"MG 24.305000 " \ +"POT 39.102000 " \ +"CES 132.900000 " \ +"CAL 40.080000 " \ +"CLA 35.450000 " \ +"ZN 65.370000 " \ +"H 1.00800 " \ +"HC 1.00800 " \ +"HA 1.00800 " \ +"HT 1.00800 " \ +"HP 1.00800 " \ +"HB 1.00800 " \ +"HR1 1.00800 " \ +"HR2 1.00800 " \ +"HR3 1.00800 " \ +"HS 1.00800 " \ +"HE1 1.00800 " \ +"HE2 1.00800 " \ +"HA1 1.00800 " \ +"HA2 1.00800 " \ +"HA3 1.00800 " \ +"HF1 1.00800 " \ +"HF2 1.00800 " \ +"C 12.01100 " \ +"CA 12.01100 " \ +"CT1 12.01100 " \ +"CT2 12.01100 " \ +"CT3 12.01100 " \ +"CPH1 12.01100 " \ +"CPH2 12.01100 " \ +"CPT 12.01100 " \ +"CY 12.01100 " \ +"CP1 12.01100 " \ +"CP2 12.01100 " \ +"CP3 12.01100 " \ +"CC 12.01100 " \ +"CD 12.01100 " \ +"CPA 12.01100 " \ +"CPB 12.01100 " \ +"CPM 12.01100 " \ +"CM 12.01100 " \ +"CS 12.01100 " \ +"CE1 12.01100 " \ +"CE2 12.01100 " \ +"CST 12.01100 " \ +"CT 12.01100 " \ +"CT1x 12.01100 " \ +"CT2x 12.01100 " \ +"CT3x 12.01100 " \ +"CN 12.01100 " \ +"CAP 12.01100 " \ +"COA 12.01100 " \ +"C3 12.01100 " \ +"N 14.00700 " \ +"NR1 14.00700 " \ +"NR2 14.00700 " \ +"NR3 14.00700 " \ +"NH1 14.00700 " \ +"NH2 14.00700 " \ +"NH3 14.00700 " \ +"NC2 14.00700 " \ +"NY 14.00700 " \ +"NP 14.00700 " \ +"NPH 14.00700 " \ +"NC 14.00700 " \ +"O 15.99900 " \ +"OB 15.99900 " \ +"OC 15.99900 " \ +"OH1 15.99900 " \ +"OS 15.99940 " \ +"OT 15.99940 " \ +"OM 15.99900 " \ +"OST 15.99900 " \ +"OCA 15.99900 " \ +"S 32.06000 " \ +"SM 32.06000 " \ +"SS 32.06000 " \ +"HE 4.00260 " \ +"NE 20.17970 " \ +"CF1 12.01100 " \ +"CF2 12.01100 " \ +"CF3 12.01100 " \ +"FE 55.84700 " \ +"CLAL 35.45300 " \ +"FA 18.99800 " \ +"F1 18.99800 " \ +"F2 18.99800 " \ +"F3 18.99800 " \ +"DUM 0.00000 " \ +"SOD 22.989770 " \ +"MG 24.305000 " \ +"POT 39.102000 " \ +"CES 132.900000 " \ +"CAL 40.080000 " \ +"CLA 35.450000 " \ +"ZN 65.370000 " \ +"HT 1.00800 " \ +"OT 15.99940 " \ +"HAS 1.00800 " \ +"HOS 1.00800 " \ +"CTS 12.01100 " \ +"CBS 12.01100 " \ +"OHS 15.99940 " \ +"OES 15.99940 " \ +"OXT 15.99940 " \ +"HL 1.008000 " \ +"HCL 1.008000 " \ +"HT 1.008000 " \ +"HOL 1.008000 " \ +"HAL1 1.008000 " \ +"HAL2 1.008000 " \ +"HAL3 1.008000 " \ +"HEL1 1.008000 " \ +"HEL2 1.008000 " \ +"CL 12.011000 " \ +"CTL1 12.011000 " \ +"CTL2 12.011000 " \ +"CTL3 12.011000 " \ +"CTL5 12.011000 " \ +"CEL1 12.011000 " \ +"CEL2 12.011000 " \ +"NTL 14.007000 " \ +"NH3L 14.007000 " \ +"OBL 15.999400 " \ +"OCL 15.999400 " \ +"OT 15.999400 " \ +"OSL 15.999400 " \ +"O2L 15.999400 " \ +"OHL 15.999400 " \ +"PL 30.974000 " \ +"SL 32.060000 " \ +"SOD 22.989770 " \ +"MG 24.305000 " \ +"POT 39.102000 " \ +"CES 132.900000 " \ +"CAL 40.080000 " \ +"CLA 35.450000 " \ +"ZN 65.370000 " \ +"DUM 0.000000 " \ +"HT 1.008000 " \ +"HN1 1.008000 " \ +"HN2 1.008000 " \ +"HN3 1.008000 " \ +"HN3B 1.008000 " \ +"HN3C 1.008000 " \ +"HNP 1.008000 " \ +"HN4 1.008000 " \ +"HN5 1.008000 " \ +"HN6 1.008000 " \ +"HN7 1.008000 " \ +"HN8 1.008000 " \ +"HN9 1.008000 " \ +"HNE1 1.008000 " \ +"HNE2 1.008000 " \ +"CN1 12.011000 " \ +"CN1A 12.011000 " \ +"CN1T 12.011000 " \ +"CN2 12.011000 " \ +"CN3 12.011000 " \ +"CN3A 12.011000 " \ +"CN3B 12.011000 " \ +"CN3C 12.011000 " \ +"CN3D 12.011000 " \ +"CN3T 12.011000 " \ +"CN4 12.011000 " \ +"CN5 12.011000 " \ +"CN5G 12.011000 " \ +"CN7 12.011000 " \ +"CN7B 12.011000 " \ +"CN7C 12.011000 " \ +"CN7D 12.011000 " \ +"CN8 12.011000 " \ +"CN8B 12.011000 " \ +"CN9 12.011000 " \ +"CNE1 12.011000 " \ +"CNE2 12.011000 " \ +"CNA 12.011000 " \ +"CNA2 12.011000 " \ +"CN6 12.011000 " \ +"CN7E 12.011000 " \ +"NN1 14.007000 " \ +"NN1C 14.007000 " \ +"NN2 14.007000 " \ +"NN2B 14.007000 " \ +"NN2C 14.007000 " \ +"NN2U 14.007000 " \ +"NN2G 14.007000 " \ +"NN3 14.007000 " \ +"NN3A 14.007000 " \ +"NN3I 14.007000 " \ +"NN3G 14.007000 " \ +"NN4 14.007000 " \ +"NN5 14.007000 " \ +"NN6 14.007000 " \ +"OT 15.999400 " \ +"ON1 15.999400 " \ +"ON1C 15.999400 " \ +"ON2 15.999400 " \ +"ON3 15.999400 " \ +"ON4 15.999400 " \ +"ON5 15.999400 " \ +"ON6 15.999400 " \ +"ON6B 15.999400 " \ +"ON2B 15.999400 " \ +"FN1 18.998400 " \ +"FNA 18.998400 " \ +"P 30.974000 " \ +"P2 30.974000 " \ +"P3 30.974000 " \ +"SOD 22.989770 " \ +"MG 24.305000 " \ +"POT 39.102000 " \ +"CES 132.900000 " \ +"CAL 40.080000 " \ +"CLA 35.450000 " \ +"ZN 65.370000 " \ +"DUM 0.001 " \ +"CPH1 12.011000 " \ +"CPH2 12.011000 " \ +"HR3 1.008000 " \ +"HR1 1.008000 " \ +"NR1 14.007000 " \ +"NR2 14.007000 " \ +"HL 1.008000 " \ +"HCL 1.008000 " \ +"HT 1.008000 " \ +"HOL 1.008000 " \ +"HAL1 1.008000 " \ +"HAL2 1.008000 " \ +"HAL3 1.008000 " \ +"HEL1 1.008000 " \ +"HEL2 1.008000 " \ +"CL 12.011000 " \ +"CTL1 12.011000 " \ +"CTL2 12.011000 " \ +"CTL3 12.011000 " \ +"CTL5 12.011000 " \ +"CEL1 12.011000 " \ +"CEL2 12.011000 " \ +"NTL 14.007000 " \ +"NH3L 14.007000 " \ +"OBL 15.999400 " \ +"OCL 15.999400 " \ +"OT 15.999400 " \ +"OSL 15.999400 " \ +"O2L 15.999400 " \ +"OHL 15.999400 " \ +"PL 30.974000 " \ +"SL 32.060000 " \ +"CPH1 12.011000 " \ +"CPH2 12.011000 " \ +"HR3 1.008000 " \ +"HR1 1.008000 " \ +"NR1 14.007000 " \ +"NR2 14.007000 " \ +"HT 1.008000 " \ +"HN1 1.008000 " \ +"HN2 1.008000 " \ +"HN3 1.008000 " \ +"HN3B 1.008000 " \ +"HN3C 1.008000 " \ +"HNP 1.008000 " \ +"HN4 1.008000 " \ +"HN5 1.008000 " \ +"HN6 1.008000 " \ +"HN7 1.008000 " \ +"HN8 1.008000 " \ +"HN9 1.008000 " \ +"HNE1 1.008000 " \ +"HNE2 1.008000 " \ +"CN1 12.011000 " \ +"CN1A 12.011000 " \ +"CN1T 12.011000 " \ +"CN2 12.011000 " \ +"CN3 12.011000 " \ +"CN3A 12.011000 " \ +"CN3B 12.011000 " \ +"CN3C 12.011000 " \ +"CN3D 12.011000 " \ +"CN3T 12.011000 " \ +"CN4 12.011000 " \ +"CN5 12.011000 " \ +"CN5G 12.011000 " \ +"CN7 12.011000 " \ +"CN7B 12.011000 " \ +"CN7C 12.011000 " \ +"CN7D 12.011000 " \ +"CN8 12.011000 " \ +"CN8B 12.011000 " \ +"CN9 12.011000 " \ +"CNE1 12.011000 " \ +"CNE2 12.011000 " \ +"CNA 12.011000 " \ +"CNA2 12.011000 " \ +"CN6 12.011000 " \ +"CN7E 12.011000 " \ +"NN1 14.007000 " \ +"NN1C 14.007000 " \ +"NN2 14.007000 " \ +"NN2B 14.007000 " \ +"NN2C 14.007000 " \ +"NN2U 14.007000 " \ +"NN2G 14.007000 " \ +"NN3 14.007000 " \ +"NN3A 14.007000 " \ +"NN3I 14.007000 " \ +"NN3G 14.007000 " \ +"NN4 14.007000 " \ +"NN5 14.007000 " \ +"NN6 14.007000 " \ +"OT 15.999400 " \ +"ON1 15.999400 " \ +"ON1C 15.999400 " \ +"ON2 15.999400 " \ +"ON3 15.999400 " \ +"ON4 15.999400 " \ +"ON5 15.999400 " \ +"ON6 15.999400 " \ +"ON6B 15.999400 " \ +"ON2B 15.999400 " \ +"FN1 18.998400 " \ +"FNA 18.998400 " \ +"P 30.974000 " \ +"P2 30.974000 " \ +"P3 30.974000 " \ +"SOD 22.989770 " \ +"MG 24.305000 " \ +"POT 39.102000 " \ +"CES 132.900000 " \ +"CAL 40.080000 " \ +"CLA 35.450000 " \ +"ZN 65.370000 " \ +"DUM 0.001 " \ +"CPH1 12.011000 " \ +"CPH2 12.011000 " \ +"HR3 1.008000 " \ +"HR1 1.008000 " \ +"NR1 14.007000 " \ +"NR2 14.007000 " \ +"H 1.00800 " \ +"HC 1.00800 " \ +"HA 1.00800 " \ +"HT 1.00800 " \ +"HP 1.00800 " \ +"HB 1.00800 " \ +"HR1 1.00800 " \ +"HR2 1.00800 " \ +"HR3 1.00800 " \ +"HS 1.00800 " \ +"HE1 1.00800 " \ +"HE2 1.00800 " \ +"HA1 1.00800 " \ +"HA2 1.00800 " \ +"HA3 1.00800 " \ +"HF1 1.00800 " \ +"HF2 1.00800 " \ +"C 12.01100 " \ +"CA 12.01100 " \ +"CT1 12.01100 " \ +"CT2 12.01100 " \ +"CT3 12.01100 " \ +"CPH1 12.01100 " \ +"CPH2 12.01100 " \ +"CPT 12.01100 " \ +"CY 12.01100 " \ +"CP1 12.01100 " \ +"CP2 12.01100 " \ +"CP3 12.01100 " \ +"CC 12.01100 " \ +"CD 12.01100 " \ +"CPA 12.01100 " \ +"CPB 12.01100 " \ +"CPM 12.01100 " \ +"CM 12.01100 " \ +"CS 12.01100 " \ +"CE1 12.01100 " \ +"CE2 12.01100 " \ +"CST 12.01100 " \ +"CT 12.01100 " \ +"CT1x 12.01100 " \ +"CT2x 12.01100 " \ +"CT3x 12.01100 " \ +"CN 12.01100 " \ +"CAP 12.01100 " \ +"COA 12.01100 " \ +"C3 12.01100 " \ +"N 14.00700 " \ +"NR1 14.00700 " \ +"NR2 14.00700 " \ +"NR3 14.00700 " \ +"NH1 14.00700 " \ +"NH2 14.00700 " \ +"NH3 14.00700 " \ +"NC2 14.00700 " \ +"NY 14.00700 " \ +"NP 14.00700 " \ +"NPH 14.00700 " \ +"NC 14.00700 " \ +"O 15.99900 " \ +"OB 15.99900 " \ +"OC 15.99900 " \ +"OH1 15.99900 " \ +"OS 15.99940 " \ +"OT 15.99940 " \ +"OM 15.99900 " \ +"OST 15.99900 " \ +"OCA 15.99900 " \ +"S 32.06000 " \ +"SM 32.06000 " \ +"SS 32.06000 " \ +"HE 4.00260 " \ +"NE 20.17970 " \ +"CF1 12.01100 " \ +"CF2 12.01100 " \ +"CF3 12.01100 " \ +"FE 55.84700 " \ +"CLAL 35.45300 " \ +"FA 18.99800 " \ +"F1 18.99800 " \ +"F2 18.99800 " \ +"F3 18.99800 " \ +"DUM 0.00000 " \ +"HL 1.008000 " \ +"HCL 1.008000 " \ +"HT 1.008000 " \ +"HOL 1.008000 " \ +"HAL1 1.008000 " \ +"HAL2 1.008000 " \ +"HAL3 1.008000 " \ +"HEL1 1.008000 " \ +"HEL2 1.008000 " \ +"CL 12.011000 " \ +"CTL1 12.011000 " \ +"CTL2 12.011000 " \ +"CTL3 12.011000 " \ +"CTL5 12.011000 " \ +"CEL1 12.011000 " \ +"CEL2 12.011000 " \ +"NTL 14.007000 " \ +"NH3L 14.007000 " \ +"OBL 15.999400 " \ +"OCL 15.999400 " \ +"OT 15.999400 " \ +"OSL 15.999400 " \ +"O2L 15.999400 " \ +"OHL 15.999400 " \ +"PL 30.974000 " \ +"SL 32.060000 " \ +"SOD 22.989770 " \ +"MG 24.305000 " \ +"POT 39.102000 " \ +"CES 132.900000 " \ +"CAL 40.080000 " \ +"CLA 35.450000 " \ +"ZN 65.370000 " \ +"HN1 1.008000 " \ +"HN2 1.008000 " \ +"HN3 1.008000 " \ +"HN3B 1.008000 " \ +"HN3C 1.008000 " \ +"HNP 1.008000 " \ +"HN4 1.008000 " \ +"HN5 1.008000 " \ +"HN6 1.008000 " \ +"HN7 1.008000 " \ +"HN8 1.008000 " \ +"HN9 1.008000 " \ +"HNE1 1.008000 " \ +"HNE2 1.008000 " \ +"CN1 12.011000 " \ +"CN1A 12.011000 " \ +"CN1T 12.011000 " \ +"CN2 12.011000 " \ +"CN3 12.011000 " \ +"CN3A 12.011000 " \ +"CN3B 12.011000 " \ +"CN3C 12.011000 " \ +"CN3D 12.011000 " \ +"CN3T 12.011000 " \ +"CN4 12.011000 " \ +"CN5 12.011000 " \ +"CN5G 12.011000 " \ +"CN7 12.011000 " \ +"CN7B 12.011000 " \ +"CN7C 12.011000 " \ +"CN7D 12.011000 " \ +"CN8 12.011000 " \ +"CN8B 12.011000 " \ +"CN9 12.011000 " \ +"CNE1 12.011000 " \ +"CNE2 12.011000 " \ +"CNA 12.011000 " \ +"CNA2 12.011000 " \ +"CN6 12.011000 " \ +"CN7E 12.011000 " \ +"NN1 14.007000 " \ +"NN1C 14.007000 " \ +"NN2 14.007000 " \ +"NN2B 14.007000 " \ +"NN2C 14.007000 " \ +"NN2U 14.007000 " \ +"NN2G 14.007000 " \ +"NN3 14.007000 " \ +"NN3A 14.007000 " \ +"NN3I 14.007000 " \ +"NN3G 14.007000 " \ +"NN4 14.007000 " \ +"NN5 14.007000 " \ +"NN6 14.007000 " \ +"ON1 15.999400 " \ +"ON1C 15.999400 " \ +"ON2 15.999400 " \ +"ON3 15.999400 " \ +"ON4 15.999400 " \ +"ON5 15.999400 " \ +"ON6 15.999400 " \ +"ON6B 15.999400 " \ +"ON2B 15.999400 " \ +"FN1 18.998400 " \ +"FNA 18.998400 " \ +"P 30.974000 " \ +"P2 30.974000 " \ +"P3 30.974000 " \ +"SOD 22.989770 " \ +"MG 24.305000 " \ +"POT 39.102000 " \ +"CES 132.900000 " \ +"CAL 40.080000 " \ +"CLA 35.450000 " \ +"ZN 65.370000 " \ +"DUM 0.001 " \ +"H 1.00800 " \ +"HC 1.00800 " \ +"HA 1.00800 " \ +"HT 1.00800 " \ +"HP 1.00800 " \ +"HR1 1.00800 " \ +"HR2 1.00800 " \ +"HR3 1.00800 " \ +"HS 1.00800 " \ +"HE1 1.00800 " \ +"HE2 1.00800 " \ +"HA1 1.00800 " \ +"HA2 1.00800 " \ +"HA3 1.00800 " \ +"HB1 1.00800 " \ +"HB2 1.00800 " \ +"C 12.01100 " \ +"CA 12.01100 " \ +"CT1 12.01100 " \ +"CT2 12.01100 " \ +"CT3 12.01100 " \ +"CPH1 12.01100 " \ +"CPH2 12.01100 " \ +"CPT 12.01100 " \ +"CY 12.01100 " \ +"CP1 12.01100 " \ +"CP2 12.01100 " \ +"CP3 12.01100 " \ +"CC 12.01100 " \ +"CD 12.01100 " \ +"CPA 12.01100 " \ +"CPB 12.01100 " \ +"CPM 12.01100 " \ +"CM 12.01100 " \ +"CS 12.01100 " \ +"CE1 12.01100 " \ +"CE2 12.01100 " \ +"N 14.00700 " \ +"NR1 14.00700 " \ +"NR2 14.00700 " \ +"NR3 14.00700 " \ +"NH1 14.00700 " \ +"NH2 14.00700 " \ +"NH3 14.00700 " \ +"NC2 14.00700 " \ +"NY 14.00700 " \ +"NP 14.00700 " \ +"NPH 14.00700 " \ +"O 15.99900 " \ +"OB 15.99900 " \ +"OC 15.99900 " \ +"OH1 15.99900 " \ +"OS 15.99940 " \ +"OT 15.99940 " \ +"OM 15.99900 " \ +"S 32.06000 " \ +"SM 32.06000 " \ +"SS 32.06000 " \ +"HE 4.00260 " \ +"NE 20.17970 " \ +"LP 0.000000 " \ +"CAL 40.08000 " \ +"ZN 65.37000 " \ +"FE 55.84700 " \ +"DUM 0.00000 " \ +"H 1.00800 " \ +"HC 1.00800 " \ +"HA 1.00800 " \ +"HT 1.00800 " \ +"LP 0.0 " \ +"CT 12.01100 " \ +"C 12.01100 " \ +"CH1E 13.01900 " \ +"CH2E 14.02700 " \ +"CH3E 15.03500 " \ +"CR1E 13.01900 " \ +"CM 12.01100 " \ +"N 14.00670 " \ +"NR 14.00670 " \ +"NP 14.00670 " \ +"NH1E 15.01470 " \ +"NH2E 16.02270 " \ +"NH3E 17.03070 " \ +"NC2E 16.02270 " \ +"NH1 14.00670 " \ +"NH2 14.00670 " \ +"NH3 14.00670 " \ +"NC2 14.00670 " \ +"O 15.99940 " \ +"OC 15.99940 " \ +"OH1E 17.00740 " \ +"OH2E 18.01540 " \ +"OH1 15.99940 " \ +"OH2 15.99940 " \ +"OM 15.99940 " \ +"OT 15.99940 " \ +"OS 15.99940 " \ +"S 32.06000 " \ +"SH1E 33.06800 " \ +"FE 55.84700 " \ +"H 1.00800 " \ +"H2 1.00800 " \ +"HO 1.00800 " \ +"HT 1.00800 " \ +"LP 0.0 " \ +"C 12.01100 " \ +"CH 13.01900 " \ +"C2 14.02700 " \ +"CA 12.01100 " \ +"CB 12.01100 " \ +"CE 13.01900 " \ +"CF 13.01900 " \ +"C3 15.03500 " \ +"CS 12.01100 " \ +"N2 14.00670 " \ +"NA 14.00670 " \ +"NB 14.00670 " \ +"NC 14.00670 " \ +"NS 14.00670 " \ +"NH2E 16.02270 " \ +"NH3 14.00670 " \ +"O 15.99940 " \ +"O2 15.99940 " \ +"OS 15.99940 " \ +"OH 15.99940 " \ +"OH2 15.99940 " \ +"OT 15.99940 " \ +"OSS 15.99940 " \ +"OST 15.99940 " \ +"SD 22.98980 " \ +"P 30.97400 " \ +"BR 79.90400 " \ +"MG 24.30500 " +} { + set data [ split $data " " ] + set i 0 + foreach value $data { + if { $value > " " } { incr i; set val($i) $value } + if { $i == 2 } { + set mass($val(1)) $val(2) + } + } +} + +# +# Charm atom classes +# + +foreach data { \ +"S S " \ +"O1 OC " \ +"O2 OC " \ +"O3 OC " \ +"O4 OC " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT3 " \ +"HB1 HA " \ +"HB2 HA " \ +"HB3 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"CD CT2 " \ +"HD1 HA " \ +"HD2 HA " \ +"NE NC2 " \ +"HE HC " \ +"CZ C " \ +"NH1 NC2 " \ +"HH11 HC " \ +"HH12 HC " \ +"NH2 NC2 " \ +"HH21 HC " \ +"HH22 HC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CC " \ +"OD1 O " \ +"ND2 NH2 " \ +"HD21 H " \ +"HD22 H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CC " \ +"OD1 OC " \ +"OD2 OC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"SG S " \ +"HG1 HS " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"CD CC " \ +"OE1 O " \ +"NE2 NH2 " \ +"HE21 H " \ +"HE22 H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"CD CC " \ +"OE1 OC " \ +"OE2 OC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT2 " \ +"HA1 HB " \ +"HA2 HB " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"ND1 NR1 " \ +"HD1 H " \ +"CG CPH1 " \ +"CE1 CPH2 " \ +"HE1 HR1 " \ +"NE2 NR2 " \ +"CD2 CPH1 " \ +"HD2 HR3 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"ND1 NR2 " \ +"CG CPH1 " \ +"CE1 CPH2 " \ +"HE1 HR1 " \ +"NE2 NR1 " \ +"HE2 H " \ +"CD2 CPH1 " \ +"HD2 HR3 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CD2 CPH1 " \ +"HD2 HR1 " \ +"CG CPH1 " \ +"NE2 NR3 " \ +"HE2 H " \ +"ND1 NR3 " \ +"HD1 H " \ +"CE1 CPH2 " \ +"HE1 HR2 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT1 " \ +"HB HA " \ +"CG2 CT3 " \ +"HG21 HA " \ +"HG22 HA " \ +"HG23 HA " \ +"CG1 CT2 " \ +"HG11 HA " \ +"HG12 HA " \ +"CD CT3 " \ +"HD1 HA " \ +"HD2 HA " \ +"HD3 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT1 " \ +"HG HA " \ +"CD1 CT3 " \ +"HD11 HA " \ +"HD12 HA " \ +"HD13 HA " \ +"CD2 CT3 " \ +"HD21 HA " \ +"HD22 HA " \ +"HD23 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"CD CT2 " \ +"HD1 HA " \ +"HD2 HA " \ +"CE CT2 " \ +"HE1 HA " \ +"HE2 HA " \ +"NZ NH3 " \ +"HZ1 HC " \ +"HZ2 HC " \ +"HZ3 HC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"SD S " \ +"CE CT3 " \ +"HE1 HA " \ +"HE2 HA " \ +"HE3 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CA " \ +"CD1 CA " \ +"HD1 HP " \ +"CE1 CA " \ +"HE1 HP " \ +"CZ CA " \ +"HZ HP " \ +"CD2 CA " \ +"HD2 HP " \ +"CE2 CA " \ +"HE2 HP " \ +"C C " \ +"O O " \ +"N N " \ +"CD CP3 " \ +"HD1 HA " \ +"HD2 HA " \ +"CA CP1 " \ +"HA HB " \ +"CB CP2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CP2 " \ +"HG1 HA " \ +"HG2 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"OG OH1 " \ +"HG1 H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT1 " \ +"HB HA " \ +"OG1 OH1 " \ +"HG1 H " \ +"CG2 CT3 " \ +"HG21 HA " \ +"HG22 HA " \ +"HG23 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CY " \ +"CD1 CA " \ +"HD1 HP " \ +"NE1 NY " \ +"HE1 H " \ +"CE2 CPT " \ +"CD2 CPT " \ +"CE3 CA " \ +"HE3 HP " \ +"CZ3 CA " \ +"HZ3 HP " \ +"CZ2 CA " \ +"HZ2 HP " \ +"CH2 CA " \ +"HH2 HP " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CA " \ +"CD1 CA " \ +"HD1 HP " \ +"CE1 CA " \ +"HE1 HP " \ +"CZ CA " \ +"OH OH1 " \ +"HH H " \ +"CD2 CA " \ +"HD2 HP " \ +"CE2 CA " \ +"HE2 HP " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT1 " \ +"HB HA " \ +"CG1 CT3 " \ +"HG11 HA " \ +"HG12 HA " \ +"HG13 HA " \ +"CG2 CT3 " \ +"HG21 HA " \ +"HG22 HA " \ +"HG23 HA " \ +"C C " \ +"O O " \ +"CL CT3 " \ +"HL1 HA " \ +"HL2 HA " \ +"HL3 HA " \ +"CLP C " \ +"OL O " \ +"NL NH1 " \ +"HL H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT3 " \ +"HB1 HA " \ +"HB2 HA " \ +"HB3 HA " \ +"CRP C " \ +"OR O " \ +"NR NH1 " \ +"HR H " \ +"CR CT3 " \ +"HR1 HA " \ +"HR2 HA " \ +"HR3 HA " \ +"OH2 OT " \ +"H1 HT " \ +"H2 HT " \ +"OH2 OT " \ +"H1 HT " \ +"H2 HT " \ +"SOD SOD " \ +"MG MG " \ +"POT POT " \ +"CES CES " \ +"CAL CAL " \ +"CLA CLA " \ +"ZN ZN " \ +"N NH3 " \ +"HT1 HC " \ +"HT2 HC " \ +"HT3 HC " \ +"CA CT1 " \ +"HA HB " \ +"N NH3 " \ +"HT1 HC " \ +"HT2 HC " \ +"HT3 HC " \ +"CA CT2 " \ +"HA1 HB " \ +"HA2 HB " \ +"N NP " \ +"HN1 HC " \ +"HN2 HC " \ +"CD CP3 " \ +"HD1 HA " \ +"HD2 HA " \ +"CA CP1 " \ +"HA HB " \ +"CAY CT3 " \ +"HY1 HA " \ +"HY2 HA " \ +"HY3 HA " \ +"CY C " \ +"OY O " \ +"CAY CT3 " \ +"HY1 HA " \ +"HY2 HA " \ +"HY3 HA " \ +"CY C " \ +"OY O " \ +"CAY CT3 " \ +"HY1 HA " \ +"HY2 HA " \ +"HY3 HA " \ +"CY C " \ +"OY O " \ +"CAY CT3 " \ +"HY1 HA " \ +"HY2 HA " \ +"HY3 HA " \ +"CY C " \ +"OY O " \ +"C CC " \ +"OT1 OC " \ +"OT2 OC " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"C CD " \ +"OT1 OB " \ +"OT2 OS " \ +"CT CT3 " \ +"HT1 HA " \ +"HT2 HA " \ +"HT3 HA " \ +"C CC " \ +"O O " \ +"NT NH2 " \ +"HT1 H " \ +"HT2 H " \ +"C C " \ +"O O " \ +"NT NH1 " \ +"HNT H " \ +"CAT CT3 " \ +"HT1 HA " \ +"HT2 HA " \ +"HT3 HA " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CD " \ +"OD1 OB " \ +"OD2 OH1 " \ +"HD2 H " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"CD CD " \ +"OE1 OB " \ +"OE2 OH1 " \ +"HE2 H " \ +"CE CT2 " \ +"HE1 HA " \ +"HE2 HA " \ +"NZ NH2 " \ +"HZ1 HC " \ +"HZ2 HC " \ +"1CB CT2 " \ +"1SG SM " \ +"2SG SM " \ +"2CB CT2 " \ +"CE1 CPH2 " \ +"HE1 HR1 " \ +"ND1 NR2 " \ +"CG CPH1 " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"NE2 NR1 " \ +"HE2 H " \ +"CD2 CPH1 " \ +"HD2 HR3 " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT3 " \ +"HB1 HA " \ +"HB2 HA " \ +"HB3 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"CD CT2 " \ +"HD1 HA " \ +"HD2 HA " \ +"NE NC2 " \ +"HE HC " \ +"CZ C " \ +"NH1 NC2 " \ +"HH11 HC " \ +"HH12 HC " \ +"NH2 NC2 " \ +"HH21 HC " \ +"HH22 HC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CC " \ +"OD1 O " \ +"ND2 NH2 " \ +"HD21 H " \ +"HD22 H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CC " \ +"OD1 OC " \ +"OD2 OC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"SG S " \ +"HG1 HS " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"CD CC " \ +"OE1 O " \ +"NE2 NH2 " \ +"HE21 H " \ +"HE22 H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"CD CC " \ +"OE1 OC " \ +"OE2 OC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT2 " \ +"HA1 HB " \ +"HA2 HB " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"ND1 NR1 " \ +"HD1 H " \ +"CG CPH1 " \ +"CE1 CPH2 " \ +"HE1 HR1 " \ +"NE2 NR2 " \ +"CD2 CPH1 " \ +"HD2 HR3 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"ND1 NR2 " \ +"CG CPH1 " \ +"CE1 CPH2 " \ +"HE1 HR1 " \ +"NE2 NR1 " \ +"HE2 H " \ +"CD2 CPH1 " \ +"HD2 HR3 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CD2 CPH1 " \ +"HD2 HR1 " \ +"CG CPH1 " \ +"NE2 NR3 " \ +"HE2 H " \ +"ND1 NR3 " \ +"HD1 H " \ +"CE1 CPH2 " \ +"HE1 HR2 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT1 " \ +"HB HA " \ +"CG2 CT3 " \ +"HG21 HA " \ +"HG22 HA " \ +"HG23 HA " \ +"CG1 CT2 " \ +"HG11 HA " \ +"HG12 HA " \ +"CD CT3 " \ +"HD1 HA " \ +"HD2 HA " \ +"HD3 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT1 " \ +"HG HA " \ +"CD1 CT3 " \ +"HD11 HA " \ +"HD12 HA " \ +"HD13 HA " \ +"CD2 CT3 " \ +"HD21 HA " \ +"HD22 HA " \ +"HD23 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"CD CT2 " \ +"HD1 HA " \ +"HD2 HA " \ +"CE CT2 " \ +"HE1 HA " \ +"HE2 HA " \ +"NZ NH3 " \ +"HZ1 HC " \ +"HZ2 HC " \ +"HZ3 HC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"SD S " \ +"CE CT3 " \ +"HE1 HA " \ +"HE2 HA " \ +"HE3 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CA " \ +"CD1 CA " \ +"HD1 HP " \ +"CE1 CA " \ +"HE1 HP " \ +"CZ CA " \ +"HZ HP " \ +"CD2 CA " \ +"HD2 HP " \ +"CE2 CA " \ +"HE2 HP " \ +"C C " \ +"O O " \ +"N N " \ +"CD CP3 " \ +"HD1 HA " \ +"HD2 HA " \ +"CA CP1 " \ +"HA HB " \ +"CB CP2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CP2 " \ +"HG1 HA " \ +"HG2 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"OG OH1 " \ +"HG1 H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT1 " \ +"HB HA " \ +"OG1 OH1 " \ +"HG1 H " \ +"CG2 CT3 " \ +"HG21 HA " \ +"HG22 HA " \ +"HG23 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CY " \ +"CD1 CA " \ +"HD1 HP " \ +"NE1 NY " \ +"HE1 H " \ +"CE2 CPT " \ +"CD2 CPT " \ +"CE3 CA " \ +"HE3 HP " \ +"CZ3 CA " \ +"HZ3 HP " \ +"CZ2 CA " \ +"HZ2 HP " \ +"CH2 CA " \ +"HH2 HP " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CA " \ +"CD1 CA " \ +"HD1 HP " \ +"CE1 CA " \ +"HE1 HP " \ +"CZ CA " \ +"OH OH1 " \ +"HH H " \ +"CD2 CA " \ +"HD2 HP " \ +"CE2 CA " \ +"HE2 HP " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT1 " \ +"HB HA " \ +"CG1 CT3 " \ +"HG11 HA " \ +"HG12 HA " \ +"HG13 HA " \ +"CG2 CT3 " \ +"HG21 HA " \ +"HG22 HA " \ +"HG23 HA " \ +"C C " \ +"O O " \ +"CL CT3 " \ +"HL1 HA " \ +"HL2 HA " \ +"HL3 HA " \ +"CLP C " \ +"OL O " \ +"NL NH1 " \ +"HL H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT3 " \ +"HB1 HA " \ +"HB2 HA " \ +"HB3 HA " \ +"CRP C " \ +"OR O " \ +"NR NH1 " \ +"HR H " \ +"CR CT3 " \ +"HR1 HA " \ +"HR2 HA " \ +"HR3 HA " \ +"OH2 OT " \ +"H1 HT " \ +"H2 HT " \ +"OH2 OT " \ +"H1 HT " \ +"H2 HT " \ +"SOD SOD " \ +"MG MG " \ +"POT POT " \ +"CES CES " \ +"CAL CAL " \ +"CLA CLA " \ +"ZN ZN " \ +"N NH3 " \ +"HT1 HC " \ +"HT2 HC " \ +"HT3 HC " \ +"CA CT1 " \ +"HA HB " \ +"N NH3 " \ +"HT1 HC " \ +"HT2 HC " \ +"HT3 HC " \ +"CA CT2 " \ +"HA1 HB " \ +"HA2 HB " \ +"N NP " \ +"HN1 HC " \ +"HN2 HC " \ +"CD CP3 " \ +"HD1 HA " \ +"HD2 HA " \ +"CA CP1 " \ +"HA HB " \ +"CAY CT3 " \ +"HY1 HA " \ +"HY2 HA " \ +"HY3 HA " \ +"CY C " \ +"OY O " \ +"CAY CT3 " \ +"HY1 HA " \ +"HY2 HA " \ +"HY3 HA " \ +"CY C " \ +"OY O " \ +"C CC " \ +"OT1 OC " \ +"OT2 OC " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"C CD " \ +"OT1 OB " \ +"OT2 OS " \ +"CT CT3 " \ +"HT1 HA " \ +"HT2 HA " \ +"HT3 HA " \ +"C CC " \ +"O O " \ +"NT NH2 " \ +"HT1 H " \ +"HT2 H " \ +"C C " \ +"O O " \ +"NT NH1 " \ +"HNT H " \ +"CAT CT3 " \ +"HT1 HA " \ +"HT2 HA " \ +"HT3 HA " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CD " \ +"OD1 OB " \ +"OD2 OH1 " \ +"HD2 H " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"CD CD " \ +"OE1 OB " \ +"OE2 OH1 " \ +"HE2 H " \ +"CE CT2 " \ +"HE1 HA " \ +"HE2 HA " \ +"NZ NH2 " \ +"HZ1 HC " \ +"HZ2 HC " \ +"1CB CT2 " \ +"1SG SM " \ +"2SG SM " \ +"2CB CT2 " \ +"CE1 CPH2 " \ +"HE1 HR1 " \ +"ND1 NR2 " \ +"CG CPH1 " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"NE2 NR1 " \ +"HE2 H " \ +"CD2 CPH1 " \ +"HD2 HR3 " \ +"C1 CTS " \ +"H1 HAS " \ +"O1 OHS " \ +"HO1 HOS " \ +"C5 CTS " \ +"H5 HAS " \ +"O5 OES " \ +"C2 CTS " \ +"H2 HAS " \ +"O2 OHS " \ +"HO2 HOS " \ +"C3 CTS " \ +"H3 HAS " \ +"O3 OHS " \ +"HO3 HOS " \ +"C4 CTS " \ +"H4 HAS " \ +"O4 OHS " \ +"HO4 HOS " \ +"C6 CTS " \ +"H61 HAS " \ +"H62 HAS " \ +"O6 OHS " \ +"HO6 HOS " \ +"C1 CBS " \ +"N NTL " \ +"C13 CTL5 " \ +"H13A HL " \ +"H13B HL " \ +"H13C HL " \ +"C14 CTL5 " \ +"H14A HL " \ +"H14B HL " \ +"H14C HL " \ +"C15 CTL5 " \ +"H15A HL " \ +"H15B HL " \ +"H15C HL " \ +"C12 CTL2 " \ +"H12A HL " \ +"H12B HL " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"P PL " \ +"O13 O2L " \ +"O14 O2L " \ +"O11 OSL " \ +"O12 OSL " \ +"C1 CTL2 " \ +"HA HAL2 " \ +"HB HAL2 " \ +"C2 CTL2 " \ +"HS HAL2 " \ +"HR HAL2 " \ +"C3 CTL2 " \ +"HX HAL2 " \ +"HY HAL2 " \ +"O31 OSL " \ +"C31 CL " \ +"O32 OBL " \ +"C32 CTL2 " \ +"H2X HAL2 " \ +"H2Y HAL2 " \ +"C33 CTL2 " \ +"H3X HAL2 " \ +"H3Y HAL2 " \ +"C34 CTL2 " \ +"H4X HAL2 " \ +"H4Y HAL2 " \ +"C35 CTL2 " \ +"H5X HAL2 " \ +"H5Y HAL2 " \ +"C36 CTL2 " \ +"H6X HAL2 " \ +"H6Y HAL2 " \ +"C37 CTL2 " \ +"H7X HAL2 " \ +"H7Y HAL2 " \ +"C38 CTL2 " \ +"H8X HAL2 " \ +"H8Y HAL2 " \ +"C39 CTL2 " \ +"H9X HAL2 " \ +"H9Y HAL2 " \ +"C310 CTL2 " \ +"H10X HAL2 " \ +"H10Y HAL2 " \ +"C311 CTL2 " \ +"H11X HAL2 " \ +"H11Y HAL2 " \ +"C312 CTL3 " \ +"H12X HAL3 " \ +"H12Y HAL3 " \ +"H12Z HAL3 " \ +"N NH3 " \ +"HN1 HCL " \ +"HN2 HCL " \ +"HN3 HCL " \ +"C12 CTL " \ +"H12A HAL " \ +"H12B HAL " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"P PL " \ +"O13 O2L " \ +"O14 O2L " \ +"O11 OSL " \ +"O12 OSL " \ +"C1 CTL2 " \ +"HA HAL2 " \ +"HB HAL2 " \ +"C2 CTL1 " \ +"HS HAL1 " \ +"OH2 OHL " \ +"HO2 HOL " \ +"C3 CTL2 " \ +"HX HAL2 " \ +"HY HAL2 " \ +"OH3 OHL " \ +"HO3 HOL " \ +"N NH3 " \ +"HN1 HCL " \ +"HN2 HCL " \ +"HN3 HCL " \ +"C12 CTL " \ +"H12A HAL " \ +"H12B HAL " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"P PL " \ +"O13 O2L " \ +"O14 O2L " \ +"O11 OSL " \ +"O12 OSL " \ +"C1 CTL2 " \ +"HA HAL2 " \ +"HB HAL2 " \ +"C2 CTL1 " \ +"HS HAL1 " \ +"O21 OSL " \ +"C21 CL " \ +"O22 OBL " \ +"C22 CTL2 " \ +"H2R HAL2 " \ +"H2S HAL2 " \ +"C3 CTL2 " \ +"HX HAL2 " \ +"HY HAL2 " \ +"O31 OSL " \ +"C31 CL " \ +"O32 OBL " \ +"C32 CTL2 " \ +"H2X HAL2 " \ +"H2Y HAL2 " \ +"C23 CTL2 " \ +"H3R HAL2 " \ +"H3S HAL2 " \ +"C24 CTL2 " \ +"H4R HAL2 " \ +"H4S HAL2 " \ +"C25 CTL2 " \ +"H5R HAL2 " \ +"H5S HAL2 " \ +"C26 CTL2 " \ +"H6R HAL2 " \ +"H6S HAL2 " \ +"C27 CTL2 " \ +"H7R HAL2 " \ +"H7S HAL2 " \ +"C28 CTL2 " \ +"H8R HAL2 " \ +"H8S HAL2 " \ +"C29 CTL2 " \ +"H9R HAL2 " \ +"H9S HAL2 " \ +"C210 CTL2 " \ +"H10R HAL2 " \ +"H10S HAL2 " \ +"C211 CTL2 " \ +"H11R HAL2 " \ +"H11S HAL2 " \ +"C212 CTL3 " \ +"H12R HAL3 " \ +"H12S HAL3 " \ +"H12T HAL3 " \ +"C33 CTL2 " \ +"H3X HAL2 " \ +"H3Y HAL2 " \ +"C34 CTL2 " \ +"H4X HAL2 " \ +"H4Y HAL2 " \ +"C35 CTL2 " \ +"H5X HAL2 " \ +"H5Y HAL2 " \ +"C36 CTL2 " \ +"H6X HAL2 " \ +"H6Y HAL2 " \ +"C37 CTL2 " \ +"H7X HAL2 " \ +"H7Y HAL2 " \ +"C38 CTL2 " \ +"H8X HAL2 " \ +"H8Y HAL2 " \ +"C39 CTL2 " \ +"H9X HAL2 " \ +"H9Y HAL2 " \ +"C310 CTL2 " \ +"H10X HAL2 " \ +"H10Y HAL2 " \ +"C311 CTL2 " \ +"H11X HAL2 " \ +"H11Y HAL2 " \ +"C312 CTL3 " \ +"H12X HAL3 " \ +"H12Y HAL3 " \ +"H12Z HAL3 " \ +"N NTL " \ +"C13 CTL5 " \ +"H13A HL " \ +"H13B HL " \ +"H13C HL " \ +"C14 CTL5 " \ +"H14A HL " \ +"H14B HL " \ +"H14C HL " \ +"C15 CTL5 " \ +"H15A HL " \ +"H15B HL " \ +"H15C HL " \ +"C12 CTL2 " \ +"H12A HL " \ +"H12B HL " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"P PL " \ +"O13 O2L " \ +"O14 O2L " \ +"O11 OSL " \ +"O12 OSL " \ +"C1 CTL2 " \ +"HA HAL2 " \ +"HB HAL2 " \ +"C2 CTL1 " \ +"HS HAL1 " \ +"O21 OSL " \ +"C21 CL " \ +"O22 OBL " \ +"C22 CTL2 " \ +"H2R HAL2 " \ +"H2S HAL2 " \ +"C3 CTL2 " \ +"HX HAL2 " \ +"HY HAL2 " \ +"O31 OSL " \ +"C31 CL " \ +"O32 OBL " \ +"C32 CTL2 " \ +"H2X HAL2 " \ +"H2Y HAL2 " \ +"C23 CTL2 " \ +"H3R HAL2 " \ +"H3S HAL2 " \ +"C24 CTL2 " \ +"H4R HAL2 " \ +"H4S HAL2 " \ +"C25 CTL2 " \ +"H5R HAL2 " \ +"H5S HAL2 " \ +"C26 CTL2 " \ +"H6R HAL2 " \ +"H6S HAL2 " \ +"C27 CTL2 " \ +"H7R HAL2 " \ +"H7S HAL2 " \ +"C28 CTL2 " \ +"H8R HAL2 " \ +"H8S HAL2 " \ +"C29 CTL2 " \ +"H9R HAL2 " \ +"H9S HAL2 " \ +"C210 CTL2 " \ +"H10R HAL2 " \ +"H10S HAL2 " \ +"C211 CTL2 " \ +"H11R HAL2 " \ +"H11S HAL2 " \ +"C212 CTL2 " \ +"H12R HAL2 " \ +"H12S HAL2 " \ +"C213 CTL2 " \ +"H13R HAL2 " \ +"H13S HAL2 " \ +"C214 CTL3 " \ +"H14R HAL3 " \ +"H14S HAL3 " \ +"H14T HAL3 " \ +"C33 CTL2 " \ +"H3X HAL2 " \ +"H3Y HAL2 " \ +"C34 CTL2 " \ +"H4X HAL2 " \ +"H4Y HAL2 " \ +"C35 CTL2 " \ +"H5X HAL2 " \ +"H5Y HAL2 " \ +"C36 CTL2 " \ +"H6X HAL2 " \ +"H6Y HAL2 " \ +"C37 CTL2 " \ +"H7X HAL2 " \ +"H7Y HAL2 " \ +"C38 CTL2 " \ +"H8X HAL2 " \ +"H8Y HAL2 " \ +"C39 CTL2 " \ +"H9X HAL2 " \ +"H9Y HAL2 " \ +"C310 CTL2 " \ +"H10X HAL2 " \ +"H10Y HAL2 " \ +"C311 CTL2 " \ +"H11X HAL2 " \ +"H11Y HAL2 " \ +"C312 CTL2 " \ +"H12X HAL2 " \ +"H12Y HAL2 " \ +"C313 CTL2 " \ +"H13X HAL2 " \ +"H13Y HAL2 " \ +"C314 CTL3 " \ +"H14X HAL3 " \ +"H14Y HAL3 " \ +"H14Z HAL3 " \ +"S SL " \ +"OS1 OSL " \ +"OS2 O2L " \ +"OS3 O2L " \ +"OS4 O2L " \ +"C1 CTL2 " \ +"H11 HAL2 " \ +"H12 HAL2 " \ +"C2 CTL2 " \ +"H21 HAL2 " \ +"H22 HAL2 " \ +"C3 CTL2 " \ +"H31 HAL2 " \ +"H32 HAL2 " \ +"C4 CTL2 " \ +"H41 HAL2 " \ +"H42 HAL2 " \ +"C5 CTL2 " \ +"H51 HAL2 " \ +"H52 HAL2 " \ +"C6 CTL2 " \ +"H61 HAL2 " \ +"H62 HAL2 " \ +"C7 CTL2 " \ +"H71 HAL2 " \ +"H72 HAL2 " \ +"C8 CTL2 " \ +"H81 HAL2 " \ +"H82 HAL2 " \ +"C9 CTL2 " \ +"H91 HAL2 " \ +"H92 HAL2 " \ +"C10 CTL2 " \ +"H101 HAL2 " \ +"H102 HAL2 " \ +"C11 CTL2 " \ +"H111 HAL2 " \ +"H112 HAL2 " \ +"C12 CTL3 " \ +"H121 HAL3 " \ +"H122 HAL3 " \ +"H123 HAL3 " \ +"N NTL " \ +"C11 CTL2 " \ +"C12 CTL5 " \ +"C13 CTL5 " \ +"C14 CTL5 " \ +"H11 HL " \ +"H12 HL " \ +"H21 HL " \ +"H22 HL " \ +"H23 HL " \ +"H31 HL " \ +"H32 HL " \ +"H33 HL " \ +"H41 HL " \ +"H42 HL " \ +"H43 HL " \ +"C15 CTL2 " \ +"H51 HAL2 " \ +"H52 HAL2 " \ +"P1 PL " \ +"O3 O2L " \ +"O4 O2L " \ +"O1 OSL " \ +"O2 OSL " \ +"C1 CTL2 " \ +"HA HAL2 " \ +"HB HAL2 " \ +"C2 CTL1 " \ +"HS HAL1 " \ +"O21 OSL " \ +"C21 CL " \ +"O22 OBL " \ +"C22 CTL2 " \ +"H2R HAL2 " \ +"H2S HAL2 " \ +"C3 CTL2 " \ +"HX HAL2 " \ +"HY HAL2 " \ +"O31 OSL " \ +"C31 CL " \ +"O32 OBL " \ +"C32 CTL2 " \ +"H2X HAL2 " \ +"H2Y HAL2 " \ +"C23 CTL2 " \ +"H3R HAL2 " \ +"H3S HAL2 " \ +"C24 CTL2 " \ +"H4R HAL2 " \ +"H4S HAL2 " \ +"C25 CTL2 " \ +"H5R HAL2 " \ +"H5S HAL2 " \ +"C26 CTL2 " \ +"H6R HAL2 " \ +"H6S HAL2 " \ +"C27 CTL2 " \ +"H7R HAL2 " \ +"H7S HAL2 " \ +"C28 CTL2 " \ +"H8R HAL2 " \ +"H8S HAL2 " \ +"C29 CEL1 " \ +"H91 HEL1 " \ +"C210 CEL1 " \ +"H101 HEL1 " \ +"C211 CTL2 " \ +"H11R HAL2 " \ +"H11S HAL2 " \ +"C212 CTL2 " \ +"H12R HAL2 " \ +"H12S HAL2 " \ +"C213 CTL2 " \ +"H13R HAL2 " \ +"H13S HAL2 " \ +"C214 CTL2 " \ +"H14R HAL2 " \ +"H14S HAL2 " \ +"C215 CTL2 " \ +"H15R HAL2 " \ +"H15S HAL2 " \ +"C216 CTL2 " \ +"H16R HAL2 " \ +"H16S HAL2 " \ +"C217 CTL2 " \ +"H17R HAL2 " \ +"H17S HAL2 " \ +"C218 CTL3 " \ +"H18R HAL3 " \ +"H18S HAL3 " \ +"H18T HAL3 " \ +"C33 CTL2 " \ +"H3X HAL2 " \ +"H3Y HAL2 " \ +"C34 CTL2 " \ +"H4X HAL2 " \ +"H4Y HAL2 " \ +"C35 CTL2 " \ +"H5X HAL2 " \ +"H5Y HAL2 " \ +"C36 CTL2 " \ +"H6X HAL2 " \ +"H6Y HAL2 " \ +"C37 CTL2 " \ +"H7X HAL2 " \ +"H7Y HAL2 " \ +"C38 CTL2 " \ +"H8X HAL2 " \ +"H8Y HAL2 " \ +"C39 CTL2 " \ +"H9X HAL2 " \ +"H9Y HAL2 " \ +"C310 CTL2 " \ +"H10X HAL2 " \ +"H10Y HAL2 " \ +"C311 CTL2 " \ +"H11X HAL2 " \ +"H11Y HAL2 " \ +"C312 CTL2 " \ +"H12X HAL2 " \ +"H12Y HAL2 " \ +"C313 CTL2 " \ +"H13X HAL2 " \ +"H13Y HAL2 " \ +"C314 CTL2 " \ +"H14X HAL2 " \ +"H14Y HAL2 " \ +"C315 CTL2 " \ +"H15X HAL2 " \ +"H15Y HAL2 " \ +"C316 CTL3 " \ +"H16X HAL3 " \ +"H16Y HAL3 " \ +"H16Z HAL3 " \ +"N NH3 " \ +"HN1 HCL " \ +"HN2 HCL " \ +"HN3 HCL " \ +"C12 CTL " \ +"H12A HAL " \ +"H12B HAL " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"P PL " \ +"O13 O2L " \ +"O14 O2L " \ +"O11 OSL " \ +"O12 OSL " \ +"C1 CTL2 " \ +"HA HAL2 " \ +"HB HAL2 " \ +"C2 CTL1 " \ +"HS HAL1 " \ +"O21 OSL " \ +"C21 CL " \ +"O22 OBL " \ +"C22 CTL2 " \ +"H2R HAL2 " \ +"H2S HAL2 " \ +"C3 CTL2 " \ +"HX HAL2 " \ +"HY HAL2 " \ +"O31 OSL " \ +"C31 CL " \ +"O32 OBL " \ +"C32 CTL2 " \ +"H2X HAL2 " \ +"H2Y HAL2 " \ +"C23 CTL2 " \ +"H3R HAL2 " \ +"H3S HAL2 " \ +"C24 CTL2 " \ +"H4R HAL2 " \ +"H4S HAL2 " \ +"C25 CTL2 " \ +"H5R HAL2 " \ +"H5S HAL2 " \ +"C26 CTL2 " \ +"H6R HAL2 " \ +"H6S HAL2 " \ +"C27 CTL2 " \ +"H7R HAL2 " \ +"H7S HAL2 " \ +"C28 CTL2 " \ +"H8R HAL2 " \ +"H8S HAL2 " \ +"C29 CEL1 " \ +"H91 HEL1 " \ +"C210 CEL1 " \ +"H101 HEL1 " \ +"C211 CTL2 " \ +"H11R HAL2 " \ +"H11S HAL2 " \ +"C212 CTL2 " \ +"H12R HAL2 " \ +"H12S HAL2 " \ +"C213 CTL2 " \ +"H13R HAL2 " \ +"H13S HAL2 " \ +"C214 CTL2 " \ +"H14R HAL2 " \ +"H14S HAL2 " \ +"C215 CTL2 " \ +"H15R HAL2 " \ +"H15S HAL2 " \ +"C216 CTL2 " \ +"H16R HAL2 " \ +"H16S HAL2 " \ +"C217 CTL2 " \ +"H17R HAL2 " \ +"H17S HAL2 " \ +"C218 CTL3 " \ +"H18R HAL3 " \ +"H18S HAL3 " \ +"H18T HAL3 " \ +"C33 CTL2 " \ +"H3X HAL2 " \ +"H3Y HAL2 " \ +"C34 CTL2 " \ +"H4X HAL2 " \ +"H4Y HAL2 " \ +"C35 CTL2 " \ +"H5X HAL2 " \ +"H5Y HAL2 " \ +"C36 CTL2 " \ +"H6X HAL2 " \ +"H6Y HAL2 " \ +"C37 CTL2 " \ +"H7X HAL2 " \ +"H7Y HAL2 " \ +"C38 CTL2 " \ +"H8X HAL2 " \ +"H8Y HAL2 " \ +"C39 CTL2 " \ +"H9X HAL2 " \ +"H9Y HAL2 " \ +"C310 CTL2 " \ +"H10X HAL2 " \ +"H10Y HAL2 " \ +"C311 CTL2 " \ +"H11X HAL2 " \ +"H11Y HAL2 " \ +"C312 CTL2 " \ +"H12X HAL2 " \ +"H12Y HAL2 " \ +"C313 CTL2 " \ +"H13X HAL2 " \ +"H13Y HAL2 " \ +"C314 CTL2 " \ +"H14X HAL2 " \ +"H14Y HAL2 " \ +"C315 CTL2 " \ +"H15X HAL2 " \ +"H15Y HAL2 " \ +"C316 CTL3 " \ +"H16X HAL3 " \ +"H16Y HAL3 " \ +"H16Z HAL3 " \ +"C1 CL " \ +"O1 OCL " \ +"O2 OCL " \ +"C2 CTL2 " \ +"H2A HAL2 " \ +"H2B HAL2 " \ +"C3 CTL2 " \ +"H3A HAL2 " \ +"H3B HAL2 " \ +"C4 CTL2 " \ +"H4A HAL2 " \ +"H4B HAL2 " \ +"C5 CTL2 " \ +"H5A HAL2 " \ +"H5B HAL2 " \ +"C6 CTL2 " \ +"H6A HAL2 " \ +"H6B HAL2 " \ +"C7 CTL2 " \ +"H7A HAL2 " \ +"H7B HAL2 " \ +"C8 CTL2 " \ +"H8A HAL2 " \ +"H8B HAL2 " \ +"C9 CTL2 " \ +"H9A HAL2 " \ +"H9B HAL2 " \ +"C10 CTL2 " \ +"H10A HAL2 " \ +"H10B HAL2 " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"C12 CTL2 " \ +"H12A HAL2 " \ +"H12B HAL2 " \ +"C13 CTL2 " \ +"H13A HAL2 " \ +"H13B HAL2 " \ +"C14 CTL2 " \ +"H14A HAL2 " \ +"H14B HAL2 " \ +"C15 CTL2 " \ +"H15A HAL2 " \ +"H15B HAL2 " \ +"C16 CTL3 " \ +"H16A HAL3 " \ +"H16B HAL3 " \ +"H16C HAL3 " \ +"C1 CL " \ +"O1 OCL " \ +"O2 OCL " \ +"C2 CTL2 " \ +"H2A HAL2 " \ +"H2B HAL2 " \ +"C3 CTL2 " \ +"H3A HAL2 " \ +"H3B HAL2 " \ +"C4 CTL2 " \ +"H4A HAL2 " \ +"H4B HAL2 " \ +"C5 CTL2 " \ +"H5A HAL2 " \ +"H5B HAL2 " \ +"C6 CTL2 " \ +"H6A HAL2 " \ +"H6B HAL2 " \ +"C7 CTL2 " \ +"H7A HAL2 " \ +"H7B HAL2 " \ +"C8 CTL2 " \ +"H8A HAL2 " \ +"H8B HAL2 " \ +"C9 CEL1 " \ +"H9A HEL1 " \ +"C10 CEL1 " \ +"H10A HEL1 " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"C12 CTL2 " \ +"H12A HAL2 " \ +"H12B HAL2 " \ +"C13 CTL2 " \ +"H13A HAL2 " \ +"H13B HAL2 " \ +"C14 CTL2 " \ +"H14A HAL2 " \ +"H14B HAL2 " \ +"C15 CTL2 " \ +"H15A HAL2 " \ +"H15B HAL2 " \ +"C16 CTL2 " \ +"H16A HAL2 " \ +"H16B HAL2 " \ +"C17 CTL2 " \ +"H17A HAL2 " \ +"H17B HAL2 " \ +"C18 CTL3 " \ +"H18A HAL3 " \ +"H18B HAL3 " \ +"H18C HAL3 " \ +"C1 CL " \ +"O1 OCL " \ +"O2 OCL " \ +"C2 CTL2 " \ +"H2A HAL2 " \ +"H2B HAL2 " \ +"C3 CTL2 " \ +"H3A HAL2 " \ +"H3B HAL2 " \ +"C4 CEL1 " \ +"H4 HEL1 " \ +"C5 CEL1 " \ +"H5 HEL1 " \ +"C6 CTL2 " \ +"H6A HAL2 " \ +"H6B HAL2 " \ +"C7 CEL1 " \ +"H7 HEL1 " \ +"C8 CEL1 " \ +"H8 HEL1 " \ +"C9 CTL2 " \ +"H9A HAL2 " \ +"H9B HAL2 " \ +"C10 CEL1 " \ +"H10 HEL1 " \ +"C11 CEL1 " \ +"H11 HEL1 " \ +"C12 CTL2 " \ +"H12A HAL2 " \ +"H12B HAL2 " \ +"C13 CEL1 " \ +"H13 HEL1 " \ +"C14 CEL1 " \ +"H14 HEL1 " \ +"C15 CTL2 " \ +"H15A HAL2 " \ +"H15B HAL2 " \ +"C16 CEL1 " \ +"H16 HEL1 " \ +"C17 CEL1 " \ +"H17 HEL1 " \ +"C18 CTL2 " \ +"H18A HAL2 " \ +"H18B HAL2 " \ +"C19 CEL1 " \ +"H19 HEL1 " \ +"C20 CEL1 " \ +"H20 HEL1 " \ +"C21 CTL2 " \ +"H21A HAL2 " \ +"H21B HAL2 " \ +"C22 CTL3 " \ +"H22A HAL3 " \ +"H22B HAL3 " \ +"H22C HAL3 " \ +"C1 CL " \ +"O1 OCL " \ +"O2 OCL " \ +"C2 CTL2 " \ +"H2A HAL2 " \ +"H2B HAL2 " \ +"C3 CTL2 " \ +"H3A HAL2 " \ +"H3B HAL2 " \ +"C4 CTL2 " \ +"H4A HAL2 " \ +"H4B HAL2 " \ +"C5 CTL2 " \ +"H5A HAL2 " \ +"H5B HAL2 " \ +"C6 CTL2 " \ +"H6A HAL2 " \ +"H6B HAL2 " \ +"C7 CTL2 " \ +"H7A HAL2 " \ +"H7B HAL2 " \ +"C8 CTL2 " \ +"H8A HAL2 " \ +"H8B HAL2 " \ +"C9 CTL2 " \ +"H9A HAL2 " \ +"H9B HAL2 " \ +"C10 CTL2 " \ +"H10A HAL2 " \ +"H10B HAL2 " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"C12 CTL2 " \ +"H12A HAL2 " \ +"H12B HAL2 " \ +"C13 CTL2 " \ +"H13A HAL2 " \ +"H13B HAL2 " \ +"C14 CTL2 " \ +"H14A HAL2 " \ +"H14B HAL2 " \ +"C15 CTL2 " \ +"H15A HAL2 " \ +"H15B HAL2 " \ +"C16 CTL2 " \ +"H16A HAL2 " \ +"H16B HAL2 " \ +"C17 CTL2 " \ +"H17A HAL2 " \ +"H17B HAL2 " \ +"C18 CTL3 " \ +"H18A HAL3 " \ +"H18B HAL3 " \ +"H18C HAL3 " \ +"N NTL " \ +"C5 CTL2 " \ +"C6 CTL5 " \ +"C7 CTL5 " \ +"C8 CTL5 " \ +"H5A HL " \ +"H5B HL " \ +"H6A HL " \ +"H6B HL " \ +"H6C HL " \ +"H7A HL " \ +"H7B HL " \ +"H7C HL " \ +"H8A HL " \ +"H8B HL " \ +"H8C HL " \ +"C4 CTL2 " \ +"H4A HAL2 " \ +"H4B HAL2 " \ +"P PL " \ +"OP3 O2L " \ +"OP4 O2L " \ +"OP1 OSL " \ +"OP2 OSL " \ +"C3 CTL2 " \ +"H3A HAL2 " \ +"H3B HAL2 " \ +"C2 CTL1 " \ +"H2A HAL1 " \ +"O2 OHL " \ +"H2 HOL " \ +"C1 CTL2 " \ +"H1A HAL2 " \ +"H1B HAL2 " \ +"O1 OHL " \ +"H1 HOL " \ +"1C1 CTL2 " \ +"1H1A HAL2 " \ +"1H1B HAL2 " \ +"1O1 OSL " \ +"2C1 CL " \ +"2O1 OBL " \ +"2C2 CTL2 " \ +"2H2A HAL2 " \ +"2H2B HAL2 " \ +"1C2 CTL1 " \ +"1H2A HAL1 " \ +"1O2 OSL " \ +"2C1 CL " \ +"2O1 OBL " \ +"2C2 CTL2 " \ +"2H2A HAL2 " \ +"2H2B HAL2 " \ +"OH2 OT " \ +"H1 HT " \ +"H2 HT " \ +"OH2 OT " \ +"H1 HT " \ +"H2 HT " \ +"SOD SOD " \ +"MG MG " \ +"POT POT " \ +"CES CES " \ +"CAL CAL " \ +"CLA CLA " \ +"ZN ZN " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6B " \ +"C1' CN7B " \ +"H1' HN7 " \ +"N9 NN2B " \ +"C4 CN5 " \ +"N2 NN1 " \ +"H21 HN1 " \ +"H22 HN1 " \ +"N3 NN3G " \ +"C2 CN2 " \ +"N1 NN2G " \ +"H1 HN2 " \ +"C6 CN1 " \ +"O6 ON1 " \ +"C5 CN5G " \ +"N7 NN4 " \ +"C8 CN4 " \ +"H8 HN3 " \ +"C2' CN7B " \ +"H2'' HN7 " \ +"O2' ON5 " \ +"H2' HN5 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"O3' ON2 " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6B " \ +"C1' CN7B " \ +"H1' HN7 " \ +"N9 NN2 " \ +"C5 CN5 " \ +"N7 NN4 " \ +"C8 CN4 " \ +"H8 HN3 " \ +"N1 NN3A " \ +"C2 CN4 " \ +"H2 HN3 " \ +"N3 NN3A " \ +"C4 CN5 " \ +"C6 CN2 " \ +"N6 NN1 " \ +"H61 HN1 " \ +"H62 HN1 " \ +"C2' CN7B " \ +"H2'' HN7 " \ +"O2' ON5 " \ +"H2' HN5 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"O3' ON2 " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6B " \ +"C1' CN7B " \ +"H1' HN7 " \ +"N1 NN2 " \ +"C6 CN3 " \ +"H6 HN3 " \ +"C5 CN3 " \ +"H5 HN3 " \ +"C2 CN1 " \ +"O2 ON1C " \ +"N3 NN3 " \ +"C4 CN2 " \ +"N4 NN1 " \ +"H41 HN1 " \ +"H42 HN1 " \ +"C2' CN7B " \ +"H2'' HN7 " \ +"O2' ON5 " \ +"H2' HN5 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"O3' ON2 " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6B " \ +"C1' CN7B " \ +"H1' HN7 " \ +"N1 NN2B " \ +"C6 CN3 " \ +"H6 HN3 " \ +"C2 CN1T " \ +"O2 ON1 " \ +"N3 NN2U " \ +"H3 HN2 " \ +"C4 CN1 " \ +"O4 ON1 " \ +"C5 CN3T " \ +"C5M CN9 " \ +"H51 HN9 " \ +"H52 HN9 " \ +"H53 HN9 " \ +"C2' CN7B " \ +"H2'' HN7 " \ +"O2' ON5 " \ +"H2' HN5 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"O3' ON2 " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6B " \ +"C1' CN7B " \ +"H1' HN7 " \ +"N1 NN2B " \ +"C6 CN3 " \ +"H6 HN3 " \ +"C2 CN1T " \ +"O2 ON1 " \ +"N3 NN2U " \ +"H3 HN2 " \ +"C4 CN1 " \ +"O4 ON1 " \ +"C5 CN3 " \ +"H5 HN3 " \ +"C2' CN7B " \ +"H2'' HN7 " \ +"O2' ON5 " \ +"H2' HN5 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"O3' ON2 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6 " \ +"C1' CN7B " \ +"H1' HN7 " \ +"C2' CN8 " \ +"H2' HN8 " \ +"H2'' HN8 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6 " \ +"C1' CN7B " \ +"H1' HN7 " \ +"C2' CN8 " \ +"H2' HN8 " \ +"H2'' HN8 " \ +"H5T HN5 " \ +"O5' ON5 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"C5' CN9 " \ +"H5' HN9 " \ +"H5'' HN9 " \ +"H53' HN9 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"O5T ON4 " \ +"H5T HN4 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"O5T ON2 " \ +"C5T CN9 " \ +"H5T1 HN9 " \ +"H5T2 HN9 " \ +"H5T3 HN9 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"O3' ON5 " \ +"H3T HN5 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"P3 P " \ +"O1P3 ON3 " \ +"O2P3 ON3 " \ +"O3' ON2 " \ +"O3T ON4 " \ +"H3T HN4 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"P3 P " \ +"O1P3 ON3 " \ +"O2P3 ON3 " \ +"O3' ON2 " \ +"O3T ON2 " \ +"C3T CN9 " \ +"H3T1 HN9 " \ +"H3T2 HN9 " \ +"H3T3 HN9 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"P3 P " \ +"O3' ON2 " \ +"O1P3 ON3 " \ +"O2P3 ON3 " \ +"O3P3 ON3 " \ +"OH2 OT " \ +"H1 HT " \ +"H2 HT " \ +"OH2 OT " \ +"H1 HT " \ +"H2 HT " \ +"SOD SOD " \ +"MG MG " \ +"POT POT " \ +"CES CES " \ +"CAL CAL " \ +"CLA CLA " \ +"ZN ZN " \ +"N NTL " \ +"C13 CTL5 " \ +"H13A HL " \ +"H13B HL " \ +"H13C HL " \ +"C14 CTL5 " \ +"H14A HL " \ +"H14B HL " \ +"H14C HL " \ +"C15 CTL5 " \ +"H15A HL " \ +"H15B HL " \ +"H15C HL " \ +"C12 CTL2 " \ +"H12A HL " \ +"H12B HL " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"P PL " \ +"O13 O2L " \ +"O14 O2L " \ +"O11 OSL " \ +"O12 OSL " \ +"C1 CTL2 " \ +"HA HAL2 " \ +"HB HAL2 " \ +"C2 CTL2 " \ +"HS HAL2 " \ +"HR HAL2 " \ +"C3 CTL2 " \ +"HX HAL2 " \ +"HY HAL2 " \ +"O31 OSL " \ +"C31 CL " \ +"O32 OBL " \ +"C32 CTL2 " \ +"H2X HAL2 " \ +"H2Y HAL2 " \ +"C33 CTL2 " \ +"H3X HAL2 " \ +"H3Y HAL2 " \ +"C34 CTL2 " \ +"H4X HAL2 " \ +"H4Y HAL2 " \ +"C35 CTL2 " \ +"H5X HAL2 " \ +"H5Y HAL2 " \ +"C36 CTL2 " \ +"H6X HAL2 " \ +"H6Y HAL2 " \ +"C37 CTL2 " \ +"H7X HAL2 " \ +"H7Y HAL2 " \ +"C38 CTL2 " \ +"H8X HAL2 " \ +"H8Y HAL2 " \ +"C39 CTL2 " \ +"H9X HAL2 " \ +"H9Y HAL2 " \ +"C310 CTL2 " \ +"H10X HAL2 " \ +"H10Y HAL2 " \ +"C311 CTL2 " \ +"H11X HAL2 " \ +"H11Y HAL2 " \ +"C312 CTL3 " \ +"H12X HAL3 " \ +"H12Y HAL3 " \ +"H12Z HAL3 " \ +"N NH3 " \ +"HN1 HCL " \ +"HN2 HCL " \ +"HN3 HCL " \ +"C12 CTL " \ +"H12A HAL " \ +"H12B HAL " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"P PL " \ +"O13 O2L " \ +"O14 O2L " \ +"O11 OSL " \ +"O12 OSL " \ +"C1 CTL2 " \ +"HA HAL2 " \ +"HB HAL2 " \ +"C2 CTL1 " \ +"HS HAL1 " \ +"OH2 OHL " \ +"HO2 HOL " \ +"C3 CTL2 " \ +"HX HAL2 " \ +"HY HAL2 " \ +"OH3 OHL " \ +"HO3 HOL " \ +"N NH3 " \ +"HN1 HCL " \ +"HN2 HCL " \ +"HN3 HCL " \ +"C12 CTL " \ +"H12A HAL " \ +"H12B HAL " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"P PL " \ +"O13 O2L " \ +"O14 O2L " \ +"O11 OSL " \ +"O12 OSL " \ +"C1 CTL2 " \ +"HA HAL2 " \ +"HB HAL2 " \ +"C2 CTL1 " \ +"HS HAL1 " \ +"O21 OSL " \ +"C21 CL " \ +"O22 OBL " \ +"C22 CTL2 " \ +"H2R HAL2 " \ +"H2S HAL2 " \ +"C3 CTL2 " \ +"HX HAL2 " \ +"HY HAL2 " \ +"O31 OSL " \ +"C31 CL " \ +"O32 OBL " \ +"C32 CTL2 " \ +"H2X HAL2 " \ +"H2Y HAL2 " \ +"C23 CTL2 " \ +"H3R HAL2 " \ +"H3S HAL2 " \ +"C24 CTL2 " \ +"H4R HAL2 " \ +"H4S HAL2 " \ +"C25 CTL2 " \ +"H5R HAL2 " \ +"H5S HAL2 " \ +"C26 CTL2 " \ +"H6R HAL2 " \ +"H6S HAL2 " \ +"C27 CTL2 " \ +"H7R HAL2 " \ +"H7S HAL2 " \ +"C28 CTL2 " \ +"H8R HAL2 " \ +"H8S HAL2 " \ +"C29 CTL2 " \ +"H9R HAL2 " \ +"H9S HAL2 " \ +"C210 CTL2 " \ +"H10R HAL2 " \ +"H10S HAL2 " \ +"C211 CTL2 " \ +"H11R HAL2 " \ +"H11S HAL2 " \ +"C212 CTL3 " \ +"H12R HAL3 " \ +"H12S HAL3 " \ +"H12T HAL3 " \ +"C33 CTL2 " \ +"H3X HAL2 " \ +"H3Y HAL2 " \ +"C34 CTL2 " \ +"H4X HAL2 " \ +"H4Y HAL2 " \ +"C35 CTL2 " \ +"H5X HAL2 " \ +"H5Y HAL2 " \ +"C36 CTL2 " \ +"H6X HAL2 " \ +"H6Y HAL2 " \ +"C37 CTL2 " \ +"H7X HAL2 " \ +"H7Y HAL2 " \ +"C38 CTL2 " \ +"H8X HAL2 " \ +"H8Y HAL2 " \ +"C39 CTL2 " \ +"H9X HAL2 " \ +"H9Y HAL2 " \ +"C310 CTL2 " \ +"H10X HAL2 " \ +"H10Y HAL2 " \ +"C311 CTL2 " \ +"H11X HAL2 " \ +"H11Y HAL2 " \ +"C312 CTL3 " \ +"H12X HAL3 " \ +"H12Y HAL3 " \ +"H12Z HAL3 " \ +"N NTL " \ +"C13 CTL5 " \ +"H13A HL " \ +"H13B HL " \ +"H13C HL " \ +"C14 CTL5 " \ +"H14A HL " \ +"H14B HL " \ +"H14C HL " \ +"C15 CTL5 " \ +"H15A HL " \ +"H15B HL " \ +"H15C HL " \ +"C12 CTL2 " \ +"H12A HL " \ +"H12B HL " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"P PL " \ +"O13 O2L " \ +"O14 O2L " \ +"O11 OSL " \ +"O12 OSL " \ +"C1 CTL2 " \ +"HA HAL2 " \ +"HB HAL2 " \ +"C2 CTL1 " \ +"HS HAL1 " \ +"O21 OSL " \ +"C21 CL " \ +"O22 OBL " \ +"C22 CTL2 " \ +"H2R HAL2 " \ +"H2S HAL2 " \ +"C3 CTL2 " \ +"HX HAL2 " \ +"HY HAL2 " \ +"O31 OSL " \ +"C31 CL " \ +"O32 OBL " \ +"C32 CTL2 " \ +"H2X HAL2 " \ +"H2Y HAL2 " \ +"C23 CTL2 " \ +"H3R HAL2 " \ +"H3S HAL2 " \ +"C24 CTL2 " \ +"H4R HAL2 " \ +"H4S HAL2 " \ +"C25 CTL2 " \ +"H5R HAL2 " \ +"H5S HAL2 " \ +"C26 CTL2 " \ +"H6R HAL2 " \ +"H6S HAL2 " \ +"C27 CTL2 " \ +"H7R HAL2 " \ +"H7S HAL2 " \ +"C28 CTL2 " \ +"H8R HAL2 " \ +"H8S HAL2 " \ +"C29 CTL2 " \ +"H9R HAL2 " \ +"H9S HAL2 " \ +"C210 CTL2 " \ +"H10R HAL2 " \ +"H10S HAL2 " \ +"C211 CTL2 " \ +"H11R HAL2 " \ +"H11S HAL2 " \ +"C212 CTL2 " \ +"H12R HAL2 " \ +"H12S HAL2 " \ +"C213 CTL2 " \ +"H13R HAL2 " \ +"H13S HAL2 " \ +"C214 CTL3 " \ +"H14R HAL3 " \ +"H14S HAL3 " \ +"H14T HAL3 " \ +"C33 CTL2 " \ +"H3X HAL2 " \ +"H3Y HAL2 " \ +"C34 CTL2 " \ +"H4X HAL2 " \ +"H4Y HAL2 " \ +"C35 CTL2 " \ +"H5X HAL2 " \ +"H5Y HAL2 " \ +"C36 CTL2 " \ +"H6X HAL2 " \ +"H6Y HAL2 " \ +"C37 CTL2 " \ +"H7X HAL2 " \ +"H7Y HAL2 " \ +"C38 CTL2 " \ +"H8X HAL2 " \ +"H8Y HAL2 " \ +"C39 CTL2 " \ +"H9X HAL2 " \ +"H9Y HAL2 " \ +"C310 CTL2 " \ +"H10X HAL2 " \ +"H10Y HAL2 " \ +"C311 CTL2 " \ +"H11X HAL2 " \ +"H11Y HAL2 " \ +"C312 CTL2 " \ +"H12X HAL2 " \ +"H12Y HAL2 " \ +"C313 CTL2 " \ +"H13X HAL2 " \ +"H13Y HAL2 " \ +"C314 CTL3 " \ +"H14X HAL3 " \ +"H14Y HAL3 " \ +"H14Z HAL3 " \ +"S SL " \ +"OS1 OSL " \ +"OS2 O2L " \ +"OS3 O2L " \ +"OS4 O2L " \ +"C1 CTL2 " \ +"H11 HAL2 " \ +"H12 HAL2 " \ +"C2 CTL2 " \ +"H21 HAL2 " \ +"H22 HAL2 " \ +"C3 CTL2 " \ +"H31 HAL2 " \ +"H32 HAL2 " \ +"C4 CTL2 " \ +"H41 HAL2 " \ +"H42 HAL2 " \ +"C5 CTL2 " \ +"H51 HAL2 " \ +"H52 HAL2 " \ +"C6 CTL2 " \ +"H61 HAL2 " \ +"H62 HAL2 " \ +"C7 CTL2 " \ +"H71 HAL2 " \ +"H72 HAL2 " \ +"C8 CTL2 " \ +"H81 HAL2 " \ +"H82 HAL2 " \ +"C9 CTL2 " \ +"H91 HAL2 " \ +"H92 HAL2 " \ +"C10 CTL2 " \ +"H101 HAL2 " \ +"H102 HAL2 " \ +"C11 CTL2 " \ +"H111 HAL2 " \ +"H112 HAL2 " \ +"C12 CTL3 " \ +"H121 HAL3 " \ +"H122 HAL3 " \ +"H123 HAL3 " \ +"N NTL " \ +"C11 CTL2 " \ +"C12 CTL5 " \ +"C13 CTL5 " \ +"C14 CTL5 " \ +"H11 HL " \ +"H12 HL " \ +"H21 HL " \ +"H22 HL " \ +"H23 HL " \ +"H31 HL " \ +"H32 HL " \ +"H33 HL " \ +"H41 HL " \ +"H42 HL " \ +"H43 HL " \ +"C15 CTL2 " \ +"H51 HAL2 " \ +"H52 HAL2 " \ +"P1 PL " \ +"O3 O2L " \ +"O4 O2L " \ +"O1 OSL " \ +"O2 OSL " \ +"C1 CTL2 " \ +"HA HAL2 " \ +"HB HAL2 " \ +"C2 CTL1 " \ +"HS HAL1 " \ +"O21 OSL " \ +"C21 CL " \ +"O22 OBL " \ +"C22 CTL2 " \ +"H2R HAL2 " \ +"H2S HAL2 " \ +"C3 CTL2 " \ +"HX HAL2 " \ +"HY HAL2 " \ +"O31 OSL " \ +"C31 CL " \ +"O32 OBL " \ +"C32 CTL2 " \ +"H2X HAL2 " \ +"H2Y HAL2 " \ +"C23 CTL2 " \ +"H3R HAL2 " \ +"H3S HAL2 " \ +"C24 CTL2 " \ +"H4R HAL2 " \ +"H4S HAL2 " \ +"C25 CTL2 " \ +"H5R HAL2 " \ +"H5S HAL2 " \ +"C26 CTL2 " \ +"H6R HAL2 " \ +"H6S HAL2 " \ +"C27 CTL2 " \ +"H7R HAL2 " \ +"H7S HAL2 " \ +"C28 CTL2 " \ +"H8R HAL2 " \ +"H8S HAL2 " \ +"C29 CEL1 " \ +"H91 HEL1 " \ +"C210 CEL1 " \ +"H101 HEL1 " \ +"C211 CTL2 " \ +"H11R HAL2 " \ +"H11S HAL2 " \ +"C212 CTL2 " \ +"H12R HAL2 " \ +"H12S HAL2 " \ +"C213 CTL2 " \ +"H13R HAL2 " \ +"H13S HAL2 " \ +"C214 CTL2 " \ +"H14R HAL2 " \ +"H14S HAL2 " \ +"C215 CTL2 " \ +"H15R HAL2 " \ +"H15S HAL2 " \ +"C216 CTL2 " \ +"H16R HAL2 " \ +"H16S HAL2 " \ +"C217 CTL2 " \ +"H17R HAL2 " \ +"H17S HAL2 " \ +"C218 CTL3 " \ +"H18R HAL3 " \ +"H18S HAL3 " \ +"H18T HAL3 " \ +"C33 CTL2 " \ +"H3X HAL2 " \ +"H3Y HAL2 " \ +"C34 CTL2 " \ +"H4X HAL2 " \ +"H4Y HAL2 " \ +"C35 CTL2 " \ +"H5X HAL2 " \ +"H5Y HAL2 " \ +"C36 CTL2 " \ +"H6X HAL2 " \ +"H6Y HAL2 " \ +"C37 CTL2 " \ +"H7X HAL2 " \ +"H7Y HAL2 " \ +"C38 CTL2 " \ +"H8X HAL2 " \ +"H8Y HAL2 " \ +"C39 CTL2 " \ +"H9X HAL2 " \ +"H9Y HAL2 " \ +"C310 CTL2 " \ +"H10X HAL2 " \ +"H10Y HAL2 " \ +"C311 CTL2 " \ +"H11X HAL2 " \ +"H11Y HAL2 " \ +"C312 CTL2 " \ +"H12X HAL2 " \ +"H12Y HAL2 " \ +"C313 CTL2 " \ +"H13X HAL2 " \ +"H13Y HAL2 " \ +"C314 CTL2 " \ +"H14X HAL2 " \ +"H14Y HAL2 " \ +"C315 CTL2 " \ +"H15X HAL2 " \ +"H15Y HAL2 " \ +"C316 CTL3 " \ +"H16X HAL3 " \ +"H16Y HAL3 " \ +"H16Z HAL3 " \ +"N NH3 " \ +"HN1 HCL " \ +"HN2 HCL " \ +"HN3 HCL " \ +"C12 CTL " \ +"H12A HAL " \ +"H12B HAL " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"P PL " \ +"O13 O2L " \ +"O14 O2L " \ +"O11 OSL " \ +"O12 OSL " \ +"C1 CTL2 " \ +"HA HAL2 " \ +"HB HAL2 " \ +"C2 CTL1 " \ +"HS HAL1 " \ +"O21 OSL " \ +"C21 CL " \ +"O22 OBL " \ +"C22 CTL2 " \ +"H2R HAL2 " \ +"H2S HAL2 " \ +"C3 CTL2 " \ +"HX HAL2 " \ +"HY HAL2 " \ +"O31 OSL " \ +"C31 CL " \ +"O32 OBL " \ +"C32 CTL2 " \ +"H2X HAL2 " \ +"H2Y HAL2 " \ +"C23 CTL2 " \ +"H3R HAL2 " \ +"H3S HAL2 " \ +"C24 CTL2 " \ +"H4R HAL2 " \ +"H4S HAL2 " \ +"C25 CTL2 " \ +"H5R HAL2 " \ +"H5S HAL2 " \ +"C26 CTL2 " \ +"H6R HAL2 " \ +"H6S HAL2 " \ +"C27 CTL2 " \ +"H7R HAL2 " \ +"H7S HAL2 " \ +"C28 CTL2 " \ +"H8R HAL2 " \ +"H8S HAL2 " \ +"C29 CEL1 " \ +"H91 HEL1 " \ +"C210 CEL1 " \ +"H101 HEL1 " \ +"C211 CTL2 " \ +"H11R HAL2 " \ +"H11S HAL2 " \ +"C212 CTL2 " \ +"H12R HAL2 " \ +"H12S HAL2 " \ +"C213 CTL2 " \ +"H13R HAL2 " \ +"H13S HAL2 " \ +"C214 CTL2 " \ +"H14R HAL2 " \ +"H14S HAL2 " \ +"C215 CTL2 " \ +"H15R HAL2 " \ +"H15S HAL2 " \ +"C216 CTL2 " \ +"H16R HAL2 " \ +"H16S HAL2 " \ +"C217 CTL2 " \ +"H17R HAL2 " \ +"H17S HAL2 " \ +"C218 CTL3 " \ +"H18R HAL3 " \ +"H18S HAL3 " \ +"H18T HAL3 " \ +"C33 CTL2 " \ +"H3X HAL2 " \ +"H3Y HAL2 " \ +"C34 CTL2 " \ +"H4X HAL2 " \ +"H4Y HAL2 " \ +"C35 CTL2 " \ +"H5X HAL2 " \ +"H5Y HAL2 " \ +"C36 CTL2 " \ +"H6X HAL2 " \ +"H6Y HAL2 " \ +"C37 CTL2 " \ +"H7X HAL2 " \ +"H7Y HAL2 " \ +"C38 CTL2 " \ +"H8X HAL2 " \ +"H8Y HAL2 " \ +"C39 CTL2 " \ +"H9X HAL2 " \ +"H9Y HAL2 " \ +"C310 CTL2 " \ +"H10X HAL2 " \ +"H10Y HAL2 " \ +"C311 CTL2 " \ +"H11X HAL2 " \ +"H11Y HAL2 " \ +"C312 CTL2 " \ +"H12X HAL2 " \ +"H12Y HAL2 " \ +"C313 CTL2 " \ +"H13X HAL2 " \ +"H13Y HAL2 " \ +"C314 CTL2 " \ +"H14X HAL2 " \ +"H14Y HAL2 " \ +"C315 CTL2 " \ +"H15X HAL2 " \ +"H15Y HAL2 " \ +"C316 CTL3 " \ +"H16X HAL3 " \ +"H16Y HAL3 " \ +"H16Z HAL3 " \ +"C1 CL " \ +"O1 OCL " \ +"O2 OCL " \ +"C2 CTL2 " \ +"H2A HAL2 " \ +"H2B HAL2 " \ +"C3 CTL2 " \ +"H3A HAL2 " \ +"H3B HAL2 " \ +"C4 CTL2 " \ +"H4A HAL2 " \ +"H4B HAL2 " \ +"C5 CTL2 " \ +"H5A HAL2 " \ +"H5B HAL2 " \ +"C6 CTL2 " \ +"H6A HAL2 " \ +"H6B HAL2 " \ +"C7 CTL2 " \ +"H7A HAL2 " \ +"H7B HAL2 " \ +"C8 CTL2 " \ +"H8A HAL2 " \ +"H8B HAL2 " \ +"C9 CTL2 " \ +"H9A HAL2 " \ +"H9B HAL2 " \ +"C10 CTL2 " \ +"H10A HAL2 " \ +"H10B HAL2 " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"C12 CTL2 " \ +"H12A HAL2 " \ +"H12B HAL2 " \ +"C13 CTL2 " \ +"H13A HAL2 " \ +"H13B HAL2 " \ +"C14 CTL2 " \ +"H14A HAL2 " \ +"H14B HAL2 " \ +"C15 CTL2 " \ +"H15A HAL2 " \ +"H15B HAL2 " \ +"C16 CTL3 " \ +"H16A HAL3 " \ +"H16B HAL3 " \ +"H16C HAL3 " \ +"C1 CL " \ +"O1 OCL " \ +"O2 OCL " \ +"C2 CTL2 " \ +"H2A HAL2 " \ +"H2B HAL2 " \ +"C3 CTL2 " \ +"H3A HAL2 " \ +"H3B HAL2 " \ +"C4 CTL2 " \ +"H4A HAL2 " \ +"H4B HAL2 " \ +"C5 CTL2 " \ +"H5A HAL2 " \ +"H5B HAL2 " \ +"C6 CTL2 " \ +"H6A HAL2 " \ +"H6B HAL2 " \ +"C7 CTL2 " \ +"H7A HAL2 " \ +"H7B HAL2 " \ +"C8 CTL2 " \ +"H8A HAL2 " \ +"H8B HAL2 " \ +"C9 CEL1 " \ +"H9A HEL1 " \ +"C10 CEL1 " \ +"H10A HEL1 " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"C12 CTL2 " \ +"H12A HAL2 " \ +"H12B HAL2 " \ +"C13 CTL2 " \ +"H13A HAL2 " \ +"H13B HAL2 " \ +"C14 CTL2 " \ +"H14A HAL2 " \ +"H14B HAL2 " \ +"C15 CTL2 " \ +"H15A HAL2 " \ +"H15B HAL2 " \ +"C16 CTL2 " \ +"H16A HAL2 " \ +"H16B HAL2 " \ +"C17 CTL2 " \ +"H17A HAL2 " \ +"H17B HAL2 " \ +"C18 CTL3 " \ +"H18A HAL3 " \ +"H18B HAL3 " \ +"H18C HAL3 " \ +"C1 CL " \ +"O1 OCL " \ +"O2 OCL " \ +"C2 CTL2 " \ +"H2A HAL2 " \ +"H2B HAL2 " \ +"C3 CTL2 " \ +"H3A HAL2 " \ +"H3B HAL2 " \ +"C4 CEL1 " \ +"H4 HEL1 " \ +"C5 CEL1 " \ +"H5 HEL1 " \ +"C6 CTL2 " \ +"H6A HAL2 " \ +"H6B HAL2 " \ +"C7 CEL1 " \ +"H7 HEL1 " \ +"C8 CEL1 " \ +"H8 HEL1 " \ +"C9 CTL2 " \ +"H9A HAL2 " \ +"H9B HAL2 " \ +"C10 CEL1 " \ +"H10 HEL1 " \ +"C11 CEL1 " \ +"H11 HEL1 " \ +"C12 CTL2 " \ +"H12A HAL2 " \ +"H12B HAL2 " \ +"C13 CEL1 " \ +"H13 HEL1 " \ +"C14 CEL1 " \ +"H14 HEL1 " \ +"C15 CTL2 " \ +"H15A HAL2 " \ +"H15B HAL2 " \ +"C16 CEL1 " \ +"H16 HEL1 " \ +"C17 CEL1 " \ +"H17 HEL1 " \ +"C18 CTL2 " \ +"H18A HAL2 " \ +"H18B HAL2 " \ +"C19 CEL1 " \ +"H19 HEL1 " \ +"C20 CEL1 " \ +"H20 HEL1 " \ +"C21 CTL2 " \ +"H21A HAL2 " \ +"H21B HAL2 " \ +"C22 CTL3 " \ +"H22A HAL3 " \ +"H22B HAL3 " \ +"H22C HAL3 " \ +"C1 CL " \ +"O1 OCL " \ +"O2 OCL " \ +"C2 CTL2 " \ +"H2A HAL2 " \ +"H2B HAL2 " \ +"C3 CTL2 " \ +"H3A HAL2 " \ +"H3B HAL2 " \ +"C4 CTL2 " \ +"H4A HAL2 " \ +"H4B HAL2 " \ +"C5 CTL2 " \ +"H5A HAL2 " \ +"H5B HAL2 " \ +"C6 CTL2 " \ +"H6A HAL2 " \ +"H6B HAL2 " \ +"C7 CTL2 " \ +"H7A HAL2 " \ +"H7B HAL2 " \ +"C8 CTL2 " \ +"H8A HAL2 " \ +"H8B HAL2 " \ +"C9 CTL2 " \ +"H9A HAL2 " \ +"H9B HAL2 " \ +"C10 CTL2 " \ +"H10A HAL2 " \ +"H10B HAL2 " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"C12 CTL2 " \ +"H12A HAL2 " \ +"H12B HAL2 " \ +"C13 CTL2 " \ +"H13A HAL2 " \ +"H13B HAL2 " \ +"C14 CTL2 " \ +"H14A HAL2 " \ +"H14B HAL2 " \ +"C15 CTL2 " \ +"H15A HAL2 " \ +"H15B HAL2 " \ +"C16 CTL2 " \ +"H16A HAL2 " \ +"H16B HAL2 " \ +"C17 CTL2 " \ +"H17A HAL2 " \ +"H17B HAL2 " \ +"C18 CTL3 " \ +"H18A HAL3 " \ +"H18B HAL3 " \ +"H18C HAL3 " \ +"N NTL " \ +"C5 CTL2 " \ +"C6 CTL5 " \ +"C7 CTL5 " \ +"C8 CTL5 " \ +"H5A HL " \ +"H5B HL " \ +"H6A HL " \ +"H6B HL " \ +"H6C HL " \ +"H7A HL " \ +"H7B HL " \ +"H7C HL " \ +"H8A HL " \ +"H8B HL " \ +"H8C HL " \ +"C4 CTL2 " \ +"H4A HAL2 " \ +"H4B HAL2 " \ +"P PL " \ +"OP3 O2L " \ +"OP4 O2L " \ +"OP1 OSL " \ +"OP2 OSL " \ +"C3 CTL2 " \ +"H3A HAL2 " \ +"H3B HAL2 " \ +"C2 CTL1 " \ +"H2A HAL1 " \ +"O2 OHL " \ +"H2 HOL " \ +"C1 CTL2 " \ +"H1A HAL2 " \ +"H1B HAL2 " \ +"O1 OHL " \ +"H1 HOL " \ +"1C1 CTL2 " \ +"1H1A HAL2 " \ +"1H1B HAL2 " \ +"1O1 OSL " \ +"2C1 CL " \ +"2O1 OBL " \ +"2C2 CTL2 " \ +"2H2A HAL2 " \ +"2H2B HAL2 " \ +"1C2 CTL1 " \ +"1H2A HAL1 " \ +"1O2 OSL " \ +"2C1 CL " \ +"2O1 OBL " \ +"2C2 CTL2 " \ +"2H2A HAL2 " \ +"2H2B HAL2 " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6B " \ +"C1' CN7B " \ +"H1' HN7 " \ +"N9 NN2B " \ +"C4 CN5 " \ +"N2 NN1 " \ +"H21 HN1 " \ +"H22 HN1 " \ +"N3 NN3G " \ +"C2 CN2 " \ +"N1 NN2G " \ +"H1 HN2 " \ +"C6 CN1 " \ +"O6 ON1 " \ +"C5 CN5G " \ +"N7 NN4 " \ +"C8 CN4 " \ +"H8 HN3 " \ +"C2' CN7B " \ +"H2'' HN7 " \ +"O2' ON5 " \ +"H2' HN5 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"O3' ON2 " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6B " \ +"C1' CN7B " \ +"H1' HN7 " \ +"N9 NN2 " \ +"C5 CN5 " \ +"N7 NN4 " \ +"C8 CN4 " \ +"H8 HN3 " \ +"N1 NN3A " \ +"C2 CN4 " \ +"H2 HN3 " \ +"N3 NN3A " \ +"C4 CN5 " \ +"C6 CN2 " \ +"N6 NN1 " \ +"H61 HN1 " \ +"H62 HN1 " \ +"C2' CN7B " \ +"H2'' HN7 " \ +"O2' ON5 " \ +"H2' HN5 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"O3' ON2 " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6B " \ +"C1' CN7B " \ +"H1' HN7 " \ +"N1 NN2 " \ +"C6 CN3 " \ +"H6 HN3 " \ +"C5 CN3 " \ +"H5 HN3 " \ +"C2 CN1 " \ +"O2 ON1C " \ +"N3 NN3 " \ +"C4 CN2 " \ +"N4 NN1 " \ +"H41 HN1 " \ +"H42 HN1 " \ +"C2' CN7B " \ +"H2'' HN7 " \ +"O2' ON5 " \ +"H2' HN5 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"O3' ON2 " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6B " \ +"C1' CN7B " \ +"H1' HN7 " \ +"N1 NN2B " \ +"C6 CN3 " \ +"H6 HN3 " \ +"C2 CN1T " \ +"O2 ON1 " \ +"N3 NN2U " \ +"H3 HN2 " \ +"C4 CN1 " \ +"O4 ON1 " \ +"C5 CN3T " \ +"C5M CN9 " \ +"H51 HN9 " \ +"H52 HN9 " \ +"H53 HN9 " \ +"C2' CN7B " \ +"H2'' HN7 " \ +"O2' ON5 " \ +"H2' HN5 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"O3' ON2 " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6B " \ +"C1' CN7B " \ +"H1' HN7 " \ +"N1 NN2B " \ +"C6 CN3 " \ +"H6 HN3 " \ +"C2 CN1T " \ +"O2 ON1 " \ +"N3 NN2U " \ +"H3 HN2 " \ +"C4 CN1 " \ +"O4 ON1 " \ +"C5 CN3 " \ +"H5 HN3 " \ +"C2' CN7B " \ +"H2'' HN7 " \ +"O2' ON5 " \ +"H2' HN5 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"O3' ON2 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6 " \ +"C1' CN7B " \ +"H1' HN7 " \ +"C2' CN8 " \ +"H2' HN8 " \ +"H2'' HN8 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6 " \ +"C1' CN7B " \ +"H1' HN7 " \ +"C2' CN8 " \ +"H2' HN8 " \ +"H2'' HN8 " \ +"H5T HN5 " \ +"O5' ON5 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"C5' CN9 " \ +"H5' HN9 " \ +"H5'' HN9 " \ +"H53' HN9 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"O5T ON4 " \ +"H5T HN4 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"O5T ON2 " \ +"C5T CN9 " \ +"H5T1 HN9 " \ +"H5T2 HN9 " \ +"H5T3 HN9 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"O3' ON5 " \ +"H3T HN5 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"P3 P " \ +"O1P3 ON3 " \ +"O2P3 ON3 " \ +"O3' ON2 " \ +"O3T ON4 " \ +"H3T HN4 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"P3 P " \ +"O1P3 ON3 " \ +"O2P3 ON3 " \ +"O3' ON2 " \ +"O3T ON2 " \ +"C3T CN9 " \ +"H3T1 HN9 " \ +"H3T2 HN9 " \ +"H3T3 HN9 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"P3 P " \ +"O3' ON2 " \ +"O1P3 ON3 " \ +"O2P3 ON3 " \ +"O3P3 ON3 " \ +"OH2 OT " \ +"H1 HT " \ +"H2 HT " \ +"OH2 OT " \ +"H1 HT " \ +"H2 HT " \ +"SOD SOD " \ +"MG MG " \ +"POT POT " \ +"CES CES " \ +"CAL CAL " \ +"CLA CLA " \ +"ZN ZN " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT3 " \ +"HB1 HA " \ +"HB2 HA " \ +"HB3 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"CD CT2 " \ +"HD1 HA " \ +"HD2 HA " \ +"NE NC2 " \ +"HE HC " \ +"CZ C " \ +"NH1 NC2 " \ +"HH11 HC " \ +"HH12 HC " \ +"NH2 NC2 " \ +"HH21 HC " \ +"HH22 HC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CC " \ +"OD1 O " \ +"ND2 NH2 " \ +"HD21 H " \ +"HD22 H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CC " \ +"OD1 OC " \ +"OD2 OC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"SG S " \ +"HG1 HS " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"CD CC " \ +"OE1 O " \ +"NE2 NH2 " \ +"HE21 H " \ +"HE22 H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"CD CC " \ +"OE1 OC " \ +"OE2 OC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT2 " \ +"HA1 HB " \ +"HA2 HB " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"ND1 NR1 " \ +"HD1 H " \ +"CG CPH1 " \ +"CE1 CPH2 " \ +"HE1 HR1 " \ +"NE2 NR2 " \ +"CD2 CPH1 " \ +"HD2 HR3 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"ND1 NR2 " \ +"CG CPH1 " \ +"CE1 CPH2 " \ +"HE1 HR1 " \ +"NE2 NR1 " \ +"HE2 H " \ +"CD2 CPH1 " \ +"HD2 HR3 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CD2 CPH1 " \ +"HD2 HR1 " \ +"CG CPH1 " \ +"NE2 NR3 " \ +"HE2 H " \ +"ND1 NR3 " \ +"HD1 H " \ +"CE1 CPH2 " \ +"HE1 HR2 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT1 " \ +"HB HA " \ +"CG2 CT3 " \ +"HG21 HA " \ +"HG22 HA " \ +"HG23 HA " \ +"CG1 CT2 " \ +"HG11 HA " \ +"HG12 HA " \ +"CD CT3 " \ +"HD1 HA " \ +"HD2 HA " \ +"HD3 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT1 " \ +"HG HA " \ +"CD1 CT3 " \ +"HD11 HA " \ +"HD12 HA " \ +"HD13 HA " \ +"CD2 CT3 " \ +"HD21 HA " \ +"HD22 HA " \ +"HD23 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"CD CT2 " \ +"HD1 HA " \ +"HD2 HA " \ +"CE CT2 " \ +"HE1 HA " \ +"HE2 HA " \ +"NZ NH3 " \ +"HZ1 HC " \ +"HZ2 HC " \ +"HZ3 HC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"SD S " \ +"CE CT3 " \ +"HE1 HA " \ +"HE2 HA " \ +"HE3 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CA " \ +"CD1 CA " \ +"HD1 HP " \ +"CE1 CA " \ +"HE1 HP " \ +"CZ CA " \ +"HZ HP " \ +"CD2 CA " \ +"HD2 HP " \ +"CE2 CA " \ +"HE2 HP " \ +"C C " \ +"O O " \ +"N N " \ +"CD CP3 " \ +"HD1 HA " \ +"HD2 HA " \ +"CA CP1 " \ +"HA HB " \ +"CB CP2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CP2 " \ +"HG1 HA " \ +"HG2 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"OG OH1 " \ +"HG1 H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT1 " \ +"HB HA " \ +"OG1 OH1 " \ +"HG1 H " \ +"CG2 CT3 " \ +"HG21 HA " \ +"HG22 HA " \ +"HG23 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CY " \ +"CD1 CA " \ +"HD1 HP " \ +"NE1 NY " \ +"HE1 H " \ +"CE2 CPT " \ +"CD2 CPT " \ +"CE3 CA " \ +"HE3 HP " \ +"CZ3 CA " \ +"HZ3 HP " \ +"CZ2 CA " \ +"HZ2 HP " \ +"CH2 CA " \ +"HH2 HP " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CA " \ +"CD1 CA " \ +"HD1 HP " \ +"CE1 CA " \ +"HE1 HP " \ +"CZ CA " \ +"OH OH1 " \ +"HH H " \ +"CD2 CA " \ +"HD2 HP " \ +"CE2 CA " \ +"HE2 HP " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT1 " \ +"HB HA " \ +"CG1 CT3 " \ +"HG11 HA " \ +"HG12 HA " \ +"HG13 HA " \ +"CG2 CT3 " \ +"HG21 HA " \ +"HG22 HA " \ +"HG23 HA " \ +"C C " \ +"O O " \ +"CL CT3 " \ +"HL1 HA " \ +"HL2 HA " \ +"HL3 HA " \ +"CLP C " \ +"OL O " \ +"NL NH1 " \ +"HL H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT3 " \ +"HB1 HA " \ +"HB2 HA " \ +"HB3 HA " \ +"CRP C " \ +"OR O " \ +"NR NH1 " \ +"HR H " \ +"CR CT3 " \ +"HR1 HA " \ +"HR2 HA " \ +"HR3 HA " \ +"OH2 OT " \ +"H1 HT " \ +"H2 HT " \ +"OH2 OT " \ +"H1 HT " \ +"H2 HT " \ +"N NH3 " \ +"HT1 HC " \ +"HT2 HC " \ +"HT3 HC " \ +"CA CT1 " \ +"HA HB " \ +"N NH3 " \ +"HT1 HC " \ +"HT2 HC " \ +"HT3 HC " \ +"CA CT2 " \ +"HA1 HB " \ +"HA2 HB " \ +"N NP " \ +"HN1 HC " \ +"HN2 HC " \ +"CD CP3 " \ +"HD1 HA " \ +"HD2 HA " \ +"CA CP1 " \ +"HA HB " \ +"CAY CT3 " \ +"HY1 HA " \ +"HY2 HA " \ +"HY3 HA " \ +"CY C " \ +"OY O " \ +"CAY CT3 " \ +"HY1 HA " \ +"HY2 HA " \ +"HY3 HA " \ +"CY C " \ +"OY O " \ +"C CC " \ +"OT1 OC " \ +"OT2 OC " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"C CD " \ +"OT1 OB " \ +"OT2 OS " \ +"CT CT3 " \ +"HT1 HA " \ +"HT2 HA " \ +"HT3 HA " \ +"C CC " \ +"O O " \ +"NT NH2 " \ +"HT1 H " \ +"HT2 H " \ +"C C " \ +"O O " \ +"NT NH1 " \ +"HNT H " \ +"CAT CT3 " \ +"HT1 HA " \ +"HT2 HA " \ +"HT3 HA " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CD " \ +"OD1 OB " \ +"OD2 OH1 " \ +"HD2 H " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"CD CD " \ +"OE1 OB " \ +"OE2 OH1 " \ +"HE2 H " \ +"CE CT2 " \ +"HE1 HA " \ +"HE2 HA " \ +"NZ NH2 " \ +"HZ1 HC " \ +"HZ2 HC " \ +"1CB CT2 " \ +"1SG SM " \ +"2SG SM " \ +"2CB CT2 " \ +"CE1 CPH2 " \ +"HE1 HR1 " \ +"ND1 NR2 " \ +"CG CPH1 " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"NE2 NR1 " \ +"HE2 H " \ +"CD2 CPH1 " \ +"HD2 HR3 " \ +"N NTL " \ +"C13 CTL5 " \ +"H13A HL " \ +"H13B HL " \ +"H13C HL " \ +"C14 CTL5 " \ +"H14A HL " \ +"H14B HL " \ +"H14C HL " \ +"C15 CTL5 " \ +"H15A HL " \ +"H15B HL " \ +"H15C HL " \ +"C12 CTL2 " \ +"H12A HL " \ +"H12B HL " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"P PL " \ +"O13 O2L " \ +"O14 O2L " \ +"O11 OSL " \ +"O12 OSL " \ +"C1 CTL2 " \ +"HA HAL2 " \ +"HB HAL2 " \ +"C2 CTL2 " \ +"HS HAL2 " \ +"HR HAL2 " \ +"C3 CTL2 " \ +"HX HAL2 " \ +"HY HAL2 " \ +"O31 OSL " \ +"C31 CL " \ +"O32 OBL " \ +"C32 CTL2 " \ +"H2X HAL2 " \ +"H2Y HAL2 " \ +"C33 CTL2 " \ +"H3X HAL2 " \ +"H3Y HAL2 " \ +"C34 CTL2 " \ +"H4X HAL2 " \ +"H4Y HAL2 " \ +"C35 CTL2 " \ +"H5X HAL2 " \ +"H5Y HAL2 " \ +"C36 CTL2 " \ +"H6X HAL2 " \ +"H6Y HAL2 " \ +"C37 CTL2 " \ +"H7X HAL2 " \ +"H7Y HAL2 " \ +"C38 CTL2 " \ +"H8X HAL2 " \ +"H8Y HAL2 " \ +"C39 CTL2 " \ +"H9X HAL2 " \ +"H9Y HAL2 " \ +"C310 CTL2 " \ +"H10X HAL2 " \ +"H10Y HAL2 " \ +"C311 CTL2 " \ +"H11X HAL2 " \ +"H11Y HAL2 " \ +"C312 CTL3 " \ +"H12X HAL3 " \ +"H12Y HAL3 " \ +"H12Z HAL3 " \ +"N NH3 " \ +"HN1 HCL " \ +"HN2 HCL " \ +"HN3 HCL " \ +"C12 CTL " \ +"H12A HAL " \ +"H12B HAL " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"P PL " \ +"O13 O2L " \ +"O14 O2L " \ +"O11 OSL " \ +"O12 OSL " \ +"C1 CTL2 " \ +"HA HAL2 " \ +"HB HAL2 " \ +"C2 CTL1 " \ +"HS HAL1 " \ +"OH2 OHL " \ +"HO2 HOL " \ +"C3 CTL2 " \ +"HX HAL2 " \ +"HY HAL2 " \ +"OH3 OHL " \ +"HO3 HOL " \ +"N NH3 " \ +"HN1 HCL " \ +"HN2 HCL " \ +"HN3 HCL " \ +"C12 CTL " \ +"H12A HAL " \ +"H12B HAL " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"P PL " \ +"O13 O2L " \ +"O14 O2L " \ +"O11 OSL " \ +"O12 OSL " \ +"C1 CTL2 " \ +"HA HAL2 " \ +"HB HAL2 " \ +"C2 CTL1 " \ +"HS HAL1 " \ +"O21 OSL " \ +"C21 CL " \ +"O22 OBL " \ +"C22 CTL2 " \ +"H2R HAL2 " \ +"H2S HAL2 " \ +"C3 CTL2 " \ +"HX HAL2 " \ +"HY HAL2 " \ +"O31 OSL " \ +"C31 CL " \ +"O32 OBL " \ +"C32 CTL2 " \ +"H2X HAL2 " \ +"H2Y HAL2 " \ +"C23 CTL2 " \ +"H3R HAL2 " \ +"H3S HAL2 " \ +"C24 CTL2 " \ +"H4R HAL2 " \ +"H4S HAL2 " \ +"C25 CTL2 " \ +"H5R HAL2 " \ +"H5S HAL2 " \ +"C26 CTL2 " \ +"H6R HAL2 " \ +"H6S HAL2 " \ +"C27 CTL2 " \ +"H7R HAL2 " \ +"H7S HAL2 " \ +"C28 CTL2 " \ +"H8R HAL2 " \ +"H8S HAL2 " \ +"C29 CTL2 " \ +"H9R HAL2 " \ +"H9S HAL2 " \ +"C210 CTL2 " \ +"H10R HAL2 " \ +"H10S HAL2 " \ +"C211 CTL2 " \ +"H11R HAL2 " \ +"H11S HAL2 " \ +"C212 CTL3 " \ +"H12R HAL3 " \ +"H12S HAL3 " \ +"H12T HAL3 " \ +"C33 CTL2 " \ +"H3X HAL2 " \ +"H3Y HAL2 " \ +"C34 CTL2 " \ +"H4X HAL2 " \ +"H4Y HAL2 " \ +"C35 CTL2 " \ +"H5X HAL2 " \ +"H5Y HAL2 " \ +"C36 CTL2 " \ +"H6X HAL2 " \ +"H6Y HAL2 " \ +"C37 CTL2 " \ +"H7X HAL2 " \ +"H7Y HAL2 " \ +"C38 CTL2 " \ +"H8X HAL2 " \ +"H8Y HAL2 " \ +"C39 CTL2 " \ +"H9X HAL2 " \ +"H9Y HAL2 " \ +"C310 CTL2 " \ +"H10X HAL2 " \ +"H10Y HAL2 " \ +"C311 CTL2 " \ +"H11X HAL2 " \ +"H11Y HAL2 " \ +"C312 CTL3 " \ +"H12X HAL3 " \ +"H12Y HAL3 " \ +"H12Z HAL3 " \ +"N NTL " \ +"C13 CTL5 " \ +"H13A HL " \ +"H13B HL " \ +"H13C HL " \ +"C14 CTL5 " \ +"H14A HL " \ +"H14B HL " \ +"H14C HL " \ +"C15 CTL5 " \ +"H15A HL " \ +"H15B HL " \ +"H15C HL " \ +"C12 CTL2 " \ +"H12A HL " \ +"H12B HL " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"P PL " \ +"O13 O2L " \ +"O14 O2L " \ +"O11 OSL " \ +"O12 OSL " \ +"C1 CTL2 " \ +"HA HAL2 " \ +"HB HAL2 " \ +"C2 CTL1 " \ +"HS HAL1 " \ +"O21 OSL " \ +"C21 CL " \ +"O22 OBL " \ +"C22 CTL2 " \ +"H2R HAL2 " \ +"H2S HAL2 " \ +"C3 CTL2 " \ +"HX HAL2 " \ +"HY HAL2 " \ +"O31 OSL " \ +"C31 CL " \ +"O32 OBL " \ +"C32 CTL2 " \ +"H2X HAL2 " \ +"H2Y HAL2 " \ +"C23 CTL2 " \ +"H3R HAL2 " \ +"H3S HAL2 " \ +"C24 CTL2 " \ +"H4R HAL2 " \ +"H4S HAL2 " \ +"C25 CTL2 " \ +"H5R HAL2 " \ +"H5S HAL2 " \ +"C26 CTL2 " \ +"H6R HAL2 " \ +"H6S HAL2 " \ +"C27 CTL2 " \ +"H7R HAL2 " \ +"H7S HAL2 " \ +"C28 CTL2 " \ +"H8R HAL2 " \ +"H8S HAL2 " \ +"C29 CTL2 " \ +"H9R HAL2 " \ +"H9S HAL2 " \ +"C210 CTL2 " \ +"H10R HAL2 " \ +"H10S HAL2 " \ +"C211 CTL2 " \ +"H11R HAL2 " \ +"H11S HAL2 " \ +"C212 CTL2 " \ +"H12R HAL2 " \ +"H12S HAL2 " \ +"C213 CTL2 " \ +"H13R HAL2 " \ +"H13S HAL2 " \ +"C214 CTL3 " \ +"H14R HAL3 " \ +"H14S HAL3 " \ +"H14T HAL3 " \ +"C33 CTL2 " \ +"H3X HAL2 " \ +"H3Y HAL2 " \ +"C34 CTL2 " \ +"H4X HAL2 " \ +"H4Y HAL2 " \ +"C35 CTL2 " \ +"H5X HAL2 " \ +"H5Y HAL2 " \ +"C36 CTL2 " \ +"H6X HAL2 " \ +"H6Y HAL2 " \ +"C37 CTL2 " \ +"H7X HAL2 " \ +"H7Y HAL2 " \ +"C38 CTL2 " \ +"H8X HAL2 " \ +"H8Y HAL2 " \ +"C39 CTL2 " \ +"H9X HAL2 " \ +"H9Y HAL2 " \ +"C310 CTL2 " \ +"H10X HAL2 " \ +"H10Y HAL2 " \ +"C311 CTL2 " \ +"H11X HAL2 " \ +"H11Y HAL2 " \ +"C312 CTL2 " \ +"H12X HAL2 " \ +"H12Y HAL2 " \ +"C313 CTL2 " \ +"H13X HAL2 " \ +"H13Y HAL2 " \ +"C314 CTL3 " \ +"H14X HAL3 " \ +"H14Y HAL3 " \ +"H14Z HAL3 " \ +"S SL " \ +"OS1 OSL " \ +"OS2 O2L " \ +"OS3 O2L " \ +"OS4 O2L " \ +"C1 CTL2 " \ +"H11 HAL2 " \ +"H12 HAL2 " \ +"C2 CTL2 " \ +"H21 HAL2 " \ +"H22 HAL2 " \ +"C3 CTL2 " \ +"H31 HAL2 " \ +"H32 HAL2 " \ +"C4 CTL2 " \ +"H41 HAL2 " \ +"H42 HAL2 " \ +"C5 CTL2 " \ +"H51 HAL2 " \ +"H52 HAL2 " \ +"C6 CTL2 " \ +"H61 HAL2 " \ +"H62 HAL2 " \ +"C7 CTL2 " \ +"H71 HAL2 " \ +"H72 HAL2 " \ +"C8 CTL2 " \ +"H81 HAL2 " \ +"H82 HAL2 " \ +"C9 CTL2 " \ +"H91 HAL2 " \ +"H92 HAL2 " \ +"C10 CTL2 " \ +"H101 HAL2 " \ +"H102 HAL2 " \ +"C11 CTL2 " \ +"H111 HAL2 " \ +"H112 HAL2 " \ +"C12 CTL3 " \ +"H121 HAL3 " \ +"H122 HAL3 " \ +"H123 HAL3 " \ +"N NTL " \ +"C11 CTL2 " \ +"C12 CTL5 " \ +"C13 CTL5 " \ +"C14 CTL5 " \ +"H11 HL " \ +"H12 HL " \ +"H21 HL " \ +"H22 HL " \ +"H23 HL " \ +"H31 HL " \ +"H32 HL " \ +"H33 HL " \ +"H41 HL " \ +"H42 HL " \ +"H43 HL " \ +"C15 CTL2 " \ +"H51 HAL2 " \ +"H52 HAL2 " \ +"P1 PL " \ +"O3 O2L " \ +"O4 O2L " \ +"O1 OSL " \ +"O2 OSL " \ +"C1 CTL2 " \ +"HA HAL2 " \ +"HB HAL2 " \ +"C2 CTL1 " \ +"HS HAL1 " \ +"O21 OSL " \ +"C21 CL " \ +"O22 OBL " \ +"C22 CTL2 " \ +"H2R HAL2 " \ +"H2S HAL2 " \ +"C3 CTL2 " \ +"HX HAL2 " \ +"HY HAL2 " \ +"O31 OSL " \ +"C31 CL " \ +"O32 OBL " \ +"C32 CTL2 " \ +"H2X HAL2 " \ +"H2Y HAL2 " \ +"C23 CTL2 " \ +"H3R HAL2 " \ +"H3S HAL2 " \ +"C24 CTL2 " \ +"H4R HAL2 " \ +"H4S HAL2 " \ +"C25 CTL2 " \ +"H5R HAL2 " \ +"H5S HAL2 " \ +"C26 CTL2 " \ +"H6R HAL2 " \ +"H6S HAL2 " \ +"C27 CTL2 " \ +"H7R HAL2 " \ +"H7S HAL2 " \ +"C28 CTL2 " \ +"H8R HAL2 " \ +"H8S HAL2 " \ +"C29 CEL1 " \ +"H91 HEL1 " \ +"C210 CEL1 " \ +"H101 HEL1 " \ +"C211 CTL2 " \ +"H11R HAL2 " \ +"H11S HAL2 " \ +"C212 CTL2 " \ +"H12R HAL2 " \ +"H12S HAL2 " \ +"C213 CTL2 " \ +"H13R HAL2 " \ +"H13S HAL2 " \ +"C214 CTL2 " \ +"H14R HAL2 " \ +"H14S HAL2 " \ +"C215 CTL2 " \ +"H15R HAL2 " \ +"H15S HAL2 " \ +"C216 CTL2 " \ +"H16R HAL2 " \ +"H16S HAL2 " \ +"C217 CTL2 " \ +"H17R HAL2 " \ +"H17S HAL2 " \ +"C218 CTL3 " \ +"H18R HAL3 " \ +"H18S HAL3 " \ +"H18T HAL3 " \ +"C33 CTL2 " \ +"H3X HAL2 " \ +"H3Y HAL2 " \ +"C34 CTL2 " \ +"H4X HAL2 " \ +"H4Y HAL2 " \ +"C35 CTL2 " \ +"H5X HAL2 " \ +"H5Y HAL2 " \ +"C36 CTL2 " \ +"H6X HAL2 " \ +"H6Y HAL2 " \ +"C37 CTL2 " \ +"H7X HAL2 " \ +"H7Y HAL2 " \ +"C38 CTL2 " \ +"H8X HAL2 " \ +"H8Y HAL2 " \ +"C39 CTL2 " \ +"H9X HAL2 " \ +"H9Y HAL2 " \ +"C310 CTL2 " \ +"H10X HAL2 " \ +"H10Y HAL2 " \ +"C311 CTL2 " \ +"H11X HAL2 " \ +"H11Y HAL2 " \ +"C312 CTL2 " \ +"H12X HAL2 " \ +"H12Y HAL2 " \ +"C313 CTL2 " \ +"H13X HAL2 " \ +"H13Y HAL2 " \ +"C314 CTL2 " \ +"H14X HAL2 " \ +"H14Y HAL2 " \ +"C315 CTL2 " \ +"H15X HAL2 " \ +"H15Y HAL2 " \ +"C316 CTL3 " \ +"H16X HAL3 " \ +"H16Y HAL3 " \ +"H16Z HAL3 " \ +"N NH3 " \ +"HN1 HCL " \ +"HN2 HCL " \ +"HN3 HCL " \ +"C12 CTL " \ +"H12A HAL " \ +"H12B HAL " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"P PL " \ +"O13 O2L " \ +"O14 O2L " \ +"O11 OSL " \ +"O12 OSL " \ +"C1 CTL2 " \ +"HA HAL2 " \ +"HB HAL2 " \ +"C2 CTL1 " \ +"HS HAL1 " \ +"O21 OSL " \ +"C21 CL " \ +"O22 OBL " \ +"C22 CTL2 " \ +"H2R HAL2 " \ +"H2S HAL2 " \ +"C3 CTL2 " \ +"HX HAL2 " \ +"HY HAL2 " \ +"O31 OSL " \ +"C31 CL " \ +"O32 OBL " \ +"C32 CTL2 " \ +"H2X HAL2 " \ +"H2Y HAL2 " \ +"C23 CTL2 " \ +"H3R HAL2 " \ +"H3S HAL2 " \ +"C24 CTL2 " \ +"H4R HAL2 " \ +"H4S HAL2 " \ +"C25 CTL2 " \ +"H5R HAL2 " \ +"H5S HAL2 " \ +"C26 CTL2 " \ +"H6R HAL2 " \ +"H6S HAL2 " \ +"C27 CTL2 " \ +"H7R HAL2 " \ +"H7S HAL2 " \ +"C28 CTL2 " \ +"H8R HAL2 " \ +"H8S HAL2 " \ +"C29 CEL1 " \ +"H91 HEL1 " \ +"C210 CEL1 " \ +"H101 HEL1 " \ +"C211 CTL2 " \ +"H11R HAL2 " \ +"H11S HAL2 " \ +"C212 CTL2 " \ +"H12R HAL2 " \ +"H12S HAL2 " \ +"C213 CTL2 " \ +"H13R HAL2 " \ +"H13S HAL2 " \ +"C214 CTL2 " \ +"H14R HAL2 " \ +"H14S HAL2 " \ +"C215 CTL2 " \ +"H15R HAL2 " \ +"H15S HAL2 " \ +"C216 CTL2 " \ +"H16R HAL2 " \ +"H16S HAL2 " \ +"C217 CTL2 " \ +"H17R HAL2 " \ +"H17S HAL2 " \ +"C218 CTL3 " \ +"H18R HAL3 " \ +"H18S HAL3 " \ +"H18T HAL3 " \ +"C33 CTL2 " \ +"H3X HAL2 " \ +"H3Y HAL2 " \ +"C34 CTL2 " \ +"H4X HAL2 " \ +"H4Y HAL2 " \ +"C35 CTL2 " \ +"H5X HAL2 " \ +"H5Y HAL2 " \ +"C36 CTL2 " \ +"H6X HAL2 " \ +"H6Y HAL2 " \ +"C37 CTL2 " \ +"H7X HAL2 " \ +"H7Y HAL2 " \ +"C38 CTL2 " \ +"H8X HAL2 " \ +"H8Y HAL2 " \ +"C39 CTL2 " \ +"H9X HAL2 " \ +"H9Y HAL2 " \ +"C310 CTL2 " \ +"H10X HAL2 " \ +"H10Y HAL2 " \ +"C311 CTL2 " \ +"H11X HAL2 " \ +"H11Y HAL2 " \ +"C312 CTL2 " \ +"H12X HAL2 " \ +"H12Y HAL2 " \ +"C313 CTL2 " \ +"H13X HAL2 " \ +"H13Y HAL2 " \ +"C314 CTL2 " \ +"H14X HAL2 " \ +"H14Y HAL2 " \ +"C315 CTL2 " \ +"H15X HAL2 " \ +"H15Y HAL2 " \ +"C316 CTL3 " \ +"H16X HAL3 " \ +"H16Y HAL3 " \ +"H16Z HAL3 " \ +"C1 CL " \ +"O1 OCL " \ +"O2 OCL " \ +"C2 CTL2 " \ +"H2A HAL2 " \ +"H2B HAL2 " \ +"C3 CTL2 " \ +"H3A HAL2 " \ +"H3B HAL2 " \ +"C4 CTL2 " \ +"H4A HAL2 " \ +"H4B HAL2 " \ +"C5 CTL2 " \ +"H5A HAL2 " \ +"H5B HAL2 " \ +"C6 CTL2 " \ +"H6A HAL2 " \ +"H6B HAL2 " \ +"C7 CTL2 " \ +"H7A HAL2 " \ +"H7B HAL2 " \ +"C8 CTL2 " \ +"H8A HAL2 " \ +"H8B HAL2 " \ +"C9 CTL2 " \ +"H9A HAL2 " \ +"H9B HAL2 " \ +"C10 CTL2 " \ +"H10A HAL2 " \ +"H10B HAL2 " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"C12 CTL2 " \ +"H12A HAL2 " \ +"H12B HAL2 " \ +"C13 CTL2 " \ +"H13A HAL2 " \ +"H13B HAL2 " \ +"C14 CTL2 " \ +"H14A HAL2 " \ +"H14B HAL2 " \ +"C15 CTL2 " \ +"H15A HAL2 " \ +"H15B HAL2 " \ +"C16 CTL3 " \ +"H16A HAL3 " \ +"H16B HAL3 " \ +"H16C HAL3 " \ +"C1 CL " \ +"O1 OCL " \ +"O2 OCL " \ +"C2 CTL2 " \ +"H2A HAL2 " \ +"H2B HAL2 " \ +"C3 CTL2 " \ +"H3A HAL2 " \ +"H3B HAL2 " \ +"C4 CTL2 " \ +"H4A HAL2 " \ +"H4B HAL2 " \ +"C5 CTL2 " \ +"H5A HAL2 " \ +"H5B HAL2 " \ +"C6 CTL2 " \ +"H6A HAL2 " \ +"H6B HAL2 " \ +"C7 CTL2 " \ +"H7A HAL2 " \ +"H7B HAL2 " \ +"C8 CTL2 " \ +"H8A HAL2 " \ +"H8B HAL2 " \ +"C9 CEL1 " \ +"H9A HEL1 " \ +"C10 CEL1 " \ +"H10A HEL1 " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"C12 CTL2 " \ +"H12A HAL2 " \ +"H12B HAL2 " \ +"C13 CTL2 " \ +"H13A HAL2 " \ +"H13B HAL2 " \ +"C14 CTL2 " \ +"H14A HAL2 " \ +"H14B HAL2 " \ +"C15 CTL2 " \ +"H15A HAL2 " \ +"H15B HAL2 " \ +"C16 CTL2 " \ +"H16A HAL2 " \ +"H16B HAL2 " \ +"C17 CTL2 " \ +"H17A HAL2 " \ +"H17B HAL2 " \ +"C18 CTL3 " \ +"H18A HAL3 " \ +"H18B HAL3 " \ +"H18C HAL3 " \ +"C1 CL " \ +"O1 OCL " \ +"O2 OCL " \ +"C2 CTL2 " \ +"H2A HAL2 " \ +"H2B HAL2 " \ +"C3 CTL2 " \ +"H3A HAL2 " \ +"H3B HAL2 " \ +"C4 CEL1 " \ +"H4 HEL1 " \ +"C5 CEL1 " \ +"H5 HEL1 " \ +"C6 CTL2 " \ +"H6A HAL2 " \ +"H6B HAL2 " \ +"C7 CEL1 " \ +"H7 HEL1 " \ +"C8 CEL1 " \ +"H8 HEL1 " \ +"C9 CTL2 " \ +"H9A HAL2 " \ +"H9B HAL2 " \ +"C10 CEL1 " \ +"H10 HEL1 " \ +"C11 CEL1 " \ +"H11 HEL1 " \ +"C12 CTL2 " \ +"H12A HAL2 " \ +"H12B HAL2 " \ +"C13 CEL1 " \ +"H13 HEL1 " \ +"C14 CEL1 " \ +"H14 HEL1 " \ +"C15 CTL2 " \ +"H15A HAL2 " \ +"H15B HAL2 " \ +"C16 CEL1 " \ +"H16 HEL1 " \ +"C17 CEL1 " \ +"H17 HEL1 " \ +"C18 CTL2 " \ +"H18A HAL2 " \ +"H18B HAL2 " \ +"C19 CEL1 " \ +"H19 HEL1 " \ +"C20 CEL1 " \ +"H20 HEL1 " \ +"C21 CTL2 " \ +"H21A HAL2 " \ +"H21B HAL2 " \ +"C22 CTL3 " \ +"H22A HAL3 " \ +"H22B HAL3 " \ +"H22C HAL3 " \ +"C1 CL " \ +"O1 OCL " \ +"O2 OCL " \ +"C2 CTL2 " \ +"H2A HAL2 " \ +"H2B HAL2 " \ +"C3 CTL2 " \ +"H3A HAL2 " \ +"H3B HAL2 " \ +"C4 CTL2 " \ +"H4A HAL2 " \ +"H4B HAL2 " \ +"C5 CTL2 " \ +"H5A HAL2 " \ +"H5B HAL2 " \ +"C6 CTL2 " \ +"H6A HAL2 " \ +"H6B HAL2 " \ +"C7 CTL2 " \ +"H7A HAL2 " \ +"H7B HAL2 " \ +"C8 CTL2 " \ +"H8A HAL2 " \ +"H8B HAL2 " \ +"C9 CTL2 " \ +"H9A HAL2 " \ +"H9B HAL2 " \ +"C10 CTL2 " \ +"H10A HAL2 " \ +"H10B HAL2 " \ +"C11 CTL2 " \ +"H11A HAL2 " \ +"H11B HAL2 " \ +"C12 CTL2 " \ +"H12A HAL2 " \ +"H12B HAL2 " \ +"C13 CTL2 " \ +"H13A HAL2 " \ +"H13B HAL2 " \ +"C14 CTL2 " \ +"H14A HAL2 " \ +"H14B HAL2 " \ +"C15 CTL2 " \ +"H15A HAL2 " \ +"H15B HAL2 " \ +"C16 CTL2 " \ +"H16A HAL2 " \ +"H16B HAL2 " \ +"C17 CTL2 " \ +"H17A HAL2 " \ +"H17B HAL2 " \ +"C18 CTL3 " \ +"H18A HAL3 " \ +"H18B HAL3 " \ +"H18C HAL3 " \ +"N NTL " \ +"C5 CTL2 " \ +"C6 CTL5 " \ +"C7 CTL5 " \ +"C8 CTL5 " \ +"H5A HL " \ +"H5B HL " \ +"H6A HL " \ +"H6B HL " \ +"H6C HL " \ +"H7A HL " \ +"H7B HL " \ +"H7C HL " \ +"H8A HL " \ +"H8B HL " \ +"H8C HL " \ +"C4 CTL2 " \ +"H4A HAL2 " \ +"H4B HAL2 " \ +"P PL " \ +"OP3 O2L " \ +"OP4 O2L " \ +"OP1 OSL " \ +"OP2 OSL " \ +"C3 CTL2 " \ +"H3A HAL2 " \ +"H3B HAL2 " \ +"C2 CTL1 " \ +"H2A HAL1 " \ +"O2 OHL " \ +"H2 HOL " \ +"C1 CTL2 " \ +"H1A HAL2 " \ +"H1B HAL2 " \ +"O1 OHL " \ +"H1 HOL " \ +"1C1 CTL2 " \ +"1H1A HAL2 " \ +"1H1B HAL2 " \ +"1O1 OSL " \ +"2C1 CL " \ +"2O1 OBL " \ +"2C2 CTL2 " \ +"2H2A HAL2 " \ +"2H2B HAL2 " \ +"1C2 CTL1 " \ +"1H2A HAL1 " \ +"1O2 OSL " \ +"2C1 CL " \ +"2O1 OBL " \ +"2C2 CTL2 " \ +"2H2A HAL2 " \ +"2H2B HAL2 " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT3 " \ +"HB1 HA " \ +"HB2 HA " \ +"HB3 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"CD CT2 " \ +"HD1 HA " \ +"HD2 HA " \ +"NE NC2 " \ +"HE HC " \ +"CZ C " \ +"NH1 NC2 " \ +"HH11 HC " \ +"HH12 HC " \ +"NH2 NC2 " \ +"HH21 HC " \ +"HH22 HC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CC " \ +"OD1 O " \ +"ND2 NH2 " \ +"HD21 H " \ +"HD22 H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CC " \ +"OD1 OC " \ +"OD2 OC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"SG S " \ +"HG1 HS " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"CD CC " \ +"OE1 O " \ +"NE2 NH2 " \ +"HE21 H " \ +"HE22 H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"CD CC " \ +"OE1 OC " \ +"OE2 OC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT2 " \ +"HA1 HB " \ +"HA2 HB " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"ND1 NR1 " \ +"HD1 H " \ +"CG CPH1 " \ +"CE1 CPH2 " \ +"HE1 HR1 " \ +"NE2 NR2 " \ +"CD2 CPH1 " \ +"HD2 HR3 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"ND1 NR2 " \ +"CG CPH1 " \ +"CE1 CPH2 " \ +"HE1 HR1 " \ +"NE2 NR1 " \ +"HE2 H " \ +"CD2 CPH1 " \ +"HD2 HR3 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CD2 CPH1 " \ +"HD2 HR1 " \ +"CG CPH1 " \ +"NE2 NR3 " \ +"HE2 H " \ +"ND1 NR3 " \ +"HD1 H " \ +"CE1 CPH2 " \ +"HE1 HR2 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT1 " \ +"HB HA " \ +"CG2 CT3 " \ +"HG21 HA " \ +"HG22 HA " \ +"HG23 HA " \ +"CG1 CT2 " \ +"HG11 HA " \ +"HG12 HA " \ +"CD CT3 " \ +"HD1 HA " \ +"HD2 HA " \ +"HD3 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT1 " \ +"HG HA " \ +"CD1 CT3 " \ +"HD11 HA " \ +"HD12 HA " \ +"HD13 HA " \ +"CD2 CT3 " \ +"HD21 HA " \ +"HD22 HA " \ +"HD23 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"CD CT2 " \ +"HD1 HA " \ +"HD2 HA " \ +"CE CT2 " \ +"HE1 HA " \ +"HE2 HA " \ +"NZ NH3 " \ +"HZ1 HC " \ +"HZ2 HC " \ +"HZ3 HC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"SD S " \ +"CE CT3 " \ +"HE1 HA " \ +"HE2 HA " \ +"HE3 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CA " \ +"CD1 CA " \ +"HD1 HP " \ +"CE1 CA " \ +"HE1 HP " \ +"CZ CA " \ +"HZ HP " \ +"CD2 CA " \ +"HD2 HP " \ +"CE2 CA " \ +"HE2 HP " \ +"C C " \ +"O O " \ +"N N " \ +"CD CP3 " \ +"HD1 HA " \ +"HD2 HA " \ +"CA CP1 " \ +"HA HB " \ +"CB CP2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CP2 " \ +"HG1 HA " \ +"HG2 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"OG OH1 " \ +"HG1 H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT1 " \ +"HB HA " \ +"OG1 OH1 " \ +"HG1 H " \ +"CG2 CT3 " \ +"HG21 HA " \ +"HG22 HA " \ +"HG23 HA " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CY " \ +"CD1 CA " \ +"HD1 HP " \ +"NE1 NY " \ +"HE1 H " \ +"CE2 CPT " \ +"CD2 CPT " \ +"CE3 CA " \ +"HE3 HP " \ +"CZ3 CA " \ +"HZ3 HP " \ +"CZ2 CA " \ +"HZ2 HP " \ +"CH2 CA " \ +"HH2 HP " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CA " \ +"CD1 CA " \ +"HD1 HP " \ +"CE1 CA " \ +"HE1 HP " \ +"CZ CA " \ +"OH OH1 " \ +"HH H " \ +"CD2 CA " \ +"HD2 HP " \ +"CE2 CA " \ +"HE2 HP " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT1 " \ +"HB HA " \ +"CG1 CT3 " \ +"HG11 HA " \ +"HG12 HA " \ +"HG13 HA " \ +"CG2 CT3 " \ +"HG21 HA " \ +"HG22 HA " \ +"HG23 HA " \ +"C C " \ +"O O " \ +"CL CT3 " \ +"HL1 HA " \ +"HL2 HA " \ +"HL3 HA " \ +"CLP C " \ +"OL O " \ +"NL NH1 " \ +"HL H " \ +"CA CT1 " \ +"HA HB " \ +"CB CT3 " \ +"HB1 HA " \ +"HB2 HA " \ +"HB3 HA " \ +"CRP C " \ +"OR O " \ +"NR NH1 " \ +"HR H " \ +"CR CT3 " \ +"HR1 HA " \ +"HR2 HA " \ +"HR3 HA " \ +"OH2 OT " \ +"H1 HT " \ +"H2 HT " \ +"OH2 OT " \ +"H1 HT " \ +"H2 HT " \ +"N NH3 " \ +"HT1 HC " \ +"HT2 HC " \ +"HT3 HC " \ +"CA CT1 " \ +"HA HB " \ +"N NH3 " \ +"HT1 HC " \ +"HT2 HC " \ +"HT3 HC " \ +"CA CT2 " \ +"HA1 HB " \ +"HA2 HB " \ +"N NP " \ +"HN1 HC " \ +"HN2 HC " \ +"CD CP3 " \ +"HD1 HA " \ +"HD2 HA " \ +"CA CP1 " \ +"HA HB " \ +"CAY CT3 " \ +"HY1 HA " \ +"HY2 HA " \ +"HY3 HA " \ +"CY C " \ +"OY O " \ +"CAY CT3 " \ +"HY1 HA " \ +"HY2 HA " \ +"HY3 HA " \ +"CY C " \ +"OY O " \ +"C CC " \ +"OT1 OC " \ +"OT2 OC " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB " \ +"C CD " \ +"OT1 OB " \ +"OT2 OS " \ +"CT CT3 " \ +"HT1 HA " \ +"HT2 HA " \ +"HT3 HA " \ +"C CC " \ +"O O " \ +"NT NH2 " \ +"HT1 H " \ +"HT2 H " \ +"C C " \ +"O O " \ +"NT NH1 " \ +"HNT H " \ +"CAT CT3 " \ +"HT1 HA " \ +"HT2 HA " \ +"HT3 HA " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"CG CD " \ +"OD1 OB " \ +"OD2 OH1 " \ +"HD2 H " \ +"CG CT2 " \ +"HG1 HA " \ +"HG2 HA " \ +"CD CD " \ +"OE1 OB " \ +"OE2 OH1 " \ +"HE2 H " \ +"CE CT2 " \ +"HE1 HA " \ +"HE2 HA " \ +"NZ NH2 " \ +"HZ1 HC " \ +"HZ2 HC " \ +"1CB CT2 " \ +"1SG SM " \ +"2SG SM " \ +"2CB CT2 " \ +"CE1 CPH2 " \ +"HE1 HR1 " \ +"ND1 NR2 " \ +"CG CPH1 " \ +"CB CT2 " \ +"HB1 HA " \ +"HB2 HA " \ +"NE2 NR1 " \ +"HE2 H " \ +"CD2 CPH1 " \ +"HD2 HR3 " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6B " \ +"C1' CN7B " \ +"H1' HN7 " \ +"N9 NN2B " \ +"C4 CN5 " \ +"N2 NN1 " \ +"H21 HN1 " \ +"H22 HN1 " \ +"N3 NN3G " \ +"C2 CN2 " \ +"N1 NN2G " \ +"H1 HN2 " \ +"C6 CN1 " \ +"O6 ON1 " \ +"C5 CN5G " \ +"N7 NN4 " \ +"C8 CN4 " \ +"H8 HN3 " \ +"C2' CN7B " \ +"H2'' HN7 " \ +"O2' ON5 " \ +"H2' HN5 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"O3' ON2 " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6B " \ +"C1' CN7B " \ +"H1' HN7 " \ +"N9 NN2 " \ +"C5 CN5 " \ +"N7 NN4 " \ +"C8 CN4 " \ +"H8 HN3 " \ +"N1 NN3A " \ +"C2 CN4 " \ +"H2 HN3 " \ +"N3 NN3A " \ +"C4 CN5 " \ +"C6 CN2 " \ +"N6 NN1 " \ +"H61 HN1 " \ +"H62 HN1 " \ +"C2' CN7B " \ +"H2'' HN7 " \ +"O2' ON5 " \ +"H2' HN5 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"O3' ON2 " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6B " \ +"C1' CN7B " \ +"H1' HN7 " \ +"N1 NN2 " \ +"C6 CN3 " \ +"H6 HN3 " \ +"C5 CN3 " \ +"H5 HN3 " \ +"C2 CN1 " \ +"O2 ON1C " \ +"N3 NN3 " \ +"C4 CN2 " \ +"N4 NN1 " \ +"H41 HN1 " \ +"H42 HN1 " \ +"C2' CN7B " \ +"H2'' HN7 " \ +"O2' ON5 " \ +"H2' HN5 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"O3' ON2 " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6B " \ +"C1' CN7B " \ +"H1' HN7 " \ +"N1 NN2B " \ +"C6 CN3 " \ +"H6 HN3 " \ +"C2 CN1T " \ +"O2 ON1 " \ +"N3 NN2U " \ +"H3 HN2 " \ +"C4 CN1 " \ +"O4 ON1 " \ +"C5 CN3T " \ +"C5M CN9 " \ +"H51 HN9 " \ +"H52 HN9 " \ +"H53 HN9 " \ +"C2' CN7B " \ +"H2'' HN7 " \ +"O2' ON5 " \ +"H2' HN5 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"O3' ON2 " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6B " \ +"C1' CN7B " \ +"H1' HN7 " \ +"N1 NN2B " \ +"C6 CN3 " \ +"H6 HN3 " \ +"C2 CN1T " \ +"O2 ON1 " \ +"N3 NN2U " \ +"H3 HN2 " \ +"C4 CN1 " \ +"O4 ON1 " \ +"C5 CN3 " \ +"H5 HN3 " \ +"C2' CN7B " \ +"H2'' HN7 " \ +"O2' ON5 " \ +"H2' HN5 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"O3' ON2 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6 " \ +"C1' CN7B " \ +"H1' HN7 " \ +"C2' CN8 " \ +"H2' HN8 " \ +"H2'' HN8 " \ +"C4' CN7 " \ +"H4' HN7 " \ +"O4' ON6 " \ +"C1' CN7B " \ +"H1' HN7 " \ +"C2' CN8 " \ +"H2' HN8 " \ +"H2'' HN8 " \ +"H5T HN5 " \ +"O5' ON5 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"C5' CN9 " \ +"H5' HN9 " \ +"H5'' HN9 " \ +"H53' HN9 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"O5T ON4 " \ +"H5T HN4 " \ +"C5' CN8B " \ +"H5' HN8 " \ +"H5'' HN8 " \ +"P P " \ +"O1P ON3 " \ +"O2P ON3 " \ +"O5' ON2 " \ +"O5T ON2 " \ +"C5T CN9 " \ +"H5T1 HN9 " \ +"H5T2 HN9 " \ +"H5T3 HN9 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"O3' ON5 " \ +"H3T HN5 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"P3 P " \ +"O1P3 ON3 " \ +"O2P3 ON3 " \ +"O3' ON2 " \ +"O3T ON4 " \ +"H3T HN4 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"P3 P " \ +"O1P3 ON3 " \ +"O2P3 ON3 " \ +"O3' ON2 " \ +"O3T ON2 " \ +"C3T CN9 " \ +"H3T1 HN9 " \ +"H3T2 HN9 " \ +"H3T3 HN9 " \ +"C3' CN7 " \ +"H3' HN7 " \ +"P3 P " \ +"O3' ON2 " \ +"O1P3 ON3 " \ +"O2P3 ON3 " \ +"O3P3 ON3 " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB1 " \ +"CB CT1 " \ +"HB HA1 " \ +"CG2 CT3 " \ +"HG21 HA3 " \ +"HG22 HA3 " \ +"HG23 HA3 " \ +"CG1 CT2 " \ +"HG11 HA2 " \ +"HG12 HA2 " \ +"CD CT3 " \ +"HD1 HA3 " \ +"HD2 HA3 " \ +"HD3 HA3 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB1 " \ +"CB CT3 " \ +"HB1 HA3 " \ +"HB2 HA3 " \ +"HB3 HA3 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB1 " \ +"CB CT2 " \ +"HB1 HA2 " \ +"HB2 HA2 " \ +"CG CT1 " \ +"HG HA1 " \ +"CD1 CT3 " \ +"HD11 HA3 " \ +"HD12 HA3 " \ +"HD13 HA3 " \ +"CD2 CT3 " \ +"HD21 HA3 " \ +"HD22 HA3 " \ +"HD23 HA3 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB1 " \ +"CB CT2 " \ +"HB1 HA2 " \ +"HB2 HA2 " \ +"OG OH1 " \ +"HG1 H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB1 " \ +"CB CT2 " \ +"HB1 HA2 " \ +"HB2 HA2 " \ +"CG CT2 " \ +"HG1 HA2 " \ +"HG2 HA2 " \ +"CD CT2 " \ +"HD1 HA2 " \ +"HD2 HA2 " \ +"CE CT2 " \ +"HE1 HA2 " \ +"HE2 HA2 " \ +"NZ NH3 " \ +"HZ1 HC " \ +"HZ2 HC " \ +"HZ3 HC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB1 " \ +"CB CT2 " \ +"HB1 HA2 " \ +"HB2 HA2 " \ +"SG S " \ +"HG1 HS " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB1 " \ +"CB CT2 " \ +"HB1 HA2 " \ +"HB2 HA2 " \ +"CG CT2 " \ +"HG1 HA2 " \ +"HG2 HA2 " \ +"CD CC " \ +"OE1 O " \ +"NE2 NH2 " \ +"HE21 H " \ +"HE22 H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB1 " \ +"CB CT2 " \ +"HB1 HA2 " \ +"HB2 HA2 " \ +"CG CC " \ +"OD1 O " \ +"ND2 NH2 " \ +"HD21 H " \ +"HD22 H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB1 " \ +"CB CT2 " \ +"HB1 HA2 " \ +"HB2 HA2 " \ +"CG CT2 " \ +"HG1 HA2 " \ +"HG2 HA2 " \ +"CD CC " \ +"OE1 OC " \ +"OE2 OC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB1 " \ +"CB CT2 " \ +"HB1 HA2 " \ +"HB2 HA2 " \ +"CG CC " \ +"OD1 OC " \ +"OD2 OC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB1 " \ +"CB CT1 " \ +"HB HA1 " \ +"OG1 OH1 " \ +"HG1 H " \ +"CG2 CT3 " \ +"HG21 HA3 " \ +"HG22 HA3 " \ +"HG23 HA3 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB1 " \ +"CB CT2 " \ +"HB1 HA2 " \ +"HB2 HA2 " \ +"CG CY " \ +"CD1 CA " \ +"HD1 HP " \ +"NE1 NY " \ +"HE1 H " \ +"CE2 CPT " \ +"CD2 CPT " \ +"CE3 CA " \ +"HE3 HP " \ +"CZ3 CA " \ +"HZ3 HP " \ +"CZ2 CA " \ +"HZ2 HP " \ +"CH2 CA " \ +"HH2 HP " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB1 " \ +"CB CT2 " \ +"HB1 HA2 " \ +"HB2 HA2 " \ +"CG CT2 " \ +"HG1 HA2 " \ +"HG2 HA2 " \ +"SD S " \ +"CE CT3 " \ +"HE1 HA3 " \ +"HE2 HA3 " \ +"HE3 HA3 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB1 " \ +"CB CT2 " \ +"HB1 HA2 " \ +"HB2 HA2 " \ +"CG CA " \ +"CD1 CA " \ +"HD1 HP " \ +"CE1 CA " \ +"HE1 HP " \ +"CZ CA " \ +"HZ HP " \ +"CD2 CA " \ +"HD2 HP " \ +"CE2 CA " \ +"HE2 HP " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB1 " \ +"CB CT2 " \ +"HB1 HA2 " \ +"HB2 HA2 " \ +"CG CA " \ +"CD1 CA " \ +"HD1 HP " \ +"CE1 CA " \ +"HE1 HP " \ +"CZ CA " \ +"OH OH1 " \ +"HH H " \ +"CD2 CA " \ +"HD2 HP " \ +"CE2 CA " \ +"HE2 HP " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB1 " \ +"CB CT2 " \ +"HB1 HA2 " \ +"HB2 HA2 " \ +"ND1 NR1 " \ +"HD1 H " \ +"CG CPH1 " \ +"CE1 CPH2 " \ +"HE1 HR1 " \ +"NE2 NR2 " \ +"CD2 CPH1 " \ +"HD2 HR3 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB1 " \ +"CB CT1 " \ +"HB HA1 " \ +"CG1 CT3 " \ +"HG11 HA3 " \ +"HG12 HA3 " \ +"HG13 HA3 " \ +"CG2 CT3 " \ +"HG21 HA3 " \ +"HG22 HA3 " \ +"HG23 HA3 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB1 " \ +"CB CT2 " \ +"HB1 HA2 " \ +"HB2 HA2 " \ +"CD2 CPH1 " \ +"HD2 HR1 " \ +"CG CPH1 " \ +"NE2 NR3 " \ +"HE2 H " \ +"ND1 NR3 " \ +"HD1 H " \ +"CE1 CPH2 " \ +"HE1 HR2 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB1 " \ +"CB CT2 " \ +"HB1 HA2 " \ +"HB2 HA2 " \ +"ND1 NR2 " \ +"CG CPH1 " \ +"CE1 CPH2 " \ +"HE1 HR1 " \ +"NE2 NR1 " \ +"HE2 H " \ +"CD2 CPH1 " \ +"HD2 HR3 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA1 HB2 " \ +"HA2 HB2 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"HN H " \ +"CA CT1 " \ +"HA HB1 " \ +"CB CT2 " \ +"HB1 HA2 " \ +"HB2 HA2 " \ +"CG CT2 " \ +"HG1 HA2 " \ +"HG2 HA2 " \ +"CD CT2 " \ +"HD1 HA2 " \ +"HD2 HA2 " \ +"NE NC2 " \ +"HE HC " \ +"CZ C " \ +"NH1 NC2 " \ +"HH11 HC " \ +"HH12 HC " \ +"NH2 NC2 " \ +"HH21 HC " \ +"HH22 HC " \ +"C C " \ +"O O " \ +"N N " \ +"CD CP3 " \ +"HD1 HA2 " \ +"HD2 HA2 " \ +"CA CP1 " \ +"HA HB1 " \ +"CB CP2 " \ +"HB1 HA2 " \ +"HB2 HA2 " \ +"CG CP2 " \ +"HG1 HA2 " \ +"HG2 HA2 " \ +"C C " \ +"O O " \ +"N NH3 " \ +"HT1 HC " \ +"HT2 HC " \ +"HT3 HC " \ +"CA CT1 " \ +"HA HB1 " \ +"C CC " \ +"OT1 OC " \ +"OT2 OC " \ +"CAY CT3 " \ +"HY1 HA3 " \ +"HY2 HA3 " \ +"HY3 HA3 " \ +"CY C " \ +"OY O " \ +"C C " \ +"O O " \ +"NT NH1 " \ +"HNT H " \ +"CAT CT3 " \ +"HT1 HA3 " \ +"HT2 HA3 " \ +"HT3 HA3 " \ +"1CB CT2 " \ +"1SG SM " \ +"2SG SM " \ +"2CB CT2 " \ +"OH2 OT " \ +"OM LP " \ +"H1 HT " \ +"H2 HT " \ +"OH2 OT " \ +"H1 HT " \ +"H2 HT " \ +"h11 ha3 " \ +"h12 ha3 " \ +"h13 ha3 " \ +"c1 ct3 " \ +"h21 ha3 " \ +"h22 ha3 " \ +"h23 ha3 " \ +"c2 ct3 " \ +"h11 ha3 " \ +"h12 ha3 " \ +"h13 ha3 " \ +"c1 ct3 " \ +"c2 ct2 " \ +"h21 ha2 " \ +"H22 ha2 " \ +"h31 ha3 " \ +"h32 ha3 " \ +"h33 ha3 " \ +"c3 ct3 " \ +"h11 ha3 " \ +"h12 ha3 " \ +"h13 ha3 " \ +"c1 ct3 " \ +"h21 ha2 " \ +"h22 ha2 " \ +"c2 ct2 " \ +"h31 ha2 " \ +"h32 ha2 " \ +"c3 ct2 " \ +"h41 ha3 " \ +"h42 ha3 " \ +"h43 ha3 " \ +"c4 ct3 " \ +"CB CT3 " \ +"OG OH1 " \ +"HG1 H " \ +"HB1 HA3 " \ +"HB2 HA3 " \ +"HB3 HA3 " \ +"CL CT3 " \ +"HL1 HA3 " \ +"HL2 HA3 " \ +"HL3 HA3 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CR CT3 " \ +"HR1 HA3 " \ +"HR2 HA3 " \ +"HR3 HA3 " \ +"C1 CT3 " \ +"C CD " \ +"OM OS " \ +"C2 CT3 " \ +"O OB " \ +"H11 HA3 " \ +"H12 HA3 " \ +"H13 HA3 " \ +"H21 HA3 " \ +"H22 HA3 " \ +"H23 HA3 " \ +"HA HA1 " \ +"C CC " \ +"N NH2 " \ +"Hc H " \ +"Ht H " \ +"O O " \ +"C2 CT3 " \ +"C1 CD " \ +"H21 HA3 " \ +"H22 HA3 " \ +"H23 HA3 " \ +"O2 OB " \ +"O1 OH1 " \ +"HO1 H " \ +"HL HA1 " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CR CT3 " \ +"HR1 HA3 " \ +"HR2 HA3 " \ +"HR3 HA3 " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CH3E " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CH2E " \ +"CG CH2E " \ +"CD CH2E " \ +"NE NH1 " \ +"HE H " \ +"CZ C " \ +"NH1 NC2 " \ +"HH11 HC " \ +"HH12 HC " \ +"NH2 NC2 " \ +"HH21 HC " \ +"HH22 HC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CH2E " \ +"CG C " \ +"OD1 O " \ +"ND2 NH2 " \ +"HD21 H " \ +"HD22 H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CH2E " \ +"CG C " \ +"OD1 OC " \ +"OD2 OC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CH2E " \ +"SG SH1E " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CH2E " \ +"CG CH2E " \ +"CD C " \ +"OE1 O " \ +"NE2 NH2 " \ +"HE21 H " \ +"HE22 H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CH2E " \ +"CG CH2E " \ +"CD C " \ +"OE1 OC " \ +"OE2 OC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH2E " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CH2E " \ +"CG C " \ +"ND1 NH1 " \ +"HD1 H " \ +"CD2 CR1E " \ +"NE2 NR " \ +"CE1 CR1E " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CH2E " \ +"CG C " \ +"ND1 NR " \ +"CE1 CR1E " \ +"CD2 CR1E " \ +"NE2 NH1 " \ +"HE2 H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CH2E " \ +"CG C " \ +"CD2 CR1E " \ +"ND1 NH1 " \ +"HD1 H " \ +"CE1 CR1E " \ +"NE2 NH1 " \ +"HE2 H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CH1E " \ +"CG2 CH3E " \ +"CG1 CH2E " \ +"CD CH3E " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CH2E " \ +"CG CH1E " \ +"CD1 CH3E " \ +"CD2 CH3E " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CH2E " \ +"CG CH2E " \ +"CD CH2E " \ +"CE CH2E " \ +"NZ NH3 " \ +"HZ1 HC " \ +"HZ2 HC " \ +"HZ3 HC " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CH2E " \ +"CG CH2E " \ +"SD S " \ +"CE CH3E " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CT " \ +"CG1 CH3E " \ +"CG2 CH3E " \ +"SG SH1E " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CH2E " \ +"CG C " \ +"CD1 CR1E " \ +"CD2 CR1E " \ +"CE1 CR1E " \ +"CE2 CR1E " \ +"CZ CR1E " \ +"C C " \ +"O O " \ +"N N " \ +"CD CH2E " \ +"CA CH1E " \ +"CB CH2E " \ +"CG CH2E " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CH2E " \ +"OG OH1 " \ +"HG H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CH1E " \ +"OG1 OH1 " \ +"HG1 H " \ +"CG2 CH3E " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CH2E " \ +"CG C " \ +"CD2 C " \ +"CE2 C " \ +"CE3 CR1E " \ +"CD1 CR1E " \ +"NE1 NH1 " \ +"HE1 H " \ +"CZ2 CR1E " \ +"CZ3 CR1E " \ +"CH2 CR1E " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CH2E " \ +"CG C " \ +"CD1 CR1E " \ +"CE1 CR1E " \ +"CD2 CR1E " \ +"CE2 CR1E " \ +"CZ C " \ +"OH OH1 " \ +"HH H " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH1E " \ +"CB CH1E " \ +"CG1 CH3E " \ +"CG2 CH3E " \ +"C C " \ +"O O " \ +"FE FE " \ +"NA NP " \ +"NB NP " \ +"NC NP " \ +"ND NP " \ +"C1A C " \ +"CHA CR1E " \ +"C4D C " \ +"C1B C " \ +"CHB CR1E " \ +"C4A C " \ +"C1C C " \ +"CHC CR1E " \ +"C4B C " \ +"C1D C " \ +"CHD CR1E " \ +"C4C C " \ +"C2A C " \ +"CAA CH2E " \ +"C3A C " \ +"CMA CH3E " \ +"CBA CH2E " \ +"CGA C " \ +"O1A OC " \ +"O2A OC " \ +"C2B C " \ +"CMB CH3E " \ +"C3B C " \ +"CAB CR1E " \ +"CBB CH2E " \ +"C2C C " \ +"CMC CH3E " \ +"C3C C " \ +"CAC CR1E " \ +"CBC CH2E " \ +"C2D C " \ +"CMD CH3E " \ +"C3D C " \ +"CAD CH2E " \ +"CBD CH2E " \ +"CGD C " \ +"O1D OC " \ +"O2D OC " \ +"CH3 CH3E " \ +"C C " \ +"O O " \ +"HA HA " \ +"C C " \ +"O O " \ +"N NH2 " \ +"H1 H " \ +"H2 H " \ +"CL CH3E " \ +"C C " \ +"O O " \ +"N NH1 " \ +"H H " \ +"CA CH3E " \ +"HT1 HC " \ +"HT2 HC " \ +"N NH3 " \ +"HT3 HC " \ +"CA CH1E " \ +"HT1 HC " \ +"HT2 HC " \ +"N NH3 " \ +"HT3 HC " \ +"CA CH2E " \ +"HT1 HC " \ +"HT2 HC " \ +"N NH3 " \ +"CD CH2E " \ +"CA CH1E " \ +"C C " \ +"OT1 OC " \ +"OT2 OC " \ +"O1 OM " \ +"O2 OM " \ +"C CM " \ +"O OM " \ +"C CM " \ +"O OM " \ +"C2 CH3E " \ +"C1 CH2E " \ +"O OH1 " \ +"H H " \ +"OX2 OH2 " \ +"HX1 H " \ +"HX2 H " \ +"LX1 LP " \ +"LX2 LP " \ +"OH2 OT " \ +"H1 HT " \ +"H2 HT " \ +"OH2 OT " \ +"H1 HT " \ +"H2 HT " \ +"S S " \ +"O1 OC " \ +"O2 OC " \ +"O3 OC " \ +"O4 OC " \ +"C CH3E " \ +"O OH1 " \ +"H H " \ +"1CB CH2E " \ +"1SG S " \ +"2SG S " \ +"2CB CH2E " \ +"CG C " \ +"ND1 NR " \ +"CE1 CR1E " \ +"CD2 CR1E " \ +"NE2 NH1 " \ +"HE2 H " \ +"P P " \ +"O1P O2 " \ +"O2P O2 " \ +"O5' OS " \ +"C5' C2 " \ +"C4' CH " \ +"O4' OSS " \ +"C1' CH " \ +"N9 NS " \ +"C4 CB " \ +"N3 NC " \ +"C2 CA " \ +"N2 N2 " \ +"H21 H2 " \ +"H22 H2 " \ +"N1 NA " \ +"H1 H " \ +"C6 C " \ +"O6 O " \ +"C5 CB " \ +"N7 NB " \ +"C8 CE " \ +"C2' CH " \ +"O2' OH " \ +"H2' HO " \ +"C3' CH " \ +"O3' OS " \ +"P P " \ +"O1P O2 " \ +"O2P O2 " \ +"O5' OS " \ +"C5' C2 " \ +"C4' CH " \ +"O4' OSS " \ +"C1' CH " \ +"N9 NS " \ +"C4 CB " \ +"N3 NC " \ +"C2 CE " \ +"N1 NC " \ +"C6 CA " \ +"N6 N2 " \ +"H61 H2 " \ +"H62 H2 " \ +"C5 CB " \ +"N7 NB " \ +"C8 CE " \ +"C2' CH " \ +"O2' OH " \ +"H2' HO " \ +"C3' CH " \ +"O3' OS " \ +"P P " \ +"O1P O2 " \ +"O2P O2 " \ +"O5' OS " \ +"C5' C2 " \ +"C4' CH " \ +"O4' OSS " \ +"C1' CH " \ +"N1 NS " \ +"C6 CF " \ +"C2 C " \ +"O2 O " \ +"N3 NC " \ +"C4 CA " \ +"N4 N2 " \ +"H41 H2 " \ +"H42 H2 " \ +"C5 CF " \ +"C2' CH " \ +"O2' OH " \ +"H2' HO " \ +"C3' CH " \ +"O3' OS " \ +"P P " \ +"O1P O2 " \ +"O2P O2 " \ +"O5' OS " \ +"C5' C2 " \ +"C4' CH " \ +"O4' OSS " \ +"C1' CH " \ +"N1 NS " \ +"C6 CF " \ +"C2 C " \ +"O2 O " \ +"N3 NA " \ +"H3 H " \ +"C4 C " \ +"O4 O " \ +"C5 CS " \ +"C5A C3 " \ +"C2' CH " \ +"O2' OH " \ +"H2' HO " \ +"C3' CH " \ +"O3' OS " \ +"P P " \ +"O1P O2 " \ +"O2P O2 " \ +"O5' OS " \ +"C5' C2 " \ +"C4' CH " \ +"O4' OSS " \ +"C1' CH " \ +"N1 NS " \ +"C6 CF " \ +"C2 C " \ +"O2 O " \ +"N3 NA " \ +"H3 H " \ +"C4 C " \ +"O4 O " \ +"C5 CF " \ +"C2' CH " \ +"O2' OH " \ +"H2' HO " \ +"C3' CH " \ +"O3' OS " \ +"O4' OST " \ +"C2' C2 " \ +"C1 C3 " \ +"O1 OS " \ +"P P " \ +"O1P O2 " \ +"O2P O2 " \ +"O2 OS " \ +"C2 C3 " \ +"C1 C3 " \ +"C2 C2 " \ +"O1 OS " \ +"P P " \ +"O1P O2 " \ +"O2P O2 " \ +"O2 OS " \ +"C3 C2 " \ +"C4 C3 " \ +"C5' C3 " \ +"C4' CH " \ +"O4' OSS " \ +"C1' CH " \ +"N1 NH2E " \ +"C2' CH " \ +"O2' OH " \ +"C3' CH " \ +"O3' OS " \ +"C5' C3 " \ +"C4' CH " \ +"O4' OST " \ +"C1' CH " \ +"N1 NH2E " \ +"C2' C2 " \ +"C3' CH " \ +"O3' OS " \ +"C1 C3 " \ +"C2 C2 " \ +"C3 C2 " \ +"C4 C2 " \ +"C5 C2 " \ +"C6 C2 " \ +"C7 C2 " \ +"C8 C3 " \ +"N1 NA " \ +"C6 CF " \ +"H1 H " \ +"N9 NA " \ +"C4 CB " \ +"H9 H " \ +"H5T HO " \ +"O5' OH " \ +"C5' C2 " \ +"H5T HO " \ +"O5T OH " \ +"C3' CH " \ +"O3' OH " \ +"H3T HO " \ +"1O3' OS " \ +"2P P " \ +"2O1P O2 " \ +"2O2P O2 " \ +"2O5' OS " \ +"OH2 OH2 " \ +"H1 H " \ +"H2 H " \ +"NA SD " \ +"NA SD " \ +"N1 NH3 " \ +"C2 C2 " \ +"C3 C2 " \ +"C4 C2 " \ +"N5 NH3 " \ +"C6 C2 " \ +"C7 C2 " \ +"C8 C2 " \ +"C9 C2 " \ +"NA NH3 " \ +"CB C2 " \ +"CC C2 " \ +"CD C2 " \ +"NE NH3 " \ +"H11 H " \ +"H12 H " \ +"H13 H " \ +"H51 H " \ +"H52 H " \ +"HA1 H " \ +"HA2 H " \ +"HE1 H " \ +"HE2 H " \ +"HE3 H " \ +"MG MG 2. " \ +"ST2 . " \ +"OX2 OH2 " \ +"HX1 H " \ +"HX2 H " \ +"LX1 LP " \ +"LX2 LP " \ +"OH2 OT " \ +"H1 HT " \ +"H2 HT " \ +"C5 C2 " \ +"C6 C2 " \ +"C5 CB " \ +"C7 C3 " \ +"N7 NB " \ +"C8 CE " \ +"N2 N2 " \ +"C2B C3 " \ +"C2A C3 " \ +"N2 N2 " \ +"H21 H2 " \ +"C2A C3 " \ +"C2' CH " \ +"O2' OH " \ +"C2A C3 " \ +"C5 CS " \ +"C6 CF " \ +"N1 NA " \ +"H11 H " \ +"C5 CS " \ +"C5A C3 " \ +"N1 NA " \ +"C1 C3 " \ +"C6 CH " \ +"C3 C3 " \ +"N3 NA " \ +"C2 CB " \ +"N2 NB " \ +"C11 CA " \ +"C10 C3 " \ +"C12 CA " \ +"N1 NA " \ +"C13 C2 " \ +"C14 C2 " \ +"C15 CH " \ +"C16 C " \ +"O18 OS " \ +"C19 C3 " \ +"O17 O " \ +"N20 NA " \ +"H20 H " \ +"C21 C " \ +"O23 O " \ +"O22 OS " \ +"C24 C3 " \ +"C2 CA " \ +"C6 CE " \ +"N2 N2 " \ +"H21 H2 " \ +"H22 H2 " +} { + set data [ split $data " " ] + set i 0 + foreach value $data { + if { $value > " " } { incr i; set val($i) $value } + if { $i == 2 } { + set class $val(2) + if { [ info exists mass($class) ] } { + set mass($val(1)) $mass($class) + } + } + } +} + + + + +set natoms 0 +set molmass 0. +foreach line $pdb_file { + if { [ string range $line 0 3 ] == "ATOM" | + [ string range $line 0 5 ] == "HETATM" } { + incr natoms + set at [ string trim [ string range $line 12 15 ] ] + if { [ info exists mass($at) ] == 0 } { + if { [ info exists mass([ string range $at 0 0 ]) ] } { + set mass($at) $mass([ string range $at 0 0 ]) + puts -nonewline " Unsure about mass of element $at: $mass($at)." + puts -nonewline " Is this correct? (y/n)" + flush stdout; gets stdin correct + if { $correct != "y" & $correct != "yes" & $correct != "Y" & $correct != "YES" } { + puts -nonewline "Type the mass of this atom:" + flush stdout; gets stdin mass($at) + } + } else { + puts "Could not find mass for atom type: $at" + puts -nonewline "Type the mass of this atom:" + flush stdout; gets stdin mass($at) + } + } + set atommass $mass($at) + set molmass [ expr $molmass + $atommass ] + } +} + +puts " -------------------------------------------------------" +puts " Molar mass of structure: $molmass" +puts " -------------------------------------------------------" + +# Total volume of the box + +if { $density == "none" } { set density 1. } +set volume [ expr $x_length * $y_length * $z_length ] + +# We use the approximation that the volume occupied by each type of molecule +# in the system is proportional to its molar mass, therefore: + +set water_molar_mass 18. +set n_water [ format %7.0f "[ expr ( $volume*($density*0.602) - $molmass ) / $water_molar_mass ]" ] +puts " Number of water molecules to be put: $n_water " + +# Fraction of the volume occupied by water + +set water_vol [ expr $n_water*$water_molar_mass/($n_water*$water_molar_mass + $molmass) ] +set water_vol [ expr $water_vol * $volume ] + +# Computing the required number of ions for an approximate concentration +# of 0.16 mol/L (approximate physiological concentration on water) + +puts " Total volume: [ format %8.2f $volume ] A^3" +puts " Volume occupied by water: [ format %8.2f "$water_vol" ] A^3 " + +# Set the number of ions of each type + +if { $noions == "true" } { + set n_chloride 0 + set n_sodium 0 +} else { + if { $charge <= 0 } { + set n_sodium [ format %8.0f [ expr 0.16 * 0.000602 * $water_vol ] ] + if { $n_sodium > [ expr -1.*$charge ] } { + set n_chloride [ expr $n_sodium + $charge ] + } else { + set n_sodium [ expr -1.*$charge ] + set n_chloride 0 + } + } + if { $charge > 0 } { + set n_chloride [ format %8.0f [ expr 0.16 * 0.000602 * $water_vol ] ] + if { $n_chloride > $charge } { + set n_sodium [ expr $n_chloride - $charge ] + } else { + set n_chloride $charge + set n_sodium 0 + } + } +} + +puts " Number of Sodium ions to be put: [ string trim $n_sodium ]" +puts " Number of Chloride ions to be put: [ string trim $n_chloride ]" + +# Minimum and maximum coordinates of the box + +set xmin [ expr -1.*$x_length / 2. ] +set xmax [ expr $x_length / 2. ] +set ymin [ expr -1.*$y_length / 2. ] +set ymax [ expr $y_length / 2. ] +set zmin [ expr -1.*$z_length / 2. ] +set zmax [ expr $z_length / 2. ] + +# +# Write packmol input file +# + +set packmol_input_file [ open ./$packmol_input w ] + +puts $packmol_input_file " +tolerance 2.0 +filetype pdb +output $output + +structure $pdb_file_name + number 1 + center + fixed 0. 0. 0. 0. 0. 0. +end structure + +structure WATER.pdb + number $n_water + inside box $xmin $ymin $zmin $xmax $ymax $zmax +end structure +" + +if { $n_sodium > 0 } { + puts $packmol_input_file " +structure SODIUM.pdb + number $n_sodium + inside box $xmin $ymin $zmin $xmax $ymax $zmax +end structure + " +} + +if { $n_chloride > 0 } { + puts $packmol_input_file " +structure CHLORIDE.pdb + number $n_chloride + inside box $xmin $ymin $zmin $xmax $ymax $zmax +end structure + " +} +close $packmol_input_file + +puts " Wrote packmol input. " + +# +# This are the temporary pdb file that will be temporaritly created +# + +set water_file [ open ./WATER.pdb w ] +puts $water_file \ +"HETATM 1 H1 TIP3 1 9.626 6.787 12.673 H" +puts $water_file \ +"HETATM 2 H2 TIP3 1 9.626 8.420 12.673 H" +puts $water_file \ +"HETATM 3 OH2 TIP3 1 10.203 7.604 12.673 O" +close $water_file + + +set sod_file [ open ./SODIUM.pdb w ] +puts $sod_file \ +"HETATM 1 SOD SOD 2 0.000 0.000 0.000 Na" +close $sod_file + +set cl_file [ open ./CHLORIDE.pdb w ] +puts $cl_file \ +"HETATM 1 CLA CLA 2 0.000 0.000 0.000 Cl" +close $cl_file + +# Run packmol + +puts " -------------------------------------------------------" +puts " Use these lengths for periodic boundary conditions: " +puts " x: [ expr $x_length + 1. ]" +puts " y: [ expr $y_length + 1. ]" +puts " z: [ expr $z_length + 1. ]" +puts " -------------------------------------------------------" +puts " -------------------------------------------------------" +puts " Now, run packmol with: packmol < $packmol_input " +puts " -------------------------------------------------------" +puts " The solvated file will be: $output " +puts " -------------------------------------------------------" + + diff --git a/tests/packmol/strlength.f90 b/tests/packmol/strlength.f90 new file mode 100644 index 00000000..12bc6593 --- /dev/null +++ b/tests/packmol/strlength.f90 @@ -0,0 +1,96 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Function that determines the length of a string (better than +! intrinsic "len" because considers tabs as empty characters) +! +function strlength(string) + + use sizes + implicit none + integer :: strlength + character(len=strl) :: string + logical empty_char + + strlength = strl + do while(empty_char(string(strlength:strlength))) + strlength = strlength - 1 + if ( strlength == 0 ) exit + end do + +end function strlength + +! +! Function that determines if a character is empty (empty, space, or tab) +! (nice suggestion from Ian Harvey -IanH0073- at github) +! + +function empty_char(ch) + character :: ch + logical empty_char + empty_char = .false. + if ( ch == '' .or. & + ch == achar(9) .or. & + ch == achar(32) ) then + empty_char = .true. + end if +end function empty_char + +! +! Function that replaces all non-space empty characters by spaces +! + +function alltospace(record) + + use sizes + implicit none + integer :: i + logical :: empty_char + character(len=strl) :: alltospace, record + + do i = 1, strl + if ( empty_char(record(i:i)) ) then + alltospace(i:i) = " " + else + alltospace(i:i) = record(i:i) + end if + end do + +end function alltospace + +subroutine parse_spaces(record) + use input, only : forbidden_char + use sizes + implicit none + integer :: i, strlength + character(len=strl) :: record + ! Replace spaces within quotes by ~ + i = 0 + do while(i < strlength(record)) + i = i + 1 + if ( record(i:i) == '"' ) then + i = i + 1 + do while(record(i:i) /= '"') + i = i + 1 + if( i > strlength(record) ) then + write(*,*) ' ERROR: Could not find ending quotes in line: ', trim(record) + stop + end if + if(record(i:i) == " ") then + record(i:i) = forbidden_char + end if + end do + end if + end do + ! Replace spaces after \ by the forbidden_char and remove the \ + i = 0 + do while(i < strlength(record)-1) + i = i + 1 + if (record(i:i) == "\" .and. record(i+1:i+1) == " ") then + record(i:i) = forbidden_char + record = record(1:i)//record(i+2:strlength(record)) + end if + end do +end \ No newline at end of file diff --git a/tests/packmol/swaptype.f90 b/tests/packmol/swaptype.f90 new file mode 100644 index 00000000..8d11f704 --- /dev/null +++ b/tests/packmol/swaptype.f90 @@ -0,0 +1,89 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Subroutine that swaps indexes for packing molecules one at a time +! + +subroutine swaptype(n,x,itype,action) + + use sizes, only : nn + use compute_data, only : ntype, comptype, nmols, ntotmol + use input, only : nloop, nloop_all, nloop_type + use swaptypemod + use ahestetic + implicit none + integer ::n, itype, ilubar, ilugan, i, action + double precision :: x(nn) + + ! Save original data + + if ( action == 0 ) then + do i = 1, nn + xfull(i) = x(i) + end do + ntemp = n + ntottemp = ntotmol + end if + + ! Swapping data for packing this itype + + if ( action == 1 ) then + do i = 1, ntype + if(i == itype) then + comptype(i) = .true. + else + comptype(i) = .false. + end if + end do + n = nmols(itype) * 6 + ntotmol = nmols(itype) + nloop = nloop_type(itype) + ilubar = 0 + do i = 1, itype - 1 + ilubar = ilubar + nmols(i) * 3 + end do + ilubar = ilubar + 1 + ilugan = ntemp/2 + ilubar + do i = 1, n / 2 + x(i) = xfull(ilubar) + x(i+n/2) = xfull(ilugan) + ilubar = ilubar + 1 + ilugan = ilugan + 1 + end do + end if + + ! Save results for this type + + if ( action == 2 ) then + ilubar = 0 + do i = 1, itype - 1 + ilubar = ilubar + nmols(i)*3 + end do + ilubar = ilubar + 1 + ilugan = ntemp/2 + ilubar + do i = 1, n/2 + xfull(ilubar) = x(i) + xfull(ilugan) = x(i+n/2) + ilubar = ilubar + 1 + ilugan = ilugan + 1 + end do + end if + + ! Restore all-molecule vectors + + if ( action == 3 ) then + n = ntemp + ntotmol = ntottemp + nloop = nloop_all + do i = 1, n + x(i) = xfull(i) + end do + do i = 1, ntype + comptype(i) = .true. + end do + end if + +end subroutine swaptype + diff --git a/tests/packmol/swaptypemod.f90 b/tests/packmol/swaptypemod.f90 new file mode 100644 index 00000000..d8086592 --- /dev/null +++ b/tests/packmol/swaptypemod.f90 @@ -0,0 +1,16 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Module that contains the temporary data for swap molecules +! for individual packing +! + +module swaptypemod + + integer :: ntemp, ntottemp + double precision, allocatable :: xfull(:) ! (nn) + +end module swaptypemod + diff --git a/tests/packmol/title.f90 b/tests/packmol/title.f90 new file mode 100644 index 00000000..109b52c6 --- /dev/null +++ b/tests/packmol/title.f90 @@ -0,0 +1,19 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! + +! Routine to print the title + +subroutine title() + + use ahestetic + write(*,hash3_line) + write(*,"(' PACKMOL - Packing optimization for the automated generation of', /& + &' starting configurations for molecular dynamics simulations.', /& + &' ',/& + &t62,' Version 20.3.2 ')") + write(*,hash3_line) + +end subroutine title diff --git a/tests/packmol/tobar.f90 b/tests/packmol/tobar.f90 new file mode 100644 index 00000000..7ec66d50 --- /dev/null +++ b/tests/packmol/tobar.f90 @@ -0,0 +1,42 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! subroutine tobar: moves molecules to their baricentres +! + +subroutine tobar() + + use sizes + use compute_data, only : coor, ntype, natoms, idfirst + implicit none + integer :: idatom, itype, iatom + double precision :: xcm, ycm, zcm + + do itype = 1, ntype + idatom = idfirst(itype) - 1 + xcm = 0.d0 + ycm = 0.d0 + zcm = 0.d0 + do iatom = 1, natoms(itype) + idatom = idatom + 1 + xcm = xcm + coor(idatom,1) + ycm = ycm + coor(idatom,2) + zcm = zcm + coor(idatom,3) + end do + xcm = xcm / natoms(itype) + ycm = ycm / natoms(itype) + zcm = zcm / natoms(itype) + idatom = idfirst(itype) - 1 + do iatom = 1, natoms(itype) + idatom = idatom + 1 + coor(idatom,1) = coor(idatom,1) - xcm + coor(idatom,2) = coor(idatom,2) - ycm + coor(idatom,3) = coor(idatom,3) - zcm + end do + end do + + return +end subroutine tobar + diff --git a/tests/packmol/usegencan.f90 b/tests/packmol/usegencan.f90 new file mode 100644 index 00000000..b390d8db --- /dev/null +++ b/tests/packmol/usegencan.f90 @@ -0,0 +1,18 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Optimization variables passed as common go pgencan + +module usegencan + + use sizes + implicit none + + integer :: maxit, iprint1, iprint2 + integer, allocatable :: wi(:) ! (nn) + double precision, allocatable :: l(:), u(:), g(:) ! (nn) + double precision, allocatable :: wd(:) ! (8*nn) + +end module usegencan diff --git a/tests/packmol/writesuccess.f90 b/tests/packmol/writesuccess.f90 new file mode 100644 index 00000000..4854c7c0 --- /dev/null +++ b/tests/packmol/writesuccess.f90 @@ -0,0 +1,46 @@ +! +! Written by Leandro Martínez, 2009-2011. +! Copyright (c) 2009-2018, Leandro Martínez, Jose Mario Martinez, +! Ernesto G. Birgin. +! +! Subroutine writesuccess +! +! Writes the success messages for good packings +! + +subroutine writesuccess(itype,fdist,frest,f) + + use input, only : input_itype + use compute_data, only : ntype + use ahestetic + implicit none + integer :: itype + double precision :: fdist, frest, f + + if(itype.le.ntype) then + write(*,dash1_line) + write(*,*)' Packing solved for molecules of type', input_itype(itype) + write(*,*)' Objective function value: ', f + write(*,*)' Maximum violation of target distance: ',fdist + write(*,*)' Max. constraint violation: ', frest + write(*,dash1_line) + else + write(*,hash3_line) + write(*,"(& + &t33, ' Success! ', /,& + &t14, ' Final objective function value: ', e10.5, /,& + &t14, ' Maximum violation of target distance: ', f10.6, /,& + &t14, ' Maximum violation of the constraints: ', e10.5 & + &)") f, fdist, frest + write(*,dash3_line) + write(*,"(& + &t14,' Please cite this work if Packmol was useful: ',/,/,& + &t11,' L. Martinez, R. Andrade, E. G. Birgin, J. M. Martinez, ',/,& + &t9,' PACKMOL: A package for building initial configurations for',/,& + &t19,' molecular dynamics simulations. ',/,& + &t10,' Journal of Computational Chemistry, 30:2157-2164,2009.' )") + write(*,hash3_line) + end if + +end subroutine writesuccess + From ce2653206617fb00dd9a034b12e3da342ba35116 Mon Sep 17 00:00:00 2001 From: Tingzheng Hou Date: Wed, 10 Nov 2021 18:32:03 -0800 Subject: [PATCH 25/55] change actions working directory --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a7bd1419..779b6545 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -54,7 +54,7 @@ jobs: run: | make echo "$HOME/tests/packmol" >> $GITHUB_PATH - working-directory: dart_project + working-directory: tests/packmol - name: Prepare Selenium # https://github.com/marketplace/actions/setup-chromedriver uses: nanasess/setup-chromedriver@master From 687769347440ed50ce566a3a7637c0bd5e6edf31 Mon Sep 17 00:00:00 2001 From: Tingzheng Hou Date: Wed, 10 Nov 2021 18:42:37 -0800 Subject: [PATCH 26/55] fortran compile error --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 779b6545..3e756bed 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -52,6 +52,7 @@ jobs: pip install -e . - name: Prepare Packmol run: | + ./configure make echo "$HOME/tests/packmol" >> $GITHUB_PATH working-directory: tests/packmol From 76e45cf0d21bcc5ab3dd9fe4a7aaa9d97995fedc Mon Sep 17 00:00:00 2001 From: Tingzheng Hou Date: Wed, 10 Nov 2021 18:58:23 -0800 Subject: [PATCH 27/55] made executable --- tests/packmol/.gitignore | 2 +- tests/packmol/Makefile | 2 +- tests/packmol/packmol | Bin 0 -> 305504 bytes 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100755 tests/packmol/packmol diff --git a/tests/packmol/.gitignore b/tests/packmol/.gitignore index ac61ebf0..717dbc09 100644 --- a/tests/packmol/.gitignore +++ b/tests/packmol/.gitignore @@ -2,4 +2,4 @@ build/ *.mod *.o *.swp -packmol + diff --git a/tests/packmol/Makefile b/tests/packmol/Makefile index b3765df7..5f58e844 100644 --- a/tests/packmol/Makefile +++ b/tests/packmol/Makefile @@ -14,7 +14,7 @@ # If you want to compile with some specific fortran compiler, you must # change the line below to the path of your fortran compiler. # -FORTRAN=/usr/bin/gfortran +FORTRAN=/usr/local/bin/gfortran # # Change the flags of the compilation if you want: # diff --git a/tests/packmol/packmol b/tests/packmol/packmol new file mode 100755 index 0000000000000000000000000000000000000000..11b5b994e5bc3e2efa1bd16bcaa3c9fa85cacbad GIT binary patch literal 305504 zcmdq~eVmn5_5Y90$P7*iok2h`QKvfAm?EH9LrTu*q0Zz%$3z_x7;K2JP)TQ$3JIMV z)LzmwbovH?X}mwxgLDumACgVDk>gORJ3rvqN1V$`Ku@^DrzgL;I63X5dM<< zH8j-Ke0Jg&CVu`5K@0yC7e4m;Bs^Ud(9ke>V*TX8B$j_hNg>cbLt9ZPe~@JV8XB6u zG_T1&aOs2ZeJ}%j?;1GLKb{LPmlQ2Dxc_nZ8X7O2Gt(fw@$J2TfZ@Bwr`L1Azy9%E z+I0RUP0e%r(zo;hhwoI6M9=R`-=$5>U%WJ5WN-Q&_V{-B6ybB2q0G}a&;uG8gs)-t zm*&j<(j~xpyq;?{E~z8#<%SF606_(W88Z^ zN9hakgjebDJk#Su&E%R8$`yTedh7+qv;8Y~7wNI^>Z*SY4HwO6xb*86e(~Zt4Rf0= z;kkc&KD*(M(xv)5$}qW~hK4U++#@yNFT_{w=?n4cxi`L}3-HZ3|DEWo@c5FRT|Gzf ziO*35_%6J7X2S&+UC`7ptNEhFKJ?8#-^nj*=X#FfqZt?c>#HY){Lbx#PtQ?&1;}`4 zX!zo#J*}*-{1$qA3#&ZCiG+*DFj z{(&NE`+8r|Qc_d`qC2iFDY|7?QIVQ+ozEkk(%(J&J)t9C6&(s(bc}fAcQ2ms@~3|G+ZCUiapND>ZaxlJ1%Jll z2i{*)#Gmf1t_Q3t7A>MJ{8tJ8!XvvI{ikxpkKQ?(q!u>N({gd+`Ey2JJhy4|mm3?6 zGF``x)$NyOU3^K?CFfss>MCLk@T#uU)uDg3y(b| zno;?xBl#R>VLqcnl8Kbx*w}FCv13CVeff|y3i9{Q$Jd(ApLyZ=O|y?36QUwtQPD^F zll-o`s-$Q!SJ@mrOCSFK;a|8K<~6|(X=H!Y0G1+KP7EVcGBLK*Y}GpTFgTt{o<_H#ia*6 zG@z*S#r=|<&y*yKSH+HK6^f$RkfLNuM|pC5ck@3<*z(Mq*;9&Z#y`?DCYhNUFVD^` zPBwPejQ>|MJM4SwPkB@9%pcy;vETarbXzli?fm`MpQ45@!Mt{JX;EfO+pbvq_kbj` z!*BdWX;F>w$J?~GT9#~CTb#V$m4Nn^9PsgE@xPPlE!pYC z>5=hdcI1`G;ytPCxGQVZFDKJ;;v*92w`#HzizlUDs7HhSe*12{2oA*8YwKu!nCe>a;2olM*0CY~Cmz$XU}(*W$1J*Ha56JL zUcNqY^_wJ+P>NIIw>CdjP(brfk{PIQEG0zH#O#-fYtyelS4!DmIzD#9Ld%~W{9Rm` zJ7pzO>1~dX^lA~(bd2F#8xma)(O*znwat9mX_mJ6PnpT_5k_;{rUmO~Efu{nqxXF^ zqSYktX??Z;Z}Tk)qZL(v@mTvfWTHB)NbyrieIAOSKbJk}gNQhpo*%E1UXF=tLybsyS+235y?xURZ&N38WZ0B-Vt z^(Cv_i{bZvzqDv#`jxSJ(a0mdhel=xkGNHe`GvAn=KZP6h-9X^ER`MhV@sboN`+LO zksUWAl^zsNWzHv6DqfXJH__a)Bioc}Qud@nQ%EowJECY}CUJKOOuw!dwT+YSDw){U zkv(Paf;lxUdywAWQOHEPGgbV|tl0Jq$?W7uiZr%yAcgE@yYm0W) z#D-fFIf$tgZP=!1=Anc85{Befd{SfkoWO4rKD3$I5~bjuir|~L-?ta&d!i2m@P|Dk6Cv@No6lD7Ox{Hl$()pX;7uKW()>! zzuNTPRQ4De4!S3^B4L3`{YrYKn(WMYc{07aHoZ1^^wjv=m&zd(=5n#tX%vm#)npRa zyoqgjL7A$PjU|h-^Y*G%ASIc|j9W6XZP$W(^aPjlqU1so&bum=Sj z5&Pk)>ekJl%ML3CHuAw(t1Nm=%iE}Mn!AbVS9it^)ZdHzJzJYSsk>%lt~NWlv`Fp0 z^J&?G?uZ>guS@nvqZ9j=&5BK3H!C(&j|cOpHv{!%px&(28y*klQE&FsoBi}=jo$Eh zFpui8YR7jr|1vWyo=ER#+4^?zs>FEA)IZ+dySHUku}P+jDoU?dPB~nFZJ0MYBLKRl&FYU3v1#HH&HF=S{1bS~IO? zdQC&_VqVd#J94w%+`HGhykC0mS5 zp0*&%vgG(x&G+YSc}v`)#A&Z6>B;f>B!;3QnLV{QiOhCCk<6wZMH3&Fg3e23OV;C0 z48U}k?}1coxqfBRci7cXcQrqiYk6buUhBnjH}BrNcjDORlGzguxqATJ-7{l5lGzEP zxDT#cIiM)wZ?(K!mDxX;xgov~T&Z*_KBBFIQirX_grf89uko8qzg3(5XU$)cYf&nz z7L`SzUs^CLln=a4j?<>zNTr`ornigrxI=&yxCbG0?L0L$B=z#1;HN(rP?Q^FMsu844#VZ`fow4bbbMni3B-B)}2a8gi7(XXIZ2mN*o|{VV^ktq3 z4KMG>mx>*qTsrP~sfs8V0)3bmvKm z_qa0F-wF%t-s37FH|b`I$vZo;6Xzz=ugj&aP5;Y#we@tr$;`@lH&=-nYttHEs)x*q z_;q$&9$&__<>UdXjx7dS84tK7NxFk;Y{~uf>Y1_0%!E6;aB_CZqZkuwznF2LaNnZr zZx`33cOt&gvDO*D)4RuR!g&0H7PHIw5YYEpO>Ds+y1vT4>2C7yqFFVugHq)ffGLmZ zcJgp;D-q$;)k-k(AOWWy1hByYh8bWOfN86_9a?fQzXvA{1~8RuLrXw@aKaGML#)E{ zeS^+)NAseV=jmB1pHJ_ke|;X%^V!R&&rMCIv~0r%-X-HOY=?fQ{);M_f=^vZ7c_M( zpoS8?o>uZteutFo4x82vlF=vCZ-0h>Rm>ReWf=2B)!J0WbC3x zL%$ULkP0W_Rs2>8-yTTdUP^c$f2d^r{j*}DyJ9W3SP8B14pIOqiY;nnT%$Y+)n;)2 z2gb68;j{^)AvH|^Ok+s9Gj{b@!z+tk`7(dto${i?kI*POffs4N>R2$S>{WNdDv(fZCGsIfX7`)>7EpMP$8=LCWkB;4?9?2;aCIJ6a zeaP|Bl++1iJ}7ZKdN5_JbR=~GxAmQ-BcC)K`6T_yIuv4e^M>?h)FFEgBcWHDMz*|& z0-&npB@c-jD!D%Ki1V}_O{!0iR4tUNN{u+W&Pc7E^4*?Vt!Wt;tyVEQIbIH}hmCwj zLj-J)7ql8>OBI#-Z;VnRbI8QDCt~f#0+fs@kkO>Zd&h1XyZ0_xK*?V4N+-KY+7rZ< zi&)&Fhp;iIF&B^PF5L)~;MrPZ1G2mew2SQMH*6_r=Jr0QY3z{7G7JHY@+H+J#rs5cV_r?Bur-KNRZADrLv`)RAD+h2ji|rWG*qeo^TpslGNy_B_)cY!9kLZTd-LM9&A= z^Y&oN3JGBN`ydNSl8zFHD2IrGq9wzeO6?=VC7_5FeSgoh75!H|tL`XYMgK@ea-F6t z`mR1K$-oXHSRRk({)oE*MHfHGTPG++OxeSJql!sy7a6M|0}>zU6p2%NNhg%b7o=qW zyj?}CurAO@RJo&k`G2>U!#_Yl;Gg91gZGNwcva?_-mDw`Yx~20zkrl;g}wB(44+Gl z&q49rnK+VSJZzQiU%_QfW=iKXKsA(RIVyq^u6V{zr$5k z$bGZpetC!Iq>%glBedqZKi1Q_J1)pc;d;t;YN21IOHN#d|mBO7H12gm$!DSzL zm-4QnUER1iea}U2I8|i!o=_k>-C)pCvqQCXX zYK?1a&Z$j5pwY`)HIo_not;cSa#rSuOmX(C;_=<{k34Eivhg9(%MT%{wAK_UJAZf) z;fQjEMZt5w#lLzY*|>VaapoTqqH9(8Bg697s(ka9hNR>-4N0sGDR@XajJeyEO7E86 zSM3Z*FnclM)(k62CW~#H8;(EUBYs7yI-56z{?O{Yd}_|EO+V_!Yxg^j&q}tu zT%Re<#5BaJ(tzv^q?Vz?WWR~^p+q(&vq;2^z7?mE!NxOF1d6*cFMVq% z!o(qQV_#>ACEhr$cO^lF$?-8Z1P660z9%^1>Tn4D7g%x$H9f#xDxTChK}KPjy<;d| z&1ie1E5L^1V3{1Z;rO5(v1`6fGBY~S!c}A?jNkI+q-=bBDm&LY!CQn8Cdmz5Ha@?0 zb7XvuL#6RKo~ad`AELvDq$1L1E(*u!?{{PL`mio*8c;a-e;;seM)C^@#@N$0QP+8%OoDF`|zIj0p=d z5t2&p^(}1CwQ6Al5!|;z!G+_3_m1C5@Bx!tzI}!C^~isX)Axr>-|aWC#>=p?xf>al zMQV0w7_X{L-{+_^*@$LYA23fFm z0PXCc)czJPW!&4D9KVAx@0RAr(%mTfvrMV%T2)NE<5{53##--Z1}eml0ijehXflE5 z>!40i_bDZW)9bf3eO{$A)PCHRuDFertKbc^9F$POQxtzWC{^Ny*|DLCQbynhCrXW) zX_olmv+-B>F$9Fb;kU5f`Vr-0Evc{}0nMS|Ze7u@p5kgS|P{bnH$b1wuewv8% z7mV%|=FEyxM!1-58E*{Cr1aKgn!p1?aRlrnyLUx=t^`l8aCXhPJjo5-+r&r*!^jX? z<4cQs5?!qh7F!438lSD=Th>%i1i1JGdstU3MK*30RyA-@Tg`oJaVy=S4dAzkXu#44 z@=o|JUNzS_@fk2!6>GVSgh=>drCCZ=?k(J-drIFHAdtGkhoN6_J?AATC?q|rO$Wrqv00{SRbItVs^q@)D;PyITq-4Qr8_k( z6N`$W@~~muelR~KBN5DuS1BrVte3M?%arO7VkxzapVXB5K$buWO$YDBZn7DvvC!fw zwF@Bkl}q_?v8(byRKdRDK@Tb(lpMd4c+k_P*CWV}K2?sd`c_%%hFII4!wnzGoBI|1 za4J)J>Vx==c$mb!T^l0^@;g+V!IueSOe%ZAg}<<GzKP<;{rOm6^_!0j0U>iV<>Tc9EQ@WlxOCAjmQJC2j>(P}99buRbP|491 zT7`bB++d2bXBp~+h*RlxdQ%x>dEsr^54x z>wO%=d1?;q#hjd^xxqs}>xaWZ9`{OnS^5ggO7pn0gBMYh$2oK#96H>WTXt+f$YF3h zkSJ$A^Q9MXHXook`?S4W>BA$=q@h6*Hs8j3-%HUjPc|Jz8F)vyDAw{cR*HKnx@FG* zwf0#1k#2;2jAO*L5q{^$1El$2no$BH+B0?pj0J!CDbyZq6}Fuzqq`XE1rGreaW`>A zzR%p(BO0Hz!ek=ZUamCR6Bdy#L=$|^=Re=_hsG9SWzwNX^{fU4-4O$KjBTJw_jf&`c}pllWdv6@r*qjkSN#+jj3CG+AF;AzI2wMd{B&PdQv}jxE|uJ&Og42(t8aS#PoCe_XxVGIM$X}-nU3(@CS8MtcZaIV#El3DU4 z1TUOq=x!>csp*y0wJ9J$UxNLd9G~m$%RuqPec0s%U;VN0;lp|JzuRUz@OOis@J9Y_ zb@(R8Ds6h3@9K8Dyy@M+C`&nfI;26*ULpy;wEb0DwlwpTeu#T;*Q#;Ooa zqG?J}%Qm<~260jsdBD_0Wvu1Ke@cOzmCN02z1B*b@1zh}9E~h;HwojO0Sj28RyqYT zu-R5im|B^U&i$mc27+qbreK06-~c0_G|?B+(mVrC{||Xldh(igRqXRV2ps0i`{w;l zKJU$>q4-p<;_ng|`Ca2s+`py|Bj3%V_#$bd#b4#~*6G^QaU#3iYZmM+odr6DPs6rV zVnR9c$I@f!&?~ssniEaG@>eQ*rds0-);gWsUcO$;xq)Xsnm$zILiQuPv^>5!l^U@= zdlWtX&T3bvRmKk^NWo)xgS!L-=|Zl#!EoSIGd~cHC}=oJSz$qmceAYzzT!qJQN;=c zmb-)YHp}|EN?B5k0?oW#{UK{ZP9-O$|7n?NvCPzNHG>Ze+V<9qa}){_LJ2HyT*VYNQjPqo@SN!(_-@soVtQXgyoUuNjk zkGEBEAgrO4~( zihY(}F>WlR@wXkDaLx(bgren^Dah1YZrR8doo>43?}nv$D5*!dDrkQN3?o za=vP_$6Rb4>CMF@-1IgViOc~Jdoi(XgAB$W{6MG2V0_O*`WOs^U`kmnOM>IjzTUK{ zbUHJ4QG@Y2gvzYy_fZdc4(rlS5kGcwzXs#E?~%B7KX3p6Zb|KaUPk+Y+pN|K`vIFJ zevO!<=EH=^wKau3&5O?c0T0G>vCifKSH9@&hdqttDQp+)svsSH0p1SrRKn}|X>(eO z7MT3Oh>gnqGjy|nW99AX~Xc1$j9It=a>g-t@g{)H@Ji#~u+3Wf77 zl5wR+CG%I~lz~?Q*QU2d7AU0YWBMipf@EUtUvYD^#VZSC@?$5HDyJHuOuUmZ(t;R$ zoQ$i#(~nGkDuvXjWRq_bx0|C}`nkUplKm@3 z_Lb6{o;LASwW#c2)0X$!Cc2mQL-uX~A^XoS6X^ho5E4;pD`vtwLf)dp*$XT^7xul%&;20jrfDbZ2DAV z$C7^J@q&QJ;7Cw;lCY)4>~moDLl^A*zJtyth9XV zF~{@p{wSR2Dcrvog>Uvlq0r|>L7|J(Trs$(eiU^eW1vQY)OYg_Y{nwZy^(eHzro6xyfL{eggpww`OWQpcM#3Oij>*9B;q^Tdl$ zTyqTOK4&zZ4UJY|hz8xYn5zN--ue1zUcS#~NSGb`6XHU5(qDwNyjNgIxt}ZY92i08 zQT!~A;%A1Uv`i@6AlhnqrAP5?hvMEp^ibqcEYG8uVJHS4(u<0(dla9wYfmlTOvc=B zhA4ix$Vigl77rbmzMjh-Ty35-JI%CLwdPW*HJ8dF6{c2gr%G_l-;r0#nlZUfs`>vN z-QWM_(M_^7Z((00qmUblHieyee%u-Q{86W8gfwF@tn{oI+#USo+XILXz7lJ@%+I*` zxa@?-e`pRVGqzLxo4M9Ms?37^@p~FAXG%ZLTuoGccQ~K%e5ZV&`p#AE>|w*Hk$$Z0 zZRvj0_fY}Snd`Ym)%VqYd`6+q-R(o8a)1#?O?q2R`Yn8H9B(tZjBGS6uUc@p8C^Mm zJfg*BdVfVR=AT!ZSdQ-{meu&c_)&=EkOHybB^HWh{>vtop|=-`v! zz%?qE5B4J%^QV@W0_VqR2nIEIPa;`B5fPEp_Y%nuacP}MK3yOZBoYw`ahf_CtdzcR zTcJoM;7`y49PS!G*o1ty{zV4g{WPHq7xg2OYXw9k=WvaRq1yyO%pR6*}FJs3tE z@;YQb{-;{{QNi;CLHL8No^kYTLX{x17MAicqRM$1MAgivk`>C!(W@v=HiETFK z`k=3#o(ik--A$-fR}vXXWhSh?75XHAu)@=B{{)=Ui|j=IpN;oxXB)!g7SS1DWR zkCDioN7B5_saqE`2n^Sw>`FqxvlD(~g6naVQs4;&kS034@DZQ))hi{=(&I#!U##LC zvq@xgzVmw0Q2gP&ir*?Q#sAi!*#7H2C{E9#XeCXw_~kzDC6<>+PZ+UxZJoLN++$lM zvJ;jHtwe@^j$uFlVSlwc4kL)utq7eTz*3F5!ARlFmfp^|_Re^Zq)za~4RBXWi|B8& z;V+pz%MFs$V++N{uF#7OUbpA%!FpXY6UrQ$cG`o_HiK-gqJFG2+0t>nivOcW(dw?z zyyxfho^LPNNwwXI4zBc>&fqG0QjLK^I>*Fq5rmrx3{6=$I9<|+@yX5Q=f5#wZ4X=9 zugHDh`(%|AX;$*;8=rD5Um8wD*sNXXOH5}BWgX{LN6^f3e_?EC5v0mzt@zd7dHBd-;xY^O;gPg5dAxrYqZhdLjn2hR8bdtV2yq+X( z-RxNDk-aGUs-tXbzm!$?PuZ^*^h4Pu0io<#u2IV7?2EEH8L$xu-H=PEvqyeGD%YoOJ{^V`^1?NP{L3r) zkwCYANZ`9%qY~Ii0r~9Fy14^oaV9W7j*~|U_wS|iy?3Ky*n0|R+4$Ejw@{xxni$-F zkNl!S+sp|2^d^x(mdjJwaZb7%4;Tdz9{l zLW2cbN`=V9aXY^2oKCfE3XPLomk;z3&Lx;4YjTI00V)08n+p~0Bw2=;UGW)}P!`n+{*E1sPM`k7cQFgSa z?3J$A{C`FD?e{oQc&fKTHC?$2ExR(p9zL=nu+k=iZ3_6;^YWvkuh8=TugDr% zNY?THPqumVea2&j=ka;^-v28)n>G}PuMSJx+rIth)qRAJV(peWYd0oSo*V2Ji-abB zHau7ho%p!Ymi~>j(H44xYoSAFSADzD-Qlpl(5ij$G7|T8anb@}J5J*owH-g+R}1|b zp~qQEGy5}Z`ibnkV&_V*zwtfnXVgxlJiq|wk>Vl0=Xj9&sTzXkdP1CFI>nn zg)=S=nye$F>hEF6%TP8baUcxal2|QLo*KWU`M&fPM{Ls}ZY7Hdfq*WSdvm53bLxXw z=EwYsEu3!qHidH>()jiB$0r+KJL;*Fc6Vhzs}tN<>dvt}ld>h_k^@-3n@X<_7nB5Z znouh?AC|#pNj$#;Rr~jB|7(8#*<`o>Y>@3d8)m;L?LV_Uup8OQ#Gyi|^rKc%aM3jF zi#x(}&k$!%E7k!aYp83t?mEOD?r)uJ`&-@4R?eOSO-lP)-QKuOI?tng_@0FWifj#K z?2LPvgO2DSENjiif%Vz>)y?@T_qNnW=-8Wj6l!EmZ_!qi`tVO)xH*T4K7>5 zoK)rrO;kGW#%qdfJn+Yfo4H3a)jJdDP?SlqVhTj(PT_f-#JKJ<)y zWP3#WP!so?hS_i8kucXo@Qs~p`H%L6Cep8)7{hf5K7YR5&`3lso3qql`|R8FdGqCl z?E&olO&WvsaST@ZsK)1KQYDK)|PoU;SAnQ zjQ#GOiRp(XrMq8C#1;%*NgCahKEw?zJy*jSZ;g+UI`x#++dYOA{u?2Or!JqsZ&%ad zz&Mez@?MPStX!S^XSpHt(y6bl2ET zM|IWg-a(@IDV>Pf{G~K%_js~+%S#`0=hjWxz+trD+Sqh7R1A7lThT!ESbC!;Dly+%>rdYU3$8X4kG6>n&D1@merxPBx*?pzTmP8WsEon#}bg|h2UI3Aw^;7 zAvKN)e)HvvD?V3Xn;Ps4Z{tbJF)88Jcp2@%7Wp49kBzilj+asAy9rxMXPZ|$Vl5lk z#sTh`@hY0o6O+>G6(ttww3|`4{6I}%$W(3cdChJrQL0uikSPcu6fjL<4P)_^MP-Jr z^lfqq7P~6N3VT{<+Z^7=c_`16vnsXyN5diV4LmR1q&JT3*qFnHm-KWAwog?a%0UTj zoIbboG($PGWPtXj4)A-YyP6-h9o+ZJaamQ|G{R}{{cc-M2^((D<%qQ*B{YU}IcH5< zWvK)3jn-z>nemF))xS5w&;potJHk$8F2sWITUp{K4yzD$ri>FJ7I)Y*30$NaZ7W#& zmtfDG26`iR;f}9e;WFcD+h8Qe0C#MFaU+M|pp;_(w}7qa+VZudd9&N{wHZ!ocG;G% z&A>M|9RW)!A-dB@ThQyf@&5?<_bJoWkM~EcSiiZczf!lT)C9|k!(tP$;p+g@uWK4k z!RC_M4)Q6K3AjV+lm~x|sa$TRaB>BEo1}{9^L1P)b?_xjYT7=?PayEO+d2^a>(sxW zV7d)4BZtZk%)Z0Mv6@0ULS%FcYxk^)?8)CbF*fB{z2Mkk?x+4uuMYbI$o1w)fgVyq z-PP*{L(AhcB%8Wb$X5ZI{w$^Iz|-lXo(iv~+BvC%5pS%0BTKEIdolWK{Tr*bui-uc zPfP83P5fG}+RmpI@zQj&n-j4CEW}0@av|jytkPvFC&{^^`z{+?lZNTaS8M)^i*Hth zvs@x69=z;;G<93~x;qdYpR;ECy7?E;3=^yO$d4Gk`ts}e-Ex_P5G{?u3Q@fpDU4=s z0}1T3gut7IM-$joNkYvg zw&*Gv4Ag4~!ti8T7fGgQ`Fg!h4ePld!@caC*y5K;>d=${C2?8{wSeM4vAwOpBCC>g z{Gm3-*Ry9rnD$s@>2}D<_(BMXwa+GxmetQd+1!da(lGC2=iKD2?^K(*nXHX#)cFj4 zSxe3@N5lp%eVL&G?MbJ9&y5&a-kD5DhdCq<5+OfkcV4XZNv7qjp+U=m8~X0&#BrdJ z%kAgD2NvabqRf5>P>(M3KJsBzbC*u*buGQ=sGb%cbEiv~4D8$n+Fq=+0`0ScjRaS^ z?4#_;LFS)C z9)O;XR^lUnaU}U+&gzk_`9W*u?D$f4hTB&vo3bk85B(l zIb3S2TS$osI&puDieRzq?>+r;O|T`}3w7iwh(}>ZZ{-2RQ}9lXrUT|_rb?zEkKuLY z*4&j$SS&S*tuAAAZZdNW?m0Kg2AXa>%r?iDu<$q^tt~diLAOm=Z(_IJmJ_m|$sCY4 zY2<()ssqxo^qx*qWXaH&|iZeob?VQa8Nbq&ZW+WRx@NdxSFH&yPCJ= zkD%f3@P)$sqM}EGZ`SHOf99)or5FZ||8njURl`Ucuqfru#f3WE%-2kg%VBVkOh1;= zX&~2{8#*byhtNVb>Y)fj!9{JjM)3#f6_)@-@t2yj6o}Yi+T>p7sL9!~PcwqmnmBG* zQx{qqIcqXKQdVdPO^x|)>1t>b^<^ZoWvc-3 z<$cj@s@=SRnc?!}OVvJZQ(i1<(X_Tm-~hwLc{Fq)>$sav%+k40a;m2NorDcrCnI2Dq`a@1)VB+4qk_>HMLp+?*g%oGgB_wb-Z$C+a}#&o^kv}#9HSd z6H0TwYk)lPRiWyBgSB<&9y>fq78#EATz-J8_3N=kCwd4jP3-EA2?_M^AVTiR9R$F| ze=@^sSdN#Q--vcaw}KT8g__9`A5B z_@CV9_!g&cOcbCDDnCIZqiIFdc8JC-UUg0*S8&C2DclMZ4y8MlSq@N=BEMjGbWqFz z3!qiE)#cBBsY4oP%D1DSxw>3qNpzQr&kp7ai;%E}$RSaD4L9n{4)}2BxJl4TCz3Rk zy~cb#zjZF$c3&S<>Lpv+w-CieDvw=ikG@SDD2C8~YhtYX*W%6W;G<3Fy+9)DDy6lQ zMZ(pa?cW&CBGQgt$pB7zSPO3GlSB;8$nz6?(lTfo6(SGG=SG-zEu@x=r>$u1pV9TA%t7PtiKRA< zUlm(2oK8?}Kt`u$k5XvomfTfN)+^V{CTAq7W`4ntnNotsG0kSH9obl3Vd5eeqvtY% zC$rKc9QZ#p)}LUZPH3z{359kVlbvg4r-O@Isq?91+A6mM#-LLcgb9qwhjg<#*TN*f zwKqLJky|Dk5!x|aCkc)LjYcxuHawcEVVcvq44}yUl49}>#J#yslG`40moS}&2HtNq z>Lj7{Xd_bDm8MowFKdI@((~r3*7rtKvz9f5VfZ8x`Qh6UXpglETFsbHLxs1}>-efc zJ&m@SdJVe1;IvmYZ7r6Pg6$qCr^&aWy}`=>_3{RL=|R@a~b<7BE}t!MTq7`MT~yw;Z8)qNNp%QZ}r;6R|4YTZ1E2FHvHmjCg_{_5`bc3TZXn zdi)$$8S-E9x>XFp)}4mB6NC`AD_#l!;=C3;Ye?8%luy4Ah-&UiUEee7xeZ#U9IL!P z*TtrTJD{~F_w)Q+96KtiX!1_Lp0{-ot^1_O-z=XnNsn$FdyK zJi!&7;BI>fg0S)T8xtR66(&1?O~}3G*Gstm4+;=o#Lq9X?y>ae-$E4LmV3%yhH}>B zKJN4+te2C7AbZ%2kgb)wXsu_(v#r*|*v5JO!6BX-6`rraYJg&OKf4xKmsd;^{ICH! zq_tLJrgV@fRNIbN)ZovPowN$@Zv`m)Ked-4hxTk8zP4M&Y*m~n&yFfL<7oCmx|d4d z>gpl8+|(zjLx%0k)?OrcMSRFc3BofUj8&1;KC>*(YhYh4Zy+-;b1-y_?~a|Z%9uw) z(#qguBh00;F96+Y@Y=?KlJW?WFr|d5U0nLD1@H%~0+@VJ3AU2^WTP<0j%tmM(Gw}E zx$?hge0P%K#%?g(kuD~I27frqiDU^^(^7JKp6(V;>i0tK!cNCtBXYc{(l+0GhShWcj$=#8Xb-s$@*_qnXNx;as!n ze<*Dks{(0X=62|h6xD@l`2{EKI;TXTw7=q{J)b7>9@KKl>HSFgj{rsEJi8XC<$3*x zNhRjKX2Y&(quuEZLBT>!ZeCpu8yl!+`_v=j|Fm=CjT5``(bsA7UivRNfwuMhdnjcr4 zD`po%PZOf46^h~}29${6vzPY~#WE*~Z#p#zMe()}WDmQ1me`577b#+pFY6tK+PZ3* zl$IwHHl<&s`Vq}WfZq4ef$>47Pt=WJ%zIdODUn5cw0I6V@~rE0OI*6-GJEXRly2%r zvc^C`QyT8eD`?**sXR%`onjvx;}aDSb(9iCh&qI45w+nov8g8YVd5W%H)!TXVVn6k zRf&Zf=`=hP@9|E&6<-vhh7K-ycE2o!bx(c9(NZ7SN)7~`oDKzCOF*m{W#s|SBfUb4~0SNp*^;6(=!l)>Csw{XKQ}9$(@Kjy!lq`6vD|o6ec$!i0G`rwwZo$*M zf~SQAPm2qlcEEC`h+y35tJ-$K?Km3oO!Kx}XO7EaoOhAS%*s3*oN*o;nR^EUe&ET6G!8g45X z$ZxATIAxatPO^Y`0L3~7aLHxdXilm6{T2k$Hx|A?!TP#^`?7)NO9$C}81u=tennGZ zwls(H@^px<4#;!I=xIK&*E*eboR`57Ca?N7HVbWwDlb|>5~6dnVcQW z8ij955@LjJF7jIQ9Mn^Vpkkc+%BKC951B#pg1`x<ercI!LlBaVN zwPuy4GyThqjE0j)V;2-d5-ByVjJ1B%*V$r+V5TCs`X1fnZnu96fK=N0A6 zs*NpRn#pjl4d(M6$VDnmVd&U&rdTzxOPL+iQ*a&$A{lwPHu$X1^bbz1L{{#D00?g@ z*_QjspmJ!5wdedIsu9Q_Q_hz{F6g-bzWeSgz3%$!582o?L6_K~%rVxMTQ^k|6VlDSg-E7z!dD42ezW?(sL$VCVh$ETaZz^^h_VGubT=x!#4 zH2CwS9!IIrHX4Gp%+m<+Bx_W!{6YJvsv&wsb2~IGdWRrfzrmG_(m!)J!wlei3i&Hu zAI0bCSPdOv=_%FUXdz=BOLjdhA(?(a3(l*8)Ah1(etcXi%O@g9k-U>U7Fi+6G3xpY zRSw_e(3G8gPVe+gj@QMGx;1{AGSFjID1O~#56llU%F`|MT*p-b6WuT4ULKR~JGkdR z-v~IxG5Q@{v!!LQ1>bo_dn$K_CaOHcp3ybE8U2iqAjhhZ%V4fSpbrM}d?|@dLFV}p zr@xycPM7y3y@#_r$NSM)DI~aR78}U<*xqr#m%9fn}1b9bY|2?L5Y4pb)NA^Wt}JG?4{GbYSu@X zQ40twH24{~3RV4nK~VK2DkWQbhePl2bO}$k^i`^{x3-HbHEXGO9(}^2@6mvZ4Dw!N zHsLp4Q7Qc>Z&YS0-&tlaob0&i)HPdLCH=EwTxB6Ph?^djKFnAxG*SiJTqYz18nDbD z?}eKap1MHXyo){)J@X3EZ|gk7bMxA#jhnAHh46KA58R;SztAL}XDYAS{ngDaLQ=rZ zCWE{eZbl7(n|IY`Z;vRvUv5rQacJ6+R;;`XE$d#=p)mqp20hozct!5#42bgmfkKmv z1!0X!v9tDJBDZ9piS??Q_4IA(#Pm__srDWF)bo3S zWe00F+5U7~i*M&OSxL+9HP*%8!gR!A+sY8((9_==lF858*Y{FS@2PEB!*(Tg z-q-wjEXhuVjOX{Hw0litm_vgodI;gu4UQZZRI#RMG9P8H)Y3w#n=unf@uK*X?}}Gc z1;QaB`IUo0lG6v$N2JoPNm2`;UYj7Dr-63SH>_x1Vp51*MA#M}z|Rin-ks z^T?I1xKPU7(_9CmXid*~OYlZ{-`j^#V^y3x@ocQ+tdm^|4V!>6PUUxwoM1P|tv2{njq+>-ctgM& zoa-rUY{hd&?K!*rs+saOX=>5&Zd~=wuDRr zX2zw~^mxparMs@*{k9(U7J|ENZRC()-LaNisvQw^j(rUc?69v{UM%&%Pb`aNA3nvU z)1XmGtQ9qxq7w(AX3MCpSTw-Vk5N`veh*x!Mj{83a{oKioMZ6l~#Hdm!f`ccG$Q3`M!i$zzBM z?YqqqOwl$4MrE<9?xhy)IIGT@!7I!*oQraOb{5>6ZCchEuM!_c#iVDcUaaNUdVHP8 z#!tBcbwZzfoKBQaV%-W1mSp4fxW$r8BN^(u7<^imL__{>E@RBTpx<0Smn{kEKvM2- z1r(ztPVQ3YE*iH3>~fcC2NW;KEQT0osg5mflWWeAvW|c>Em6IN*P1C)UPTbfO$2!J z$SnBwHxrErjV2iHsyf>L`v+QoYrBT2r+HlwqY1c}TDj**Kk{`INK)Zw)lZ#)R;`c+`gb*f?U@2B z{?p~-KbiGjw-gK7g zO4R3rU4tG{1+dFDHg!<9dWlCQe=XS7;}qT4reE84Gg)ns-8Wce+z;+?F(_vHD}4L$ z4s^L_>|To&{R0$l(P7OHjDIh^e`y#m`UWcD<3$!7BKXl0FCv13a>#VBv3A;O#fi9= z@72kD=fsLG5EC((e8OSVrArNLIt z@9Mp(TXoup?dNf)hLr;ZQjrfCsn=-#GlVP42;S~9m~t~3L0fD6IoJMzDP3%2Kv$b) z;cfizguJ)$bp>i@+VXFB^Ic62@@U?M_h=MC!QUCCrH0<~;2gHRx3TUxc}UxXHC#od z+G~cnUV^n(`Y4s`Lrc}bSnJ{R&4}IYt0KOeI|6?$^tk7s_>$+rlOZ^Z(S9 zhR%g`sY`xCM(VpG_dc8cO9=0oS|UjEpgNqb!d$P)oz9$w`c-YK@A2!4yr3Kd4efD`Jo}eY+x7&H9w4uHSezPM{CnQJ)ci(0d6u-9endTaR3A?sER(mPu|rY; zTlUu$^O^06*fk&4rWgf3w|PGvGE_tAOd^D!<&#U#InT@;M7j2~4>!I{MTy{#_7L3T z$D8O7RXCFpdU?5zSsk>BbGMoH@7nX6E&agpc|~k4RK%R--+C$H5OU`(A*b0lagszH zHGiIbdQp+@&nsqW3!pl5`VZ^8-|s)%*KMM6ow)4il+vSN8CB8FN|^^U8?fIRU#PZ# z=b}cOJ*QY6oK_};dfJ$}`b~ZRI6OCjm@{^Z*z%A;`eAFNH!*y_+hZ}@z4CLufIqLn zpD*x$WIM=y^XCh!;``NwI4~=&{GR;&9EIq458?N(-&217z4!;MeEYTU#oML{mERhl zOZ$^2Fpq1dC^LisXZy=TtuCpfsmM!CTP52MQ8{#bbueylZW`$Cn? zBQ1XAQQqIeZTh&seV2;{s%NsC{PT6GV)L{FAkPj6k^iJ&T%Fqc-;5giEDEkUJ4xJB zuRc#wc^q8kk>g!1^@jA?_%Lj=a?WsBbP>X&!1C4fFxwu^A(hO&e6$giC*N(hU0t6h zzx+1J4?c0X^V#G)lD3}Q#pM$2QUEw>MP!n5MJ>t3tYOZq<&FJfZHLpSP~YX|+ab#3 z@wuc_RTx#EpKZmjw5myD4#|8#WzGedU~5wyVUf8GQ~`*#w-EUVKwz79mC43~U}2xG zaCXpv$=#3p6v@U7;azsngZbNG8~epzwU$ipN8brf2o`cbi}HEyf8wWDZ!6*)`7PBB%2#zMe@Z(ixDO7%v~ zQ~*n`4Xn;>++X@BC8Y-jm5sW%a;Rw{9UM*FCB`4lemX64pc3Zss(7I8>MXIdSU?(` za<#(oPEwm~O08s<*$ewkY!35ojOKNAx=((8KFvQZzx@`RPs4PmJD;Z4IZJ#_OvRTx zYWeKf>{NKplB-?GPA*8x>jN`mVr}=ZWXyb#h7UQps*3K?D6nS)xFYN@ly?O0TdElK z4LjUMikf+A(r~bZXT4J}&FB=BdE)h>I8sR-;Z{W1UP3Aw?@G+6?Y_vu9-t^GtYAlW!gS_{Jc-}3xl?CJl}&bESNY^*3yIUDfjp!w_S(}k-ilt)GwY`e zgq;_YIH=c4&HAZ-S*mPz0Jd4b+Vm!kmo6T4BWwEnY~N;`lUA9Z{(^#~R-~KrGsJF1 zTE8KBm{~><^5`vM$UXmyg1>y!G5>w8>W*N3`0s5_i5PRpG;?Jl&(E28xh#x&h`s`% z!U#?>l#bbaWi%Sl(H^eCrgI{qma2b^C&$?8V`g05g;0{gIW*pl|*Ls}t^^EEd{EMk`^vDNnt$!`C@=fNb#K++cXy4s2~h;$>Z? zCARO-_}Ba`X;1J$73}<=mS;5P7#F*tQ^Sw4dzyY3`u;E<{4$=e>%q-7t4BG6u^>n- zX^+23!M&hb3+kE(lFEr?XpgJ9XPls<4X1Q}6{5 z;oVBhWv$Y7v~CY37=;4}{$69py#s=)W#%fTmV$eEpRLv7v?FSh0?8`anRy1pSaSiQ{f|9;5vE@vW7 z*kc~J6){=2ptA1(sOuto>5RQ^1L=I}Uh&Q1=XIc`L+ITJjPnJ_=;up6&leyY9<_sc zt|?{z8FDyrj6IS)*+WJsjXJhql+P#|oCl8ZK-u6taDWHO2Iqm>Mmj~24bB4}^FZ0) zJa7#_9)d+&bKPv{T&l{PO%giox#K?>Yd^aj;mKP7Ry;5_SbI6Lr4LghNP8=iyj(R9 z+Q4jShvp1@qYAq}PP{A1Re_y$!dztTZyeekuD7ri2s7iAwdr*!Jc_!|amii6P6~~i zQ6$ALXdyEw4Ji-NUUW{sn9F0Vy_-ex+0PY^-DSrc=}fjH@C3P1T*b{TQ2x@V!tykR zO+3ojdnzMtqPLoT>b{HvL3K1vca62|yU59;(JGED+1Qk%NRGTD+O4tZ1DD^$@2i(R zZFm?;7vi}GJpTO6ZZg;0Axws@`3{^wot9?gp^YLh);a|81)al_VyCmY=DEwg#s|g1 zxFsCjf^wvHWX8AcjkOi=`3#%<+I*x*g;{p8%DbUNTEBW9;(e=ye4*VFS)L1OLLL0_ z1+-xI2hE}2mW0bKKW`G|fUXH1b8i{%A$lQIs2fEPVu^X7fe5mLv>c?G1>;QB=eh2M z3|Ia%cUnb+h^aQ`Y`Gd9MC5CXm`Z+A?1i5h7Fzdbj!_We9cg4==%-zfWWQ|?bFo;lx!`RH2p7r8_slB4z(l`Cn zj7V8{LvwJD3U{Ml)XdoorL2pb^?@=Y z5}87oQu@ZJ5uhX|5i033<#{?XD-Dc#I9IDllDuCL4u5BFtL@P^!B zG{2U&_*&d|A6CJoe?EmK>qp_fQ5P{;&!I-IP#s#@;ti``&U4c^8I9%rFX#Eh2xohi zB16|xU|yyP$n^-WVNPFCF(u`W;b?d%bK7SIQ86OzV}G}!_}zK}3{D$m=FJM<`;3sx z#^s5QPLJ{o5ud)*(dS8LO_k+e=&#lXe4F)KvTb=kQ8fNuK(3eC%h1DQK`ARW*q}bn zn0Lr)|Ejt!CdQ!t_BKQ9`(2u{itrTGK~X3~xsgG+kY^)-0!f)2NcF*SdJ~NjjNL$V zKu+ORH9j^F`i!g*R*axJc2rMnV3`r&yH|CgJziqIyN0M`&?c3Zm~P=d+D!*PWQ~|4 z@HJi0AJ`tAWvWOtVuco35q^k9OOK3!&J>>*oGn7>MNq)^2tx^kczPOTa8JuD$qg>4a zLK)*|&Q661$`Kv7h18)x8T+GqjVyl9lUVs z@nrn`m~I=Dvhx&rsAriDCv0#k{n7I~xHKeQ*ujfwiLJfD2G0(Qx|<2s94c;5%lbp& z1~-MP0F7{!h+$st!$I4F2J#Zn8)I|LQVeOWKXHw#^EjP`c-fsDl^rmJT%3dI8b~lu zIAOGIAc5AIi85Z1MCR|c@a9rWhs|nu+iZr4#QmeINOe)Y+2c0U~(oKSGvFe zg@Cp^x2OoX}> z{-#LwUch0`;A~bH7W2cT*}~Ynhgjl^JJVjG5~zwt`~|C2wG5Bl1r0*1J++%RlD?q5 ze!DtY6LY-XsH?Tbd@y8M zKfLvh7`RTsH9qwOGIT-8a7C-^G9aOOHv?LMuEpAZMCA}Wkn!g!%dfNbTI^Eqni{as z*600w*0V-i>3?M8-~PZm82RO?j1^4RlB<_=8v2or*>4(!x`#gfqHk}( zvEVWz9yVPv6d?}Y%dk-Q!Dp>FH=+nr1;+uj2T~9XKtId^qjVALy~3GiugQJQx1S;i zy#sHyWzJQ0|K|Fp!A?cKscWH%oZpWS3hXi+n1V8SmnT$_qYPIsJN-p~k%|q+4k!$E zHyUCXUzpG|s?a(g?C}>^=lwjez&bxMNL)p&^9F;sN%Oq)S9oB7b^eJ57Fg$RdtiZe zZuYpVk1?8=9^T3=J2tKF!9#|m4=K;dwEk_}f4Kgwhv4Y? zHw1^E`mBFDM*4tW)g#iDfyKEbpHA2KnYdkg!f4`sJEzxGF3qI=5VfIPG3?DCFPF3-!%3LitD4X7g3r|JFy>) zwcuK!I}35#1de>h z)0Hthc;aZwa3`BW!1F-xWdoPaDgdtw>I^*mYQR1z1M1Dec!4Q>f3B3iprG`B7M6Z= zwDj)%UB(Bvl5t`|#yy1@caDva{X=EU4sJiTknGzGT>85L@Vel70}t;m0B;Vi5*V`U zxXKF1FtSJ}cPK%NRC*6zj;~E~D!yL{BSou}<;s@+X-vL;{^-M|Zp>7Af`|<3Cp)Ui z=}V}0qfNR#qJg3<1zUE*IhW_AG!ddBJ^RSae)qc z3w0R5!=;Y>-|FhdUc>LvJR_=~A9IDiYe5L(j%YaBkGBe#KHE@6-M()b1giHDzi@m- z>CE%dKbs+IDmTwkv1jRtk{*^m+n1$&;um+m14|aaxXMsQS-KSnVjHKh1>J1u)W-hE zL-Q43u%h`=xv*tDo@)XHAzN9*z4_0A6Q5DJ)C-l!nucD%3G-VyOmTbg=m2Dp9ej&T zs=lW<#LB1)ybc${Ar^p=7CVEIDM1T5TnJ*F&S}|c4ifRX%82{A*obgvON0)TZSi;C z!V6~WedA=es9_s1hf&?5oCZ>UUIV-)%ZJr`*H&u*lXc!~?*$A!J8eUqc(=t25A0{< z1-Izx{VZa6k1=6Ov0GvFE{VlCyVrUb*0qLE<(-?m(rQGF2jjDae8CxpvX^JO*q2kL zt`8%OiQ&|Y^8LwJ=-D=qFic=C+5g9^#F=bQWQU*TCvG*rC-{Ufroh4dkOwZNgi!Fo z8-!sC9o)bmy&T+!Jg~sQy~_g&9Nb@eV1a{stp^r3xZe^Gt*o(^QpfDz`#)~5Wafm% zqjl$kV_xd^btvv-NM+hXsVZ2p(4Ku%AXg-&dYSfeU)&~pSrC5c%vYz!{$9fm3k_G) z0{qG#X4I&~d=%E1?tJhe3`L6r#gU_tu`bt?q)ENCUAj?V+~O(?5x%{5zfd2;#R{v8 zC*Ok=uoc?xeZ(GaHC$1iHXG#Kc*@5j{@-|VfrrynB#a%|m$5bdF!r7T4-dU9Aw?N` z3rJ|Ao4>wre!PN33OzxFh=n%k{`dCz=M=PW`z%IJB89wg#fGUZ8JTs)Xls6rKo|oK zKh>!{{4y$1BDq7V0QCUDi*JchKJfr9Yv@=ijt_s5bQ%=}1FfuEZ89)SqQJs7%a@4H z&~kz&(cR_VuKI-z{b;1Kzu_7&wo8Z}`h(jrWl>EPjVjv*s&wboB$%O6k-(>{^e`fT z%jLN9!swDPyc)~6hRlY{2mg9gOgqaerqot~V+}Xko!ql1laa-^@)wO6lolo=0q3q@ zPu(~&c-|wIJq?is8v!CVJxdJ1?<^6qf;{BMKAR%BdEjCXlqt;vFZDo~(mZgw2g;P@ zfwdkeQ~CtklpXw0 z^aQM-*na{7CJi@fK?H_bswd~nJaH=1RPSO4P%Ws)Jas?tz)HmA3?Za`Pe87x+RM@= zQIS{u`Hp~_sg<50T#->~RQXoy9#o=Fu}4IT6)mO_BYm;=kt4U%A`g*)hm#bH6-w%+ zKboYv;(a8Qc7(p^`%GoX0bNCV2I`ao`jOOt-jbTM!X(x7;XabO!x4ImtM*V*3)S4RqgEXH4w8Cx zcR!Uo!jqhoq^!aqb$};%t>q})^`WSw{_F_&7zFG~Qlcg=sc-aG>`fl1VkIe+99$zH z#h=bKcOZwl_9H2Ca-w$XBe$ERJ|`Lr?bJUUp$lBKhmu-GNl5AxE%DlyPOab7kEFK! zf2_R=d{xEu$D2dW(Wu}FnkZUQV+{%xDp*p95=|h1ec(hYMlN67~ zjo4a?)mp2zTD4VM+ak4^$Rmi>0=^I*AS&*N7SJmA$*MS)UA$FGyj)N{rc0LaB5MQs6#h$ zGWCcO;nXFTnYc%hp}Eobsw3bC`5zknCU9R z#8zs~@ufUW)N6)HwCS%bOw`+-xv98FiFDljPlP+sVFM?!Lhp2>?hmQo)^Vac*Kt2F zB-^RYTf@XI1YQ>=b|G+jm?#2sRG+6r2;7%z$Lkx!)jTI*;UmW8Lq&F1HV>f9c%#pB z5)!dF^hWQ+u4Cj=-oYDv|Hqwd&I$MnN`#ELTqDTPV)_9!b^IDLA&kr9y?cwxoRW*n zT=VR9V&Y~{OxdnuxbjcdnsE|>uC2Mt4WYTNx1!ecc0w~_W>W zVWMcsQ9VkD(9)f&MczsjWFY6qCHC#8dT=`-dFx?gYeKYlW$RKWBvnqvBDRJ?@)4VF zQCIIEB-d~1WNVIDe^4R>UdT0q429%b3CWc<@8^kcoulkR#o~3P>^4W)Z=Bd|N7;%0 zi?U$jPAE%;l&v6hJIa13%HFbhHjlCgA2Ob;ARcl%%KD=e7+8s&QuYM9DG~l1cy{d0 zD4V84cy`2&lntP!j=GStu%A1Azht}KEpU_`vLmJYI7&}Nc>a; zXYUMO!Af&Tli%Y|1$*LkypmBvTx56rV0j)`d-fGzmD$1X> zL8mzA-g*s?`R%5PyUEbYxRld&f&K`B?C)huH&bDIeSz@GGdfe(Z0S2jJ7MecUM>4n?&p*vQD6B>a-_jLQpp|6hy)w)%6>_Ww`CPcLr8&wm0sK0LgUDR zglzKZQNOHQH{#I&meSz&f2sDwl+UR@mfF*@kB2q;a`$c5+7p#ic^#-usXe*&q~m$9 zeG_du!HYd}LYhv{o9;yr?fK5fFh(~;l&~A=D7)z%-Q-dRMk#gC&Cuv(Oms6ix~b6( zHBF$V|8-I2T0yJqBv*FFi@mvjLxlP!cas=I=qIEm287psx*F~BzSzz4(ajK0TS{?s zqkglLfzi#{sPMbd%@}1t*jlb9iqadRvN`BnO8>Ado=9WuyzrT=NyOtObJhkw_$>o= z)}mG9<(*GFH}B7NS~xtGQZ9@8n-7ihYFpdi;)v2z`G+e@|E_z2cQXsyHXPt(ld*+f zcAphrHf@b@u0!`3S2b-dOlOZRN@qtFCFfKZ7Ze=pk6Tuhd2>+fvHsY$q7@%`ZSQf? z6l0{i3cfXDh88wtrWXQGogw&?=WaZA3%}+aOnWu6ileTY-ib~9u9q#_1rTpuD%O^c zwT{a4UPjW1KzW(oZFGoU56t%BII%hFXaEVb+u~A_t)zR|%XN~~fcu!I)7dL)JP0K6 z^i!P+{x7}1H$PsG%J#2lAjYUD?T#sy*UnE26O!x|HRIgpTK5(=je@X>C zy<}bt_~#TIx}we>y)9kHX+@*_I-l*PI-OfY6T)*5vb`&^-*5RSIpo*^-~zxogKGIrS~iCR-+91L}0Pmhs)$DE1q+)#_}VpW4??CZ;R8 z*Jd`Tn!dFwHqiAppH3$iaf;bH@nijx703GNJ!1|2X#ajQ8Spsa{oq-w>e%(xXr6f5j3#%s!bbx?bJH5-FHhpxDGB>C~$rnX%u z(=hSbV;we^so&`<5R{TV5!H`J7#P2GtBb6_vzD~d=BYYA{gZ;a81#Bg@rrn=sTI+0 zhnn6Msiwt6sis9d)6L{8;fb81#_@&Tmj2(EZSXa5rRer6O}G1%C;vsm)6Fp1UHtgW zm`85-o0>0Fqxcs)=j)nH+)Ze!46#Qo*)|n*8+`GeGfKAVI%|=%XP%aI zSBy`4n<8iU&dKy>2NIZG2-HK#**~Lz8X;ItJ43nO5!lRzRxqV_LOQ# zoJAxmT5GI6`#f%$2Au$^H;}B4JHLe3F~@5Jri)_w+VMu|xV0LG+>~@M7@uV@l2fv7 zL-*+YGL1*Td-l|51ar^YRrb4=V@z@#%Qq~>Eu)&ol^QbLZP=Bp z0HRx1m~t9MLoFx1f}zN8WgO7anBk1FQT8o()dP>?dw%yh1gE|xOM8f`xV(op;y8_ z*w7<)-blp%{qpz^e~({F`JSgn{8!3O_|~t8&pKm;GIpVaREX0ZrghMc%cV`~oP64ZU9!5P4{EB@UNQa-WmOgN zcYC$*-AHTfYgz*ieF(v@-W0bnSagYN41eSwj(s4C;uYLBzJ#{u`wq0e;1~}vZ=3Ew zexFkw`@v(Eh{K|D6$%{K#w8o}2;=S}{gKn(sZf85YsZ`ZNag8o5)W0*S;ptnjL%Mg zpJjYL?SJTx6!R(CY**toO)Pf2E`}pZ!CCy>RE$HaVLAjF=exhAEC%a7Np9L~)KXv} zHzj=Yd>p5umbR+&!gGfu_wK%u-+j|7Wr1}QgSuBZ)L6!xRD0|-YiK+jbQcgNXKIDK z#y8YKZa{R^GGvZhXR1cUUP0g3WN{2(k|-Wc3Aa-1jtZzoC+YX>zK0!uzelf+NAjY> z9!2g_u1oLT^*e5N%No18WsOAxNg?m4-|0KkKu1Xf{VrbvbyYr-IXYi$?PXmnGejeW zgo7C<#p+gOX4xH$FVfZSP*Kv2BXy9yb_c$#j z9=~X^A6YhoJpnBOb`C+m5l>IbSTDEYWsFYF6TAes2goWpmr6L1Wu|YZkM4#xK9Rh5N18^DocRm79&{4=nr4?qS)7Mf4>8Q3JM7FD))7$i6FV7!a zQ4~D$I99ly`0|OkaO$@8(YRh&FSvYv9$tLJJ#aR&*R-ft@^7sR1wY817Un!6wWoOP z&&YX~%50H4EA))4vZWI-LGrHXl+km&O8Nd)k~(9du_ongZMl~n>SxI@OO-z+Mu(*+1K)tk9^@}zEmvnav>!-`N)@E zReMeHH%mOu>uP@0BRPV-E|q!FyFImq604GTw$=}Nmo~+guz+v=9V-#ep>6pEYSBd*V!Obpr zCj9lXL(0bn{1T^Dwl$SeuTR?8#Xb zIu3lrw9T21o7R2h4~tcOJaw=)ad|rSOndy7qQD;$t9oU6Id03Q)@~$MEeSKGclYMu z1Zt1ZRWbIpZszFee<+*HZU0YNXiu-0(?jFAbG_`~id5_k55LX?FMBc$01iq#uE>k6 z_9n*3-Pen~=1<>;zcs-pRg_r6yV0UkbJ$Ia6vR}$C zDQt*gbr%m_!95&Y%6$csWO4r$3y=<8y3slxM%R@xM*8xd!M-nh^Z0$9b3{`9;6mop z_~udm;9`RvSF*W^L-WV!09~D2ek!W=RNh`{#OT)CJAT!*f32%(pHWk*o_lrrklI+# zFtHVv6^M!lw{g?00U~%Su%fLt!;D?rziq?yX}{v1qN3wi2EEzegonK@^LSD^vqiID z@Ar|*O z&Lu6CJqg#}7VAU!?hjt>Hf<-7C%9f*)tm5oTSN9*eP-bxwDn;_+o$b;9Q@%OP-KR- z`@>^i)52I4E;h!O`Z(#AVWZ1uheNS?1)avb9A^>_o6dZWe6~uM{L14MAnTWXj86oo zrA6oZ1FlwL_7wV5+Kdy9tM{Tb{e#hTN{{t~XUh4%oQ;db=YN#kQ`E1%*ls(s&g{(k zxhfN~5UR^?lH?!!Z=_K`)fnOz4~U&}qe z~q==%e^ z(jB2ZoI^P{vj-iq&q%T1iD-O22h)4|pxf7{5^h>b! zOHORwCQr#>H6h*ST47gXFkj%15Q0w^_)DZA6$ep=iJ>I$EtPYU%lD191dqBh2jrJo zpfXHPw2KcVZwYSVS=ZCtbvrW7%O_)yKs(8ZiHru)XzHDJcaq`xQ;LEURW^^5KCaxY z+n4*k%H@&s^-4$1bMCqwIg|3qxrZWo(Pb#c!T2$yw{HS5#yJjExiP!Eji)hH8R%CW)Mey4FM)Nw7rB4_{ zBIGYtYMjQ@l|?FQU(R5WDi}sY&$^94aF+wUzZ0}Zqv;9<%g9LdW&%huG4^1I{89lS@nUz-c!eS z3He5Z^y)&$l6*p{|1Ux|K}cPu0(pwpIOat3tmFhLxbobuF%6m)GZignNA6p>W8m9! z=sE)WG(p%`;qo}dZg+4mMy0W62(xo>#3tlba>%22r;oP1uW!Q@)*Z#hNpj8%ruEKg zu_iYy_9mS{Vn)3NmOOJzfsepTk}JTdKU(u!my#Pz-(di~jzV2aHcd#*d4a)zMTqGo zm%QiSX>Xt@N?jIR%I7Or+6mH0R}+L*BTR1n$o^3jfE#Igi78v?6`lw~HP+mwNODf4 zYVZ@6X^7X^acG9*0jnll*MQVKDy&=YE{6`Z6R z6eAv@utZg>q6|3zMU(;B(-@wD@0^3SfJxTg%o?%C%#v|pS9r(=>Z$u&uW&rWaMx^n zo++w<$vN+de!uMYdtnhRRJW!lzAf(5&>}tBI?wY5+=dqHx0H+_Y0P60D#KdM;44Y# z%sYA&SncFJ)yVIKQB{MfO5lVLrNkz`}c7O;@tQ>$mj;bVDIm zv$oTI_sxtT4i`_e*UAe8GRm;ug7ej44#lri_1OkUc*ZNNFKUm^qCI-eu#p91d2Ce` z!y@Tl#xjnLI!_;T^QuCj@vCi{4jyGz2`8(-Dkrp(#tC$@GY>UB6mz1Uw%5Q_rJs1@ z4$Tze6A!;);i_pP*}RbXi-gRbB=DBW_qE2EPEk+}$qr;xh!doZVf9g$Evl<}A?e@j zU`k;yUrzlK(#pE5$9f_HyzH2oban!LCKX;XPy66QQZc?l(nxwE;?y_omwd;|ys61i za+iv|uCI4We$wg|4BZC5cS)M;naa+*?qwEwg)WpOMTCH#_$TvlLx!DJwly;w8e%Uh z(q*j*XU9-8=W1(kG94gHlZw2FXryOSG8xDIGOk7OKo&cv(nK9zY7$sD46waCzwUbS z;drfIyRF|QR)i$YE*i8=L&y!W`dH_<#4;ycTu!mtl(r~Vxw0?4?A}aBb2fOA;HzS+h*RyJF@W*~i^@Dd!$2NJs`>4IBFqx%X=EVlT z?$d%58@yN`7jw#=x)@gmdc(fbRVbslj?Z@SU9NaHe)p~GR%AIb%Za%h`91fovoC$c zcjd!gb-S{}**nfRzV@x#C5*&aIPH(aCx-nhh8B=)FyRO1z`7|7VznBb0d_CNpO6E zSIF0rs2t`zkXhaqbn~yo>oua-KA0A3-w=1Mg!W|5J-y75X`6u=l6j?R{a3_e#5VE$ zic$K$mL$iY!ug3(S`$A@$KGm>|Ajs)@UOu2F#TYEO1Gx=ZZ4BXQcQ0!iSh#YK59c zX!PK@76}~O6V`gRyGFE!wY`vE+fiZBD!Z<8ZKt55U4OxpyTs1K?YC?GF_SLwYuPfH zIEvqFtzs(I5~;YL<8dHlxA|om93eV9r*F7OW0LR+M;BGaZ^W-iDY_t!5A=m9q@Ks< zfIM*A=(|cG@6pqPzZUDXE%3^I&V8pzXeF}+B5WLId|$fzp|VL2A?Vo^+1}rG73X< ze<9ua*HyC}x-~*~qd*VNq1#Ni!JmPQ#<1LdR;`)|B^PXU?JWnvz zZ^R88R*;;1r0L(X!+wTkpLj579iHBX1Mw3#t$&YngTfS3*e@ zr^!OT#>_w#^M2i*&A{U>(Fi&(_OG;mb`Q4t`XA^P{4}}l1}jtJ5637tBj#Z&WiT}T zaTPH#uO}E16E&qAhVKNndU);|#YJMw)MbBIukZC0Xo;t}xE5=s*4#05**)qq%jz;O z)McLItIIDCiuz3*<_TV!f%X1X+X&c;rP|iU72h>SwnS~yHugVO6NzCi{fRin_u^}y zd##fyV7DUL{_kLBO7`XYj)K;+paRy((K7)_ap79dK#i#s#h3Jf5IQ<%b zOt+>sY_1)V)K=kv0p5^>7=RX*d<<1)p0QF$7zwZ9Vvh4wK7s1uv&mX6ZMFw}Ows#UsmnpOVa?lQEtyp#gd6*T)kuc5@ewkPJ z4hn;D4*-@TrK1IK3i;~iwmwmGF5#}}nQl#6xAC03iB~V+ zV`VF3_>7=Pjj6VGx+&31u?A1It?Nd3nk7u|{N6X(z91Wd6hNYS-<{qbF?{vG$R3X1`{h-h42Ytk*arlYZ`ay30O;R~oKR<(HAN;W&w zh0|Gd6rRn9D&*{(G%LXgbyZ9J5v+~1ubhcjbX z?vVS+$#@sF){pXP%TCqW6Z27P{lOsu{mOZ$uHa?Tq}J}`3iIxiv&+0+XKIr66F*0J z;S_3Sa5FH^VJ(y`_$Df1OW>Q0lWXwyRblQ^}jZEBJZQ$P`U8sTqu)Q$9CB zWhi)lb49t)%?e+0!323=t#rPF7?V0V=MI%)dE)ARyh3j;u@|$r8S=0dYSc}=EUnKi zBAGNyngIz^R@$$=i&=ph`+7D~+xxW>6fn@{|5SEHjo0*H5o2x$E`Roo54VQP#d&fO zuDn8wqB`Czse}LhsQ_o^7;U!3R@JPkh|ATD^%k zRp|Aq6cwV2$1eHEOvw%DY<-OY(|+k?v{=DB$((glNB*EVzy2pU@TSfPqzaqN5LFGhuH;uOa|K>zDAP>2EyT$DB z$kf(b2gx~ym6^;fW|F`ih`BHm9JqVfH^N+vYoD+md0w`cOQ9ts-NsCVw=_yZUJ?tf z6a*q5JU(uZ!hxRRxq@drxDf<$n79Qb>1=tFgk&=;nqMoYenyFW;zOWELt3pCn+Sbe zBCTI+1xVBY$0^LaUlLkDk@$cmrWZq@>LwM3I@>PM28LuQEIOZ}DSx^vN>@1qt1Pwq zqRjFYcr(|UO)qObTYB*tg;talrZQs-38pFGRiLrmbQ9wyRz!&pT?tB!EuirwyuCJd zSKUCGN?4>3V|vcXZ9 z=pq5RBJFB_jUKdH8nw|q#uwFvDg^6)SO+AkmXCSu6K6p*%2eEyQ}+ zVKu2NLyeBj9x0bPSRN%qYE0J#zdPC;gMcU?;Vgpjxb|*DbCJ_V*7GJY9bNJ z8(+u3d@(w*lY3%?yRP#*&){mOj^mm`H8jtpy1zA z3BO_YO)D&Te8#hNyuBuFpTUCSjI9{io9VuuNp3#S4gENNEo1Iz{->!2ds;vCtf)w~ z+!!v-itRNxy$;9LHvdk%c|R_ETP_qJWk^o2%$(yt*>bm*aBlmp8MkQXcAF#{OTm_K zMbX*~u|5Qw-HfWI1GDsdjNpx2@BB$c_E^}L2%F&7k91SCV7QyyJWK_tBmgDZ3sh3O zmTPSiSreomm2xrDNGCXKBKaKt?bJOD)j;JKT&)Jr=;t}OojMkLj}#q&>{l*D*93nh z&C9HQ$|}H4O6u8fw%69vnax(QjE*TnsPID>G|2IoV4_Mw;+0k}2g^Pj7Fwm6EeF{+$k4AKXJfnwY|BbuX|kmmV2D3$84gXI*D9! zC6D+M4}RjuGjcvL(U0RN+PuHHyt|A|M@XM6nAJv`s0`At@{!V@7E7OKfFLi12 zg#hI>cBDV_>|BGRM$*eH%0fC8{gEz&J}7%jX6>Fv*JaU>hFgNKDd72+6-WNd;KNP` zi{pC33QX&Sc+MqsLM$LbxXmxGzmD%= zY4wowzhj=?E{(j53^l;n?1|SxHXC1qhas0Cv{X&v&2r+RJKuTiI2H<=e@)IOz39Qq z0sK7I@ezUF(&#K9&`#zVwC~JyoZ~WH@7U!P^R>3TrV8+`(jqvmO{VCan{d@MNc51^ zxm4QDy?PcjiXRh<)^BsKULCg5nspdO7aT&HfMcZn=?zBO=n&0*LgOdatTL=xP#a@l zP)N|-Z|0V9*9d7B+Cn*afv7Ff^gLIPwcP65rpcC{?*#<*+cjN{MWQ~8a-wg-)@#|tP0R?=Nn^{9em%RBt{MFPr41?U8xS@-l zJCk^4k5|yW*nhn9KXck{VDRS$mFm9O>lIEeYH1}dIXm>h(2G0mmdLi@HS!sAKs}q* zwPTAz5K6Fml4^p`8+eqeiq=*W!Z;VDqw|Y*wU~z?LZ29`0ljt9u=oS$o(zA8;N-)iN{#$%q?2*BsXZF=Ivrt3XcE^Hd5V;z_V z{g*2Ks%QU-plv2qvXnDE`la6k0#RL>k`e4DPBc?z6oA<3SF-ZyAn}{)!5TxA%E1t4 zbFTU#QgAxOmy$bydpT`zI^b7o#Lx^Y?Wv&X3RiJOMc}DoKXHkQ`=y6+QN3YBWb`sT zqo^}ilT}}R-K@^aF5`aZl?{i0;=!)A!4<*k>#VjW%BM0kqPmJZRjBx(DT)S>0QiaT z8A3%M6R4g>AVj=8yz$MNPswu*CT zDX_knY`2c4eW%h8i-_|R$L89E(Y~6t^j{wJ{=yls1qxVhRUZ;^gqcBI-xxvp)jp7CmG`TEz{T}_)C;{s zL}cD_T~w8$J)W!W3gr-$mFoq_32Rf|4|TN-tq9(_)@qxr@_uy4aJ09BTr>rpom<=V zb*VZw+58rX-o#BZK*KJ^RVg#ZdbZd{O_F1DBLN!|d^!TgpdO@dbd1j?sVa1VTp|j!n+ydiQg zq>_*DojcAurx5pTUS?U^AD2+T&K~vI_@C=F`z|EYzeIsC9OLoB+U(E;`V8tHNj=t& z^SZ&mc|9!wkBBmjJv%bn{YE<}z_{#;+Tfa!iIkDh;k7%%Aa0F2luZ^Wxk;1hg-HyJ3z|WdEp3lFi4l4_Ze&!H|xJwIe!llSMFj6IT;pIT$ZN zn;SX2^Wl$O3?Jf05UE5WDo<%FFG>56i)5-p7-B&fu{2j&BEC=-f88?{cpt_BwMuYV zT#znOZR5f$0W4|}#%Q44VqCfU!c-}=zvx|s5V`>;;&Aco% zqd#ud@p{VQMq}aUCk9b2jL#mDoO1$eJiYqkZKyUo5dBQPhrhkBu_zn=715{R6k8ix zgmMx(ym(sYx{kWo&S-WX>DCmf3MaRQ*YK=3jyTi z7897|yWVHR_pId%F0`^tB+Zeb8M5EYIWwd{zRo-|MDBvfXfb=|7;2F@Qq5Ho(MnA` zN96#O;T02_O!%%scZ%i(XMFH)Or*X7C;t1V;d)5~Y4(u%c?*xjqrqNbMK9f>3ZViv zDaLcHt{KAh+!9F@lG2R|#q^rsF3N|Y1MKZqw!p4nf#LWdxAZCDSwq+@X#UsIXOc?N zOjieD zcOs01!(eh`JKZd>$euti=%z> zE)3ZnhUD`hYBPhgv#mTJ+9BP4xjVNYvgOU!JbQlL^5#PlfM6b;R*XE^x@d$yv>ZdO zF!*;Tv@NHeHt4+N)Sp~J=i=zsBuLV0x#lg7Mi*;wv{+&CERGiTsynKG-r~sZFeT^g zX^W%8t1Ao#4b`aFOQRyIXt=OV5@Pjq@Z4`G$H2tN)8iWLzrx!q6*%VtP}Za~9|T|4 z2^VsQ?Y@R`r%*0fPon0^DK0tq>?%Fytz29MAp!e{fQX;dR3~gwTnq!{jpspk3u)Z1 zMPcQZm3O#u!D!`uE9!moQSTq3R@e#XQmCEaM-KHl)ACT)gs3;&)wOAFsA+r9w2n7; z2{>d-ViZeqdkM4UagJ;@7Qu!z+s10VpXhd})U3s|tqJ4W+J{@;$z6lllDSywbb0nL z?ytR8g^y!HHdNR7lW^oYdq3Iyev$Ob`Ysyy(iiY8&srpiVEM15 zbd$}mps?#QLDk}GpN5hv8BDM?1NAg5*t$DGiDrP2bMp zb<)2iB~w^( zg3)%g)ODF}O=q4POI~*s6IOaq+J~14@(MKTrXY>BOGaWaD)@aM+Y(9_j<9kNW z=ep;8^g6-=@Fz+?mUK9Hw1=hfDCz0U`%%^p$&%47+n2YIi?M%WBeE6u+tOtpGTGAT zi)nr!=i$w^^YCJM5DhU7#)-_Qkkvk*lXGTH*>&V%L>xG>`+YJ zS8JPw&c|)>w3S*hylLnSJUwRlH@Wv1Vw_xMsdt2_A{SSDnA)OLzxyuXNSLwVw*4oJA0Cmj=!iml{nE>GnKx0;fA+KZ=- zp&YP~RQ#FgwNB+XL!$z%VOlPnJ#u>O<9ST!LyX;Wp50DdO|a+fPS?Fb9^-l%Ca_bO z9Z8M~#}la2QQhl99lz!Cny9!u+dSGF>)80bW#yj72jWZOraPoorFpZ7{iQr{c*`mh zNv&d}?-ZQMG`2X3eNqxn9^ zfX%;jjoqj#YcP>u*t$&HgFvGtotbY>Q8dq*zH<>gTTL2`>t}wxEuG#f+h4=?(iyt( zWLV)0ca5+{goSh;PKCiqs%UUXkYD*Yr_=?Pgy6?;%`-aylTTQG!Bj>lwEXdMEvNh3 zb`jI8W}7TKKdjigyO`&{Q4&2rk2Nis0tdxyn4-$e-)Z=HfP1e##7E2|Eq z(jm;wQCM?0jsA{q%Il1yp*qLyrrR91XK~G=J{V+&5qBCt7zTV^4?M}-mg|9-BPohWs-S34Ch{1D>RBo< zQ!6M53x+XC`>Ei6Z&f?\e`4l_l`d#t>4t{TCa$V{9I|e1~O;2@P#B_o#(RbL~ zdqN$3`7-Hz33126|Dd^Y93XBtsBJX8OCW<1`bH%*izvb37X)JZn1n8|3o7A7Agff% zlWWA(F54CFkgi?ER-p`c3$*k#5nA$dde?m)Q@ZkuHaN15G`0Fsca2~|fq7TxBJkM) z|GuRN{8)kC8-ic5Q}Fll!99WZ%Yh#w@Uuhk!*>e4J|BEHfp-R>4-|Nx5d4#$h0^Y} zM?&J?&j(*dk-TuP0|ma`fd!B66gzp;f`5>jVQ#mAK`RG+HfUS0o?EhenuM%lwe|>i!E{TlKAn54$(cOK zzoui0{`17PZEgd0(7PRD{%$k>CYtmUHH(qw)>%AgDOuCGh_#nKQCHrgU*U`Ku;+afit!WGEQQd2;84XFh)fo-ugijm>3gWC=L2Gf?8^;lty*zmwK^6pNpG(|}N+$cUAwm_20#|$~ z(blaXew)&i>07lTdE7FdADd*`0WT-}_18(816II5g0o+x_}c_$FA9URiKn;V?3a=~ zMcy6b1@#I|N!)F>7M88YS>T7V8tNW5oF6+>p~p2^L;7WPRAzG%^jk!BNcW*jw~xX; z608|(UJZAMFAu>v55^)Xn>oiBYOp^MvEK;@T3qhNoe9b@07Zh5dYYMJB{PW*0joWU zQ=YbwQacvAXCOjt9}ehcn9DToyv%#{8Cl{a6umK~ooS`JL{6(W9vU@~25eKR>~?7po-h~-gA{)6&Alj*IA21q}z4NAxhKQF+g=Lva!jq*AqHU)TimBB6YY_7&xnNL8j9)ok z^*$bAx!z&9W~W$)vh2iiLI^R&L8NvHabP|~xk~z#hftqQm!f)Th-G)n;{$kbo5*R^ zBeMb1XFf0g^h21nep*sct~YyZ<6;S`)cYtn4NE8Sh)ik!&WfigoX+-H#4Hwik~q8L zww)*8Nc6UMm%a0@aGpPWc$r6b|`Q<~am3Lib zYU01svCR>GGVL&B=2fxsZ0SFqPRg*}MyxsfkN;Wa1~@6GGoj z=-WriUMWyAb4=O!=WMYPG4>ySdq6w&+Ja3x()?q$4QUVDuZLfN}cWJ;ab zcTj76%STYOnD-2mk1W*te0M!VN8pjUt8KSs-V+<|Uo!fLOl^TzwKRG29gu<{vfg^@ zvzC?K7NRwi$>xo`XYc9T2mUc?$Y<7&WIyDG)_fCOe*>-YdprUdje!S`HT-lI(d^xpe*zOE_RA$r7OzlDgdZJxhtX zPW%5fes5nOMB(@yK07yl^~uy=GS9jW;>x03BU277?IVT5*=?|?%tl^y?HtYhXA|=tesW&k!;_3McSz-&b93%| z^waUQ%YwahNJ{yJ62)`TG-g>q z1~$arAMN))BHVIL$39Z%=gMZ={b>0I7)Seqhb~}r7DQOi5SG|yVK`WWe|9CzSRdSF zFw^uEg+bORYrEe=aanfG8ifo+FtxMfBVv`~lHa4p4kbr*mi*UQc_r8X9h?bh%Hb^U zEO`j*%HeE_O42M>`)5tAZHwqSn-rWpqx@^qF`T!Xvph4u{rK*<%}1ptrnY3y%b5&nLTbkFiI@2{r)&v&s8+xFG%D#tZWJ)5UZX;OpEt2Byl5g#PVQ4? zHB25tT8RC;@>J8%3MTWh6}?hgLa5ovmIJ~{9+*WXny2+H(8ousSv|Z)?K*Nq5i!fo z9O#CftJ&?ThbX<}72&bg=_Z<>`GOI`ak`hO+V%x+cJCPCmv#AM7V`{2ohAp;?LpmD3)^Pq4{$fQfTy$FU-Bt(Uo^$Wh1nz6I%i z>+MC2A8>qeKIf`y-c@c^9_`i*fN)$)hJF4wrWqS@uXA> zVo)ezE~b8}Fy85WmhyDw0ufWhTmL<;_Q;xGdbEAmB&{q`ZSNK$z0|xY+4ItJD(=Aw zK{AXZ^GIPbV!h01h)su?Fs+EJli*}M!T*TwqF~W=M)Zo498*Q_eH4bEvN!*bN04Y~ z9~R2ZX{zqKNWzXajRu&VwcsL$_w%r`gtwQ&+o$DQ@t!5TBLuQT3!Y}K6W$Vs_rN^7 z$00Ie>ws^?d$sUhEcWbx_p@q;_sJQ?hm;B-T%va&S?ZXVANV#t7~4zJr z1#6#PM*MImRhbLv#NlBlPJ}6Cx2xZGKwTfAzW-WKhY0IAlT=)8zhB&N2vbj*03(j+ zE~u{&>KRf$A!_NBbY>z{%Tu7$Upf!<948o+)ALYwMR=JI{$!^JD?@}|PVc03H;1t7 z`ydpe2LGH`$Rf;_i287j>g34js%0cg>xgWdw=-h)9ijOBLbW(%3scCO^T-vmNB`OJ zMqG&+p!;Oci9-D_uDcyk?-`;#GOq#ex~ca|(E_i9L%iScm}`$nc6i~mQzDw;Z03k& zi$F_jp+7L^6w$V_glOTMcd*LJg&#|4ucWkC@bkVsd=>j(9(XBH^8F zc*`D-@FI85kOiX3M?n-ZI%0)ZYssFMm18oE!QgpVP2f*2+`J`j`iZ7Lb#oT2CK2V? zbiJY6`AyKF1GOH(6r-_rn)aCFO}7h_$+_HYiO@7nl;aL{#_bf0+`h*VcFHDxFI!GT z#!2i$S*x3fr!sGVLQMu~sQEp94IN!A)n$~jvnz|I9f2Ku#r8E4(&%g*qGEzyQ&^v= zE++gXSr659sAb$hJv`xsUbq)pz?T}{WV7@#1%9gnUCi0z!vfo6r20Kp?SNsRE70-* z1wNx1I(H4X_>XSYds%+MWL6HzPG^o*`vf{%K`+Qw?XJps|J&KR-)6Pu*{F&_!Ax}q zFw=Zw%?6vVG)cSXR3r^|Ao~vLWiQ*)E39SR8|^#n1uM4b3OKM)%d zX9?b~JY5$Y-4PlN*saULutRd};rx%nk@N-4ix~X}6@u>ZT=Uio!#G$$ z5}XHXJ(P`K&nTEvEQ`fYyaD^WjG>C7`5Zy#=;;{E+QQB?t6VYCIy`LnA{tI@>iWDE zsrjprwrDjZ7b3$=MV7Nj(qDK0ihO-Csp&cspLu*8qCI|NUI{wzEzO@hNk3RqZD%?% z!;vcO@#_tm_m52UA`!`xU3zGj&Os2eeJwP?iALFGP@{grpFJFr$jQ~#X_8_0KB;}N ztoi_hd5fvFF3UR*MBrZRk`8j-K8q4MuG~r$kYpduXgTw{mT(#5+i?Ibewih_;zTcG z?HX~ZQ^Hrs=*~$vlt66#2pHg3AFWIN;2Bxuy0>|3Z$tbwHATjH*KR(dYd3EQzsCmd zlp_W?KZ2S=n!d`T>HmK@ziX;mRk=~Kf4)lD$5YqlB>ia>L(->lts@Xp%V|0MT3%ry zf$~QL?^iycOFmbmQu?D(KH}4~2V2Sa5Ueh4j`DPfE zo0$CbI0%J`KN~JN7y_>(%P1)GcF!4kAeAvk;My#ks0#f1tN?54CKAjoTzt&3{E;7%8QJ96eXJ_4Elx)AC!cHBeT8dWqbdUGal+<9FI_ksu@_DeB^Z=ifXHLlx@-U ztJqJ-FW#Tx-RcRXOFpupj& zL)ikAFa9?44I8Ni!Hbue8n}@RHc(e_;>=&@djCXy_I5}EpMV|REmIt>jx}FS>_}xs z^zzzUWuNh`1EWY@i^Zw-5zg}<2m0%2f~Ird7vh~FY^VRooAG8t@{#xO%P-_@r~i6Y zOOn4?=(TM;28VyLd9c)8?wdq%Ya>D=@nxc~(^YHvGLb$@v`X%%Lr`|I?PLJ3v`)74 z6)fYUJm+q&k?qPtTQBjA3HDGcnf}I*N}tz-GWC#gXO%@HMEvie) z0M@t%8-W)Lp{CNWZztRB@JK8&7mVS55`MBFa$Mk0O4p!BG8a(oFe8*hwzv)1SXa?2 z!+`^fNpUo>j1_Iko+p&c736$N#D z!Qv<89EV#^-Y4j-Y=B;2-oe{6wW1sic%LfZ&rXP%vzj|5#odl4Odw$At;e=8aKRr? zai3K0fbVhPEy)_MP%pLa=J}V#h?9-pb9Q!d+8;a!Egf6FE3MK#u7_{Z+3KPH@^?Sc zJTUbXIW3))A78K6qgd0iBF`txN@21cnc)8^LOtt6xM#oqYk2n$Q7ugmw zp(ok$B%8)2HEod#De{2Mg2Y@$U9DmqVa|E&pX55nxnaAx;aB#HUs4_w$`Hf+GNr>f z*C@o5ZoNx8T90A34=wa{%SXCwLc@HcU=<2X=OgAguOgZ9w!Eq##%p;W!Xqsv-{s1F z-;z{jajNaTZlQpE_dDAO*s~Yq(R~L4p_5+dX-xf-cAL{y>9#?K)SX>X4xwiwfl#$o zY{Ui5EDn9!MBfyR*}vSzE-K$!6ty&w=B%JOMu&W-`M%aF>eW(uXg)DDBx*!n2p(fd zjxyaC%RsL^ZNJYE--dag5c9eV^P2f~AH!VPGs5gdg0Ee5wq7T373EjNc%q^`ktM0{ z8nJ~JQdPp-Q6@_>_7WS$czVr1@7B`pnvn4~P^T1LjT0R6xXb;hGLwSg`Q%+?MPX;I z!LXq${#&iI#Cm=Qj392*WW_V)b~eEE3%~4gK=0A0TBE?|%TddAW=PMZp#6e8)(pzk z?K-|IOJF;y^MfkwK~Ju}^lo*G($r{D=nE?5?Jn*s?^A>->R0-Y)UmShx-S;n^y3?j4zQvVN@`o(G9WzjO*U+wena|ATVWQ#RDqWBLzO z%@onaLHo5jEYIPodXp`;0W7@Foo{$osZcl>e3#WRc>BCd_#L=*g7>U)Na=I*&hUPI zpu>Ba!&{(2A>J>@0`GvE^6@%V#3a|1@(WZ$;g33NkT#S{KH2h|)vzV#>1ueZva^Qg zT@BSo=GV}LBjy6WFb}Uf$8qGrkn$(+t5f+16$&YT$l)zrNib)`kx(zlQPib|6GZv5 zB5DVoPY-K2#no_M9_81%8Y-vc)zB%@U28CR^GM9P{2Cl@js=az*rec-^Q;x+Di*e) z!7{bf$a6P8LckxL5)P`(1hXZ3p5|%4p>vktTfhV)SeHDSCrq7PvWGQnOEAM#n#~iY z?yh0g_k%gAw`+5(OSW#;9M>fulsjQM*x`LKuQ40Qg6`5|z7?-^MC(yq+2rsp3Gu#g zt}*Ej6$+VjHy$4hfj~)}Y^q$Pu(&S$OfTfT?Wv|~r8w(DJ$MpQdNCiM()hYiRpbg% zODa=ekZit?Y{)NDY%74ycFFt%g;yWx^)t|30}7ClonWsEvG)-62rvrqp#oM9(2 zzEWMWpCjzUXk`w&x)b7{eSgEgC3xhVJnRQL>;v8+EH%n?VCk`XOD)bmQ!V8WE(ypUO1!n%X_>$6MKwH0^BUC0ly# zEwZ95$gzYLvjrL4aW*_*&v8o8N{CCVTdi^X4(*b&OntolEkce5Sz2gqWuH4K-0#QWXs&WL@#XY zvbpDG*Y_q`PuiAHv&wNK23w$R`^JvTncU}7pEBXL5Gtg|b}KT&<(N29ZUAbjam34l zWBP6%?s_ycyw{8#HUnbMx60HKb;*_=Qc)LEetaGkhl>ihhB9(gz=r{cW6E>IU=p{c zLQt~jg(xFJdmY!PIN9?Wl+lT>rtDskmAAD-L8SLTJvH*S1e?$5Z1ZQNfwJ;I*G4zo za`U^_W!K6!nTpb#sNEECA*h!b>i2`&@=&jIsLTF#ld;c9Ko^9zpY-aeogw^Vh_F5n z;a?rXKIh~kbj@cmAzE<_6h%E1?kUZ$R}T%hu{K6MgM6XKDrzw9KT9W%UF*8!5^#6< z+VAr}?qt%%uHuB=9E*CT)B5eoq~YTKLEG`44IY?O4H}&!G8YPhi}LW-ScbO4!!ED2 zeM6?p{cYLnb|fVSS7)I>qG!#PxM_N`-S}D-DhNe6%GpWZJVkMs4MvUB3tB8Pc0`UCyo<5{3+QAg1_R_PdJx5yRv^+b{rn*uwF|;{4>xluZdFY+-*5pljP41>F zf55dKaN$%J4m0O-sQe_OZpg3b((;{57c2L5Rm@Zs(PT7OtovmF)5vCt?P`Bwbg9!eOGOx*7GQL6tinxI9La)$v1Uv-cwv| z*VdWk_DY_)?l!bXg@ZL{Kf{{#xJq=Q&{RSrk8q8wzC5oYeK|;L`z~!YiJu~iqU}9} zq@Z1YizkMPr%-bFxE1o8YV#Ya}%gjn-3YrEy0lvqfONdF)cvT=K|0~ zO0%mTo``^zoo=g*?GbJX5q6wz%{PSGNHYZffO8Kq5(n&=k2{?HO~K}(k~}llLUYN> zoI&$f3XiQbvJrM!wXa&T?1a!1g81rRw}^N*#AS|om}7X{etNJ*n+(A&m>*BDy&LE2w+fyz8j>xOsG!Tt z_~+9?wy9wsVRi~OY8Ol&0s5#}dZBwBa)(`5jOPQwD(@#oROeKOear`}+urSlUFWEq zPhl62$ehg-y|QzPo<~((2Fwxa8Ymr_O>O9$VVe~!%4#$27F}~O3 zv~nH)GGCYKnoVrP)YTqWD~}9L<>)q8(TK~_y|wy24)U!SKfy<&fovSA!2+|j@5dJ@ z?R0X#1SeCXR$7BY_Re2vDy^_MILKfgckkxnf3Kq4v3o9#eq-<-5<~y*dTnNYph8^l=9+cLv^TQ;ZFBjK>kAY7 z9w+INzol7Ql)cI7&vd`OV*zD5-vi1ZQxN|%nZvoLiB-_||C#<>wwk>9%XNLO--oK-Q*wiG(7%ho_X>vu z@ArauKQRTx8}7C@{|r3rQ2!25vUe}?Zv&=F+UIq%7IH)un3}H^r}ybsVa4x$mveu}@$?N7AR)7m7lD-l74JYxj!0 z4$o_{4v<}{DL9nX;2^cjnUp4ur}M0K_2e49xyA8;cSGk2=^VeuGF`gTnJ0=p*5vv( z)`gzlX6Q!)D6vTPF5O~bJCBWp27-G@c}sP#&~qM5|I#x$JmS5|tK4~u5txh22r5nd;HkJUv_ZWP&G;QKUEIIXn*Jr z()~UN4kxwa`e&)HZ9Pj5+{PWxp_%lJV!fWWF-U9&Hl4RI`h6UHK}8*Var6P*bk87- z61}Izxw-$gr0XoHuL2-iK6FW&2CG!LoqqG0OX_Jpl<57zUqKc#;ZPIv@SV=^1((FG z;lQxY`|k;^Gd|Weo7fJ?BBPDn%#PTrL4iADteTH4# zae(nRar^i3USqf+_n<8b5MfK%UV1Ul1NF>R^I<{9Kj`cz(VS4ZoPQy#_021%?oR(7 zR|Z2evF6rf^P@}jshcNFy>{Ho16-X-eR?^fGZGUl<-)K1604B!=k*%ICy>qW;X*V! z?xrQRyscN8S;;GU^;Jvjlj*jO&F$N^wQS3*N;a1$;xEF~@jjHw|1^O~@^!itZ90@e z6r_&Ved*q)Up}AUS3WJd_p6I}4(gQ$%oNh^cQAdix`R@Ksl3%C)iaudZVpXPP#T&m z9h%34=9@8AMIYu4%NytN7Nbjpb(U9|a;R1->F=)iHtwzX09X7o<^4r@Aw{JQW*5)~ zO%CRJQ5B!NJUs{3xhmGv`-~CVHdv|0JBTq6M7x97q*@xRmRl=kstf!|$qis%D{FrT zRvv-Pbzu7mdoXUNzIXd~^9Hn0G%KwvlW7<}S>j~w}usUvaCzbe>Z(3JXFHzQL2eu^Y{Wb^o zjJj>4fw|`V!NKg#hz<62Fi%G?zJr+~n7#90ra72bBp&Y^Yb>}ef;rW}{7f)wl!tK@ za{Fip_8Wmc?7(h{z`p0evI2V`1iQg?(yk6{p0cJnum@=&%=^gY{9f(7%yKGM(^F0s zS~UjhUHRWp!kG6D2QgI;wN?%Lb6~pHI=}iR!Sr-6S4A+h9ZZd2dgQ@Ob})^Cd9%T| z&=A3#=wQ-Y!{EZK?OVG zQ7=%z=Ts1#e>>MO9`#m(Elozm{ml{nhzK95yv{DV!z7^kNoDQkz}9eYymO;ZcZyn4^?ya7E9n2Kv{W^qEA8oUK zsSYHmKXEXpMdI_0!`E9fa=ztNE~j`}CzMwIO%O*ph#y1{k2#3L1#v`PEw{T`t{2R% z4(6~3=2{2yjq(azEf-iV(mi98`toRNeKMgy@Ehg9v0_>ub97021d|<1?+E5SmnSV1T$l&*FYCc-X^G${2O~yVJ&)z#JHqlR z@1nTlSXvOfIfxeSsehI$FKra;8rGp+Ip5VGZ6CZk3TNm6byBT~DwWTP`$m)IoVb5A zQ<;;U@mnq2MK1aXYK!nd#mSU z2eUPMGlyM%p|0m(mG{h+u|0mYcRQ4v9AM@ofO>Wzy>fG8tL5~ z*uR)Mf}dGl<>%^z3?C7wUZd2r9Yi96SnaUgp}YxJk!#R1*00qMDSe=Wd4qea<@XN8 z@b%Awnd4xt5X@I2tU)=LOC5~i+p0VmHvz_-=3xFICMIoQF> z7R;><=HLiscL!tgH`ictjN54aQawgsXE?ANzh87HHERZ^=2hh+rnE2j(p@VrzFq@SJ8){&~i4Nv*!L&J;6%ou44raMv{%J6| zCiQk;*9z=L2evE%D{x@X3hbw0RpNMHy;+?S%*hUBNd)t}!}klpoY1wZ#~j#R0z1Hg zoyWbk>K6{|N6Pz7Se06Jt%G?BsSGyM87HbDm>)ZsZi0DVc_AlK4(36@{N2Iq9>EN7 zFuMrmFCmPYRO(8fw1U!}}Y*`5!8ozEu?>{r%Y36d5=vfY$8U5RMmqq&9}xXQ{U(p@V1 zq-$l#{K~!>Mr9Q_&HnQ%sI1q{Doc`>XWPzE!HocmfPZog37D@Wzj`=Q%DHfp?5Xl) zy2}Z~Xe2DCQEI1+>!h%{7vm}DV*sUZQp^~6hmC~lmjrg8%e%sOTRF?+?9NlLt08oT z!1*Q`)%z>`)mjl#TFt#-Yj7~Ha0y;i9vv*>q0+&uSNgpUrdtHFpM$wadB4eni8+`* zD}AzqnZ~`<^PbDQSa}y33`ZE?hWRV$;e`7;u{@h-f{l@rMcp0Az&SwWbxXxGFwGJs zxP6>qOn3&my^H4eVPBh5=Kx{(QLb}$5tgGuEW2?H`z)>`zqCCf|6oV{%_9Hd8pkG$ zgFQ_ys-Gr1n67lc^ri^rW0!ZjV6M!A(K+bILsl@JgZV)O^OS=*L@;%EFu!*&rwFFR z!F^AF_}=fPa+U=C9H+GDyE=oGllzuHqUcb>kSaMY98FMNWVROYkVlk9Z3 zk5MRgI$U4dmE}Ve?5)!^%YQ1$`7)6n@gq&KE2sb8S22X!v`=_2oe2#E_h|Qq=W@BC zCy`)V8r;w1o;-E>1YP-47Yk)@0aVtu?;?L@ZEHC0%Qyf?2`uN6_|A)6Tfv>8#{&*hA!>HgxMWqTF zC0Y zSd8@9VK|35P(u6OHUNmfTbRk;ooM(44r|Y^FGUV=B?|Z10D{QF4X`o@{6$r#dUJ`E zuUDl`;7J+~$wMueMtPoJQ`+5lg@wTa#qc~^m{1K(nRKFHu9PZ{X>l`=-Rr($qwFuq zk_&-5CF(zrvn>-(f&kB|((I2X zzpv`^DSJ;Yqx%l!OYIV|N8VH#<0=a3lszRcD>L4zJU*HJ)^OJxv|9A+!C#wVa%T^M za+i!Lse5TKSp`9jbM4cd8z_L8A;1VeEb3uvj64?9!0hL^MCC0K`C+16^AiOZlISPI zF#}@Ha@m#ux4fDO5iMXyBv%GI+1!G+2Ir_!EL3KNxh~;@IglEJLFFIHb+rW!{?;PV zwPB)b^Ap{pM7O&{zi5$Yc9`g7CF+^0^uLtoBA2MDMWXA%M0-1co;;nF+nv{Ne#z*A zJ1>wvkQPX$KckKO9`DHjsQqA}VR`nDs?bb)*_FilObQwtI04u^t>Wbs=D&-_A>^8g|5BMt@!M^wF0&^hnFU7(GEZzSR}74DAWx*E zJE!B9Hmu-eoKD=hh7`K>O8&r7+~KLQ>!qtoDtj-<&Yrm7ZD1gG}PLDlF&*~0;;U%T@wMOhvXTQ9SmDc<;~6HokmzR z*@Gvu`)B~B5}xIciw4iz`xJ8I`8gXNQ>A;3Ppn!3wo+w4)o|tSdEB!5@_%@L+=gG_ z0Lb&$@_62=@riNE$0tVf{mf6tCnhK!n2Aq~PmFnOeBzbPW8j(bi4DY^_bPvEe>syh zV}RWN%*011@zl~XLgWHg{rR77tJoR&@@KZJ8uB@Bohz43lHDtRX@CpMZKKS}T$vTX{{NJDbgs;i|8HfE$(1?!zf^8i&70H2*AYWZRumcY6IA9P-VdO!k3EKwkvc^Kzn!z zOlwSBHIJ)c5iYA^X54H;R>54QkkvR=$Aq7)f{A>#Iwt&V6ini(n{4XrZ+W66j<`He ze>m0oVpMe&`~;BNB~s{-u6z9K$`fDGRrlMZC*NJYzZnCkhQGfi*bY#(qAtUUzw z;VGY?xqjZ&?A+FB68$(Va9eO$R&dn|J4mtZw^L+_^UU2Nf#afq$7A|p3>ZJYC>nVF zM@-I}ZGqSBsA>8h3ocXktUpoq`x{U*&A|PhJ4dpAo`6mFoZd1$P93du21oWCg0=m6 zD7ogMJMCdWPf`)}rB4`Wx~ec$Hj47U33$0r9fh1h^Hc+*t_}RI7j?qqFYFKreA_(| zm;{yF5q8}YvyPi-((bqmhsiylj95LEVo}g)DlK!CC6%aja)0|AwR#n2{`>KRD)e5& zg%a3ir(yNnPa|0h%m5*aDEVgE1=9TJ`ur?!S z(^O$(vkrkf(^Hwr6<%f(=PwRQ#XddK@7ptX^y0TVdhx^qDctXT45*p2Xoxc>(DXM3 zmYJ=tN>l~G{=m7TY5H+8-tH#z=EHDOv3GMv6?_+TFux9jsh1`jWOU%baeFtO4cU~!gxY{SQ`u<=68s1Q(AAfK+HI2xV{SWr68;8IU zYiWQ=!DOH_;ZfVt`MOTI7w`H-_(uJ6KoV|>qjy6aRsdYwWU(>@`3BA`46F25~&`ZW>EP832VjXuV4=hy5MEX|)F6Y2~n06kt0C(Dxz(@XuC7e8>QeK~nwi>kYu2 z0?2FDCmg`l4F=%BRsgpukmwdmf8e-D$kmUOH>_KtEjTEEVeB>MmbBPnZ{iBW`GwoMHH!)-K9`PoSq%cw?l8{TkzL7Y2QY!%}ORV z<@VkhO}wnAv?o9A+bt~$PBGx|1&N&AE>6sPkm3-a!_Y6`eRbOP?e|C`xL%qeU^SLdl%%xDdkCb7T;ju3{v}ONrJ3l9MecjJU=>x;K5X`OIdygZ3 zlw+t@%!#jm-;YYMj*f%F-gIXKe;F(!u}k!YR*B98NLS|-C;X`pR%Gs0Sv%NNGEvX1 zTu>Cof!owpa8Ci^DGkYPCGpI9VskV%ZGOK>z<@9ijDw*=u!^{5ESiD?2ut0G8B*!5 za?BGDHrwd%d}x{2A-UYy#?%{e=o0GTe$(W&%BBiGfbWKIGQFctNgTdpFp(uW8WvNBUL$xaWi{IUvq8 z(w7W_g?;WU-vLFzD&W;BY7MYnqt8eu6tkm3l~aK(P+0T{dXr$$t^(85oCEhm!v)pE zF(v63qbaz#k21we*4!Rw1e1oHjja6&zBUl{!VzUeQ|P;mrzu2#*AyoHM+Qy!DY#Q9 zIlp~dt<5Xe&Dw_(dS^wQeBC75nR+(krq$MHR!szubENMd*p)hop`pruCka{90+ z_HXQ~68inA6GAPGq#L5RVB1hGb2&SA{u5n!dpWasrZOpc2D#ez=n5~RGv4}+^a_y$ z%a7sp#l7jRf^oJA4cp`j_`>7->1eKlf}dKTlJ5#RvPPVhteh+?Vo<=j1>gNb%yAhLYQdm6x` z8P@1bqSfChuD1p*fY|eh7_>}V!HT}B@}OoPZ|uWfY<*#;87w#rVl_MK+#dz&-tSPe zb?)Qg=}vXxLo_FKm02X81g}!q`ss?W5?M0Db>nIJ3YgL;Y9vc=A`55E*ISdvkN3eq zS5TG|7SNo@1WDeXAnmH$&8;LRrR%Z|=&hy7Hal}Z*@cXy9_rasbl-az8Q>L_()Kdl zOUGBHrxn2|RpViQzhC1SxI~ZP960q(h?+2?2-W3ViqL9el`ISf@eD7PFg@ksUXq|D z$8TQ*AKGwmC(qD4)t=6tpvTE7J5<&lCLi{cIV_c)hVykwMpEl(jj#9=Y>xPvRmWxw0>2aX`=pijGp|)*arp!?_6U< z>L3D}MnF?UiU0T0E%8mAGx7J%wLw$eXMY^+Ihum+2&>O*zM92i^bfdQ4Fc%;r@xS$>T@RLsl{nNsfI&HwyI{NX`;6 zR%QF~v(XM->}jq<>%Jk3jXk}r$m~<6hmfr4Xt54v++w&=M`QPQ%_;q^MdHTNCN5{S z=aGUBZJF?nbR1e{c+*(te!R%^5|%e%)lYsNq1LVY5by_1`L<9*ifn12IH6*9jnl!i zJ;$nXw432G?Hvr?OL*rWR5+nRaJ>jf3cNl;J+IGEEC`=d+Ko6)jCt7mlFOXt7`LFc z>SN2j%yv495aXk0aoGwry6FxEfty;cBhO}2v0yC`dl6|JDEc@N2xVy7q@KO%v>CCT)M-Nw=%4pdwhRno-uR@|P%MSGb`OH~ku zJLdXGb(q1MCc1UUXyV)G7z+%(>KJb{DZ58BXb+H=(N+;^Bk`<}zj44W+6x55PyWE0 zeg=Zm6^EX4ad#?i5^*Bu!S)&E197C)_E7#|mfI^ic8g0sSIPS+ZqHoYe8v69W%*uD zlXZ(M_l#!wARrNpri>x^%Zl3}mu0=;mfEa>IXqkBx0lI}?%h@VoG>}HKAE(t+*L05 z@jTsZ#zQ4OGp#gLoL2vGtBXX_W`<}aMRm*ZyOa!OR&H7>~Hl^qMjXxpU%y{**+lA;BoF^w!rxBqN2ALWTWMp(H9Z9Zj^Uv zX`>CmBCku$91HtIHGAgpV&HQfr(cAfgP9o)7YaG^sNVL}e*CYaR4@GUiW7aP>vqw) zKC-9X86=vRok2x21r){p5jCN|cV}8FN7+n#;RG8r6ssc_`r*$|*RBU`Y8LM)&Eh=; zTg`y(wBi%1OI=^n>O#O@048$puczN{1K?r5>?rT1~+dg!P=oGh(ky8KKK0D3OnDgH1Oe z=oe>=r(eWcIPA=GYj!vNYS_}?c1Jsk|wZ-G)+>C6z=UI_P zSht57p~rcjic~YL8Im~#Qx&@;mDy27W_o!t_P8-ve=QUfv;NNibwP(@=JJB{b9L)G z4Cm(a#Ejpb5Bjmi=@*=tdhOc9A9bkmk8)P(8%3OylIs1`nr(CACu^s2>f-maQ_EKw zGc^@!EbMeu&P=tz&`h-<%+y~S?*+7{A*BU1=O|T>lcr2x}zCgjIlcdK^a zi15($MWyDJGb5z-cP9VrPsrzF=cFJ@~SBvom16^5(7;ty!1TyBxNlHk5`(6G>JO~p5zQ}IkX$M0#G>b%7O}D zMAi;GF}fP5FYbS4qeoFgg%Y#MKp`EG{}@m1Ic3L2W;wi|A{)7G|3!hM!M zuphG>t|;6IwD=im+=vwV@%N6lh`HWtWE9Uhc;ZD+=f!!84W7KhNI$fo2!BFfygf7=hP}HBtn29D8 zeuoMNk!Dp8mHiPWyMB%M3O3bej&>OAr6g!*)4!O>m(tr6{a{yCdqn2pf1PXC-O z0H>wV$&Uut|47{wDvh4#>fy(L80T|;h?|0Y4U?HE@ZaTlwLJd14UfHHx`+(uyDp-V zK0>~X^&Jv3EQychvq3~orwc`+J?_g>kme@K=${@?qD$92I% zvm2v(z8j-^o*Se4jKkC2Gj(fXP`wfCRfA;go1vM$e=-Mae{R^JbNA65bW>B6)ST zh~~VvB`0iBbCz|>*PN#j78CBlGhdE1`22pF^T}N-qODYmQ!82XJ=CLikSi?-aYb1( zu0^G4$)MEe=4sEiG$tA5G^z%=t+eN{V4~XZ$rAy^?yFYoOyVRbbR|tmv-Dk=r}{?c zRNv{XRNsBVwpsPPdYanUslNF;qxwdyX{q{-B?)Ls)97bRkUXPXmN?vI{t82-cppd4}LN&R%f-O0RtF|6R_lzjEc~8iMIgx2JSDRVa3nIQT-& za(_T&vam)YqAz5yCkqFZ2IpfH@!|GG71URbyj81OHt{KtLfvphv|VY|=B|pP(ezmW z8yctmM(0&@G5w6^&nx|yQS_Q!Y2qompO@g48o&PQ18(EmZ_Kr}v%1J5K#Spq9NuL7 zjb3k#iQ=Y@gvb4R)eB)iBQbL$#MjJ{}Xh#;q=QW zaG`%$!6?l&M!Q4hiGY$#&__v}w=Bo*h55tk>kMr34A5`3Cyh)6J7oPXG!!E16$)h> z(2p$(jx#uQ?t^7xn><`aaT>YEU|5qhE!0TcQ+qPT9%Z7X*vrIHu{Vboo>`pfI$KJ4 zNT%o(mVnfkicu1?xYz^C*%aHa96T%!`0;+2JUH{G;hR8-58O`UR@nK^CTGMzjWAaM zKRyI9q1!p5TamMEWWROF%dJI4$1Ybi;j8WE{XVxvX%J)iHOk-Pv|qs8HP3c8oB zVaVQczCiOi8=Wt>u1mf=Jz&GZ6+ENGeM(sJqz+@WA?}*(S${E-JEX1n+$Iun>vH;e zZl^7|=xxvUn#!7LH(2R;D$&3>d;oARvy+~mh{Gf@2J2Mm1UZVupCW-Z<`EJnPuI1< ztVVX8Nr*od7@FkfXe7-=AoEsmb5=tS!*0?i5M=*Y6|YyPPxCY zv|Zc9- zTq$F_&US-j5~cc_=LrQ{MX;n?8E0PlF%a%wwj!0dGZ275xf$JL?0GM<3+Qr)?O$`q z3WeZ?&bF1t@>ID-wnbE=e;ktSFrvOpSt9MFp(Q6q>Y|aX)h86%NPdY~eOU)1Mx!)p zrhemAgJH=3@okTjkUNe0awjahvpN1Lrw@`$OVJ;QlN0sVonBBdWcuKqB^L!rKULZk zb`;lEvP#L!s3*rRsp|bMm!*XI1V2~$;Y58UDb;aEa4%kio--1X>b*MbO|o}z^A7Wo z$+6F`*-`gX)jb@m-C&E&QWJHX>6I4+o_`4vZ*N^c?P9f}Jr+!z(p=J^63mVB9KS}Y zWV+Fo+Og!~cf7GH781wm6eE|2WbYT8IIbPu`_b$qNHsf!Wqg-_SXGi7`{Zo@7frQa z3BEG@WX;8R1x5JE>4S?)E`Hk^`?QyS+UxzI?HXC!j%07hUV>BGTyJ02WNzR#gt3KY zPv_f%%FbY7J`0P4w^j$^yw6vjW!4*NzGhz_?je&x|G5+|W_Kc*W17rxo+G<1~RP(+B1_ zXFeS*GiC{;6G>fHJMYwC))-s$o><2B{K^mfNX^`t;&xzeH1h zoi`m5KV@Wu+J}K6mhy=AjX%bi@<~l>Br{!ciLFBMUun&{(*#H(?8q~M;C*X7eht`uT?zvidS^H19E z!DbKc+R7B&EgBWw&2ftInk4S5t}x!B)>%7R$tqWCp>yI8O3G@;MjBtd=R9(UjmTTF z93`je!nZ4y`Fn!(8mbDJB5bhZ<@y7=2xiTc>q!z(?xn4wl&kL!e`fDRQ)sf%Sm^*c zWQPmcW~9tH9s~^r)5#{=^h#4x(kzGVt4Ui`aF_@gTP=R$j9|;<#-5qjXdXm`7Co;~ zK{Zw1)IwTqyU)pJF*q=n_!kDbZvE@)!BL81`Q*Be(P}muUAHXzdrOu8uzW{qxJh>F%M#L=>l-_ zd^@?M-nkc32jvui+-jezqOjCa)v9whysJHko$ZZXYjmSiqhEUYQ~u8jDPuS4TsL9# zuBlJn0ysDeWP(1xE<&8BoH+?_m`Phx+RIQ%JEW>z%qTaM;S@w-qBH-sMJlh=%zt2_ z!3^b5JJXC)VY04!M23;d=gknT>4xdlepvhX1%IRxS!&!LdP0tTVV^XjRW?N3tY_3jK`P#5H*WL`IloT3@*{jTeD;vJ3S()FheBl~D9LrSX1am(S z1Hnc6k_naQtV$dyWaYbPvYo?F1M{xJbjbz5zJygE5n;3ByZ3i837UczJ0QhJpb4>1 zwHTYr;2QpOtO|eSfz2-NR|?)J5MT^20HP(?&y+0U=GG#p)p_fLr#EZSEG17$mrTTlujPIcSAiDgj%zS4mu|PD*!aFZ-#qFTP%%k@t zl1xfWCie1VRCV!izi%hSk4pNJ;@XhhD^e(Kvik~bDdox(I4^&-|2+G-VH@$3AO92r zn!G8#ODx6pU??h`#@Qtm%VGzUK`$CW%BsXl1~J9-ZdF2HRpwkCe(7|_9X4rKg}Aqcdw2to8WDgas26vJPTsK1jnfi@Q^ zmIGNLkmU~K>;pm&^+sVqe-+3d9mwwv%bCIuAh$nQgc_N@HRD2?qG4-GsK?&ia)jyt zMo~f)JLJBQZPKNRhW-`m z$go}1B8o_}E~_&`_s}$QoayCprXT;9J;UKAb(*m(Hxgq~7;HGnC6j+BOOOqS?{KP07NJA+AA!LcyrQ zB1k`5G_nR-_~T+$yw@LUQN=?sGOc$~{_hYAr2 z-U^H;=xq|gUwj-s9q$j%j4w8- zNA6SxNxMrKmL&bYRcwr41B6@H8G9|*p48H858)GWY%iT;`VzBHzge+|eiLM<^0lZ8 z{eBC{(CtsQAw#k%CGr1v8JgpK2-bn!08g6|_k zkAKy&^;^qO%pv$kU|S&ALWXW_AGz-SGr8 z8=1%Ho|Cdv?BitmNiV&gYIvIc?_AA*JM5#vc>(!<>_VTg0}%7cy%cn$Y8c#KKI#OG zVNb+w6j8PZ36M5;g%O71E z+UOEap=2|~3>tRU*z{WRZ$e1ANf^+emao=or(PPfrRTfF`wZdGfyNBhC_xHn za>)5!q55+TB&AxScJFGmub}e!?EBVH6@Tyfi`!5oqFT=K{Xl@!c{WeS`mT9Sqbf!; z3AZJaZ8VRu(ZcFDo7vll<+~Gwwy8z(P)s@$Kg2bZkK*YYVe_`pLoyw;o6$33*`8T> z0fn|;cB_>0Q2Y~6qT-PbMMuIjwgi67;@A$3D){lWj*=mF8|49xd~9y)CZGiU2Ls)j z!CP9dkA7lUeCQ)l7BAUCEKW9?%i`bac$k(fzUpJc;wv896pL@|YJCR@^7&^^aQH8? z_yH8UX%-)^y3jD&v_f&OEx|%X8)flpKiV7?e*`F@cot7l(Xn{XErH)=v3T&|=CF8o zhi0RJ-ZYCZ`Vbb+Gd*#J8)j?mwVg_yi~7R0xa>uWxe8miv)s199EC|ua^r>;yhieT zYujTx762vOn`fI|=2#kd% z*h|!go}1qh($lm;Z=+&ZY*57J2ZKCQHLs@`>`+|&eoGX4ZwVAPDT%=t3T~;;!p^3- zr?~+rQL@}X8|%+0jC~E?;_llVYK9bS)B4M`dpmBcd$YnckDxRF7E~TV*8n9X~h1hasJ3V*MHAFGbFwOR4`3M64l$9w*xStuq_4{Q1A13fDC-`9kKRSS5{@zF5 zyD5RcPJmE$AkTctj@@FEZP%%~=)Kl#I#Obl*Z3a+B@}ZzjhvLUfCFi4f=9WNl(*i%4f;TPjw*nL0Ycd-p81qLXNys`U4dWmR%WV*3Ech*ZuWYLdr_b}T|?>BIMzklrtT*kxfXWG!q4APR5E?%Mhdzay~^UseZ zS<`H15mSEOgVyY#_0&36sP<90yQ|9IO3a+DjJaxAOC@sWzW?quO_)r1E}xMX{@+@` zEL%&()<(C@$e9>=ReW1%Vecu@tas(!i@jBQ=Sdw8BGB_G;kTv%%hv47eZpFYZriW2{G-IoIsH_xm)t>vZl%Q= z|7mW&q*>tQsPJTqCe*~U^lP|o!qpB84Y5K7?@t@jlA#lr5lt`A(ypY=Z@wkCXL5AD z4LoSRVn!9Y=KGL1HQ#kS^Ok}C59>&v-7Bp9fwFpC4f~Hz?4KuZiL3r5xctU_A=f0E!z(mom&B|)X>MWL->xb%4e$5Z$!yB~ zunPLKmu_-Q5UkEJt)B7+^w;r?)K{rV4S?{F4QL&spbM1XEcxXY%18u`*zrC;SrKS*Evcvtu^qlIu*C}~DXq$IAF z5k@3X(#Mkbp=wLN-%V_I(-G4nA*a@9>c^7zWaji@qqfW#EcS?5p~W6G#f?f%T%yLp zXgH44ibB%01wm`e32~S8=bE5q|6FsMdw%!+$@J@M_GN$ScRB?}>exRmW|oH}YnLg< zVB44MH1^^jqd;Cg1lGCi8Tjtte~EG9$NmMBnH(NjmDw%B#)?-cYh*7p?4@{E zMKWt{PZ7Vzl_VhDr6@I3n{ljWUaw*?-q#B2zp%2yyY! zqB71B)Df+ml-y$n8q7r|>glOOtE-SHT?*skaF+SnZvroG72GnG! z^yA6QQFdFx;v@Y5TUV9$y*uI8NmOIYQ?ccQuT0Fk(1~uzqE1lGuGB#t^w$b9!#H-8 zXBSR%*prjL5fQ0EcUq?3c@>KRw7ip*mPfy6V1%@e^6{HH2#Y2`A zU2Vwbcm6x+@)sEHV3H^5yJ%sf-}zhtm{n`x;<-;=u$=K@juiyp#8x@1GyqeM6VG)q z4&!jmyRKMyFyQg}n|dCT_9tOkT$?#Rp8DHG0@v;Ux)PVI{40C2#up6`Nr5 zm-C(BFnYkEyrC7qVGiIMP!8KFm3~r9gT||}C-IK3>$g|ao!Y}sYbMuy8=H0xXf0X5 zDoZ=i97$`?O&0Cyr8x*@xIgYug!bLwC`#bcnkk3sF0W$0y2*mWxGR(XsgJ_+uLb*B zm_)-QSjNi~CewHg+^3OwEo3 zd16iHnRXis?tDH^U+oOlgU5-}(l5LI9z}-z6+CPr$CcV8_$Kn*;CDoV!Cll@`Yv1| zpV?l`fD6=Z?wO&qC|l1yLnK^ZaIlaI@!12AMd%TepFi+#$a-*y;$*0Thq5_HVKJqf zeAtaJSZrgbzuLv3BVbDY@V|}H-3{3BPQ$l(E6{7rInDd4nlZi%&6r-vzE`jC z#Nyh)*ClA)#I;ZErb0UZMqS_b4bRqe*REaqpa@{o>d)fEDZoW_!{o{kg#ll9Crur34%^sk|(-9ZXmF)2(-&hcLOBg8Ug$9;dfJyLE2wX zsO<)pDB0cAvH0;We>C#pSZK2Bg-pK#MM9!BHILGs3qd{c4{~Px{uyfE?|uC(201eZ z&aJV^a}7TyK&pB%PcIXt`uSAlzdT*_&C1PjA@p}B{u}6g6fY39H-pS>jP`xJ*C!bi zH|5Ooff5zVTA_I1mOycnUWDN8r(099^>o#{Kncxj40P0cU1Ru`erR*38T$X7MEXV1 z#Y&;JZ*MNB*p!_|&^D&420KhwKh?6$r))8{Y}b2zCWVG>qdW(8tBI8xfD}Q?TcLT; zmT32)#*M94fAC4y=9nSPEr98teeXX;HBGV7?^M$O)5QJevRHC+TDd*dWHwOz5bx$z zpp9x;f77N^(;xvt-2Xh$k_QHEF&=2wyE%qJH|^cL0Vvb{tx#ks&t{SN2dJh8A8%&U z_Gi-90VNb~@DSl3U|VVJ-a4* z@;_VcV;@1L^8A_sd$cFpGW*z1)2THGtXXecu^hVk13$r`VH{7|zdl28Jon{^nJD)< zHh05UzfzsyE550F)F90%<)dZjg;_Q&GszcqQ=~ue&88UltJ`9(k>4cT$G*2K=6T?= z4_wduL3MG>#F|N-e|hIcugF+lc;dvG3Fl3zIm2V-z+9oTw7S!oK`#