View Javadoc
1   // ******************************************************************************
2   //
3   // Title:       Force Field X.
4   // Description: Force Field X - Software for Molecular Biophysics.
5   // Copyright:   Copyright (c) Michael J. Schnieders 2001-2024.
6   //
7   // This file is part of Force Field X.
8   //
9   // Force Field X is free software; you can redistribute it and/or modify it
10  // under the terms of the GNU General Public License version 3 as published by
11  // the Free Software Foundation.
12  //
13  // Force Field X is distributed in the hope that it will be useful, but WITHOUT
14  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16  // details.
17  //
18  // You should have received a copy of the GNU General Public License along with
19  // Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple
20  // Place, Suite 330, Boston, MA 02111-1307 USA
21  //
22  // Linking this library statically or dynamically with other modules is making a
23  // combined work based on this library. Thus, the terms and conditions of the
24  // GNU General Public License cover the whole combination.
25  //
26  // As a special exception, the copyright holders of this library give you
27  // permission to link this library with independent modules to produce an
28  // executable, regardless of the license terms of these independent modules, and
29  // to copy and distribute the resulting executable under terms of your choice,
30  // provided that you also meet, for each linked independent module, the terms
31  // and conditions of the license of that module. An independent module is a
32  // module which is not derived from or based on this library. If you modify this
33  // library, you may extend this exception to your version of the library, but
34  // you are not obligated to do so. If you do not wish to do so, delete this
35  // exception statement from your version.
36  //
37  // ******************************************************************************
38  package ffx.potential.nonbonded.implicit;
39  
40  import static ffx.potential.nonbonded.GeneralizedKirkwood.DEFAULT_TANH_BETA0;
41  import static ffx.potential.nonbonded.GeneralizedKirkwood.DEFAULT_TANH_BETA1;
42  import static ffx.potential.nonbonded.GeneralizedKirkwood.DEFAULT_TANH_BETA2;
43  import static org.apache.commons.math3.util.FastMath.PI;
44  import static org.apache.commons.math3.util.FastMath.pow;
45  import static org.apache.commons.math3.util.FastMath.tanh;
46  
47  /**
48   * Rescale the Born radius integral to account for interstitial spaces.
49   * <p>
50   * Ri^-1 = [rhoi^-3 - (4*pi/3(rhoi^-3 - 50^-3)) * tanh(beta0*Psi*rhoi^3 - beta1*(Psi*rhoi^3)^2 +
51   * beta2*(Psi*rhoi^3)^3)]^(1/3)
52   * <p>
53   * Citations: Aguilar, B.; Shadrach, R.; Onufriev, A. V. Reducing the secondary structure bias in the
54   * generalized Born model via R6 effective radii. J. Chem. Theory Comput. 2010, 6, 3613−3630.
55   * <p>
56   * Onufriev, A.; Bashford, D.; Case, D. Exploring protein native states and large-scale
57   * conformational changes with a modified generalized born model. Proteins 2004, 55, 383−394.
58   *
59   * @author Rae A. Corrigan
60   * @since 1.0
61   */
62  public class BornTanhRescaling {
63  
64    /**
65     * Maximum Born radius.
66     */
67    public static final double MAX_BORN_RADIUS = 30.0;
68    /**
69     * 1/50^3 where 50 Angstroms is the maximum Born radius
70     */
71    private static final double RECIP_MAX_BORN_RADIUS3 = pow(MAX_BORN_RADIUS, -3.0);
72    private static final double PI4_3 = 4.0 / 3.0 * PI;
73    /**
74     * Tanh coefficients from Corrigan et al.
75     */
76    private static double beta0 = DEFAULT_TANH_BETA0;
77    private static double beta1 = DEFAULT_TANH_BETA1;
78    private static double beta2 = DEFAULT_TANH_BETA2;
79  
80    /**
81     * Rescale the Born radius integral to account for interstitial spaces.
82     *
83     * @param Ii The total integral of 1/r^6 over vdW spheres and pairwise neck integrals.
84     * @param rhoi The base radius of for the atom being descreened.
85     * @return The rescaled integral, which is greater than or equal to the input integral.
86     */
87    public static double tanhRescaling(double Ii, double rhoi) {
88      // Set up tanh function components
89      double rhoi3 = rhoi * rhoi * rhoi;
90      double rhoi3Psi = rhoi3 * Ii;
91      double rhoi6Psi2 = rhoi3Psi * rhoi3Psi;
92      double rhoi9Psi3 = rhoi6Psi2 * rhoi3Psi;
93      // If the output of the tanh function is 1.0, then the Born radius will be MaxBornRadius
94      double tanh_constant = PI4_3 * ((1.0 / rhoi3) - RECIP_MAX_BORN_RADIUS3);
95      return tanh_constant * tanh(beta0 * rhoi3Psi - beta1 * rhoi6Psi2 + beta2 * rhoi9Psi3);
96    }
97  
98    /**
99     * The chain rule derivative for rescaling the Born radius integral to account for interstitial
100    * spaces.
101    *
102    * @param Ii The total integral of 1/r^6 over vdW spheres and pairwise neck integrals.
103    * @param rhoi The base radius of for the atom being descreened.
104    * @return The chain rule derivative.
105    */
106   public static double tanhRescalingChainRule(double Ii, double rhoi) {
107     double rhoi3 = rhoi * rhoi * rhoi;
108     double rhoi3Psi = rhoi3 * Ii;
109     double rhoi6Psi2 = rhoi3Psi * rhoi3Psi;
110     double rhoi9Psi3 = rhoi6Psi2 * rhoi3Psi;
111     double rhoi6Psi = rhoi3 * rhoi3 * Ii;
112     double rhoi9Psi2 = rhoi6Psi2 * rhoi3;
113     double tanhTerm = tanh(beta0 * rhoi3Psi - beta1 * rhoi6Psi2 + beta2 * rhoi9Psi3);
114     double tanh2 = tanhTerm * tanhTerm;
115     double chainRuleTerm = beta0 * rhoi3 - 2.0 * beta1 * rhoi6Psi + 3.0 * beta2 * rhoi9Psi2;
116     double tanh_constant = PI4_3 * ((1.0 / rhoi3) - RECIP_MAX_BORN_RADIUS3);
117     return tanh_constant * chainRuleTerm * (1.0 - tanh2);
118   }
119 
120   // Getters and setters for optimizing constants
121   public static double getBeta0() {
122     return beta0;
123   }
124 
125   public static double getBeta1() {
126     return beta1;
127   }
128 
129   public static double getBeta2() {
130     return beta2;
131   }
132 
133   public static void setBeta0(double beta0) {
134     BornTanhRescaling.beta0 = beta0;
135   }
136 
137   public static void setBeta1(double beta1) {
138     BornTanhRescaling.beta1 = beta1;
139   }
140 
141   public static void setBeta2(double beta2) {
142     BornTanhRescaling.beta2 = beta2;
143   }
144 
145 }