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 }