Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

ComputeNonbondedUtil.C

Go to the documentation of this file.
00001 
00007 /*
00008    Common operations for ComputeNonbonded classes
00009 */
00010 
00011 #ifdef WIN32
00012 extern "C" {
00013   double erfc(double);
00014 }
00015 #endif
00016 
00017 #include "InfoStream.h"
00018 #include "ComputeNonbondedUtil.h"
00019 #include "SimParameters.h"
00020 #include "Node.h"
00021 #include "Molecule.h"
00022 #include "LJTable.h"
00023 #include "ReductionMgr.h"
00024 #include <stdio.h>
00025 
00026 Bool            ComputeNonbondedUtil::commOnly;
00027 Bool            ComputeNonbondedUtil::fixedAtomsOn;
00028 BigReal         ComputeNonbondedUtil::cutoff;
00029 BigReal         ComputeNonbondedUtil::cutoff2;
00030 BigReal         ComputeNonbondedUtil::dielectric_1;
00031 const LJTable*  ComputeNonbondedUtil::ljTable = 0;
00032 const Molecule* ComputeNonbondedUtil::mol;
00033 BigReal         ComputeNonbondedUtil::r2_delta;
00034 BigReal         ComputeNonbondedUtil::r2_delta_1;
00035 int             ComputeNonbondedUtil::r2_delta_exp;
00036 BigReal*        ComputeNonbondedUtil::table_alloc = 0;
00037 BigReal*        ComputeNonbondedUtil::table_short;
00038 BigReal*        ComputeNonbondedUtil::table_noshort;
00039 BigReal*        ComputeNonbondedUtil::fast_table;
00040 BigReal*        ComputeNonbondedUtil::scor_table;
00041 BigReal*        ComputeNonbondedUtil::slow_table;
00042 BigReal*        ComputeNonbondedUtil::corr_table;
00043 BigReal*        ComputeNonbondedUtil::full_table;
00044 BigReal*        ComputeNonbondedUtil::vdwa_table;
00045 BigReal*        ComputeNonbondedUtil::vdwb_table;
00046 BigReal*        ComputeNonbondedUtil::r2_table;
00047 BigReal         ComputeNonbondedUtil::scaling;
00048 BigReal         ComputeNonbondedUtil::scale14;
00049 BigReal         ComputeNonbondedUtil::switchOn;
00050 BigReal         ComputeNonbondedUtil::switchOn_1;
00051 BigReal         ComputeNonbondedUtil::switchOn2;
00052 BigReal         ComputeNonbondedUtil::c0;
00053 BigReal         ComputeNonbondedUtil::c1;
00054 BigReal         ComputeNonbondedUtil::c3;
00055 BigReal         ComputeNonbondedUtil::c5;
00056 BigReal         ComputeNonbondedUtil::c6;
00057 BigReal         ComputeNonbondedUtil::c7;
00058 BigReal         ComputeNonbondedUtil::c8;
00059 // BigReal         ComputeNonbondedUtil::d0;
00060 // fepb
00061 Bool      ComputeNonbondedUtil::fepOn;
00062 Bool      ComputeNonbondedUtil::thermInt;
00063 BigReal   ComputeNonbondedUtil::lambda;
00064 BigReal   ComputeNonbondedUtil::lambda2;
00065 BigReal   ComputeNonbondedUtil::fepVdwShiftCoeff;
00066 BigReal   ComputeNonbondedUtil::fepVdwLambdaEnd;
00067 BigReal   ComputeNonbondedUtil::fepElecLambdaStart;
00068 Bool      ComputeNonbondedUtil::decouple;
00069 //fepe
00070 Bool      ComputeNonbondedUtil::lesOn;
00071 int       ComputeNonbondedUtil::lesFactor;
00072 BigReal   ComputeNonbondedUtil::lesScaling;
00073 
00074 BigReal*        ComputeNonbondedUtil::lambda_table = 0;
00075 
00076 Bool            ComputeNonbondedUtil::pairInteractionOn;
00077 Bool            ComputeNonbondedUtil::pairInteractionSelf;
00078 
00079 Bool            ComputeNonbondedUtil::pressureProfileOn;
00080 int             ComputeNonbondedUtil::pressureProfileSlabs;
00081 int             ComputeNonbondedUtil::pressureProfileAtomTypes;
00082 BigReal         ComputeNonbondedUtil::pressureProfileThickness;
00083 BigReal         ComputeNonbondedUtil::pressureProfileMin;
00084 
00085 BigReal         ComputeNonbondedUtil::ewaldcof;
00086 BigReal         ComputeNonbondedUtil::pi_ewaldcof;
00087 
00088 void (*ComputeNonbondedUtil::calcPair)(nonbonded *);
00089 void (*ComputeNonbondedUtil::calcPairEnergy)(nonbonded *);
00090 void (*ComputeNonbondedUtil::calcSelf)(nonbonded *);
00091 void (*ComputeNonbondedUtil::calcSelfEnergy)(nonbonded *);
00092 
00093 void (*ComputeNonbondedUtil::calcFullPair)(nonbonded *);
00094 void (*ComputeNonbondedUtil::calcFullPairEnergy)(nonbonded *);
00095 void (*ComputeNonbondedUtil::calcFullSelf)(nonbonded *);
00096 void (*ComputeNonbondedUtil::calcFullSelfEnergy)(nonbonded *);
00097 
00098 void (*ComputeNonbondedUtil::calcMergePair)(nonbonded *);
00099 void (*ComputeNonbondedUtil::calcMergePairEnergy)(nonbonded *);
00100 void (*ComputeNonbondedUtil::calcMergeSelf)(nonbonded *);
00101 void (*ComputeNonbondedUtil::calcMergeSelfEnergy)(nonbonded *);
00102 
00103 void (*ComputeNonbondedUtil::calcSlowPair)(nonbonded *);
00104 void (*ComputeNonbondedUtil::calcSlowPairEnergy)(nonbonded *);
00105 void (*ComputeNonbondedUtil::calcSlowSelf)(nonbonded *);
00106 void (*ComputeNonbondedUtil::calcSlowSelfEnergy)(nonbonded *);
00107 
00108 // define splitting function
00109 #define SPLIT_NONE      1
00110 #define SPLIT_SHIFT     2
00111 #define SPLIT_C1        3
00112 #define SPLIT_XPLOR     4
00113 
00114 void ComputeNonbondedUtil::submitReductionData(BigReal *data, SubmitReduction *reduction)
00115 {
00116   reduction->item(REDUCTION_EXCLUSION_CHECKSUM) += data[exclChecksumIndex];
00117   reduction->item(REDUCTION_PAIRLIST_WARNINGS) += data[pairlistWarningIndex];
00118   reduction->item(REDUCTION_ELECT_ENERGY) += data[electEnergyIndex];
00119   reduction->item(REDUCTION_ELECT_ENERGY_SLOW) += data[fullElectEnergyIndex];
00120   reduction->item(REDUCTION_LJ_ENERGY) += data[vdwEnergyIndex];
00121 //fepb
00122   reduction->item(REDUCTION_ELECT_ENERGY_F) += data[electEnergyIndex_s];
00123   reduction->item(REDUCTION_ELECT_ENERGY_SLOW_F) += data[fullElectEnergyIndex_s];
00124   reduction->item(REDUCTION_LJ_ENERGY_F) += data[vdwEnergyIndex_s];
00125 
00126   reduction->item(REDUCTION_ELECT_ENERGY_TI_1) += data[electEnergyIndex_ti_1];
00127   reduction->item(REDUCTION_ELECT_ENERGY_SLOW_TI_1) += data[fullElectEnergyIndex_ti_1];
00128   reduction->item(REDUCTION_LJ_ENERGY_TI_1) += data[vdwEnergyIndex_ti_1];
00129   reduction->item(REDUCTION_ELECT_ENERGY_TI_2) += data[electEnergyIndex_ti_2];
00130   reduction->item(REDUCTION_ELECT_ENERGY_SLOW_TI_2) += data[fullElectEnergyIndex_ti_2];
00131   reduction->item(REDUCTION_LJ_ENERGY_TI_2) += data[vdwEnergyIndex_ti_2];
00132 //fepe
00133   ADD_TENSOR(reduction,REDUCTION_VIRIAL_NBOND,data,virialIndex);
00134   ADD_TENSOR(reduction,REDUCTION_VIRIAL_SLOW,data,fullElectVirialIndex);
00135   ADD_VECTOR(reduction,REDUCTION_PAIR_VDW_FORCE,data,pairVDWForceIndex);
00136   ADD_VECTOR(reduction,REDUCTION_PAIR_ELECT_FORCE,data,pairElectForceIndex);
00137   reduction->item(REDUCTION_COMPUTE_CHECKSUM) += 1.;
00138 }
00139 
00140 void ComputeNonbondedUtil::submitPressureProfileData(BigReal *data,
00141   SubmitReduction *reduction)
00142 {
00143   if (!reduction) return;
00144   int numAtomTypes = pressureProfileAtomTypes;
00145   // For ease of calculation we stored interactions between types
00146   // i and j in (ni+j).  For efficiency now we coalesce the
00147   // cross interactions so that just i<=j are stored.
00148   const int arraysize = 3*pressureProfileSlabs;
00149   size_t nelems = arraysize*(numAtomTypes*(numAtomTypes+1))/2;
00150   BigReal *arr = new BigReal[nelems];
00151   memset(arr, 0, nelems*sizeof(BigReal));
00152 
00153   int i, j;
00154   for (i=0; i<numAtomTypes; i++) {
00155     for (j=0; j<numAtomTypes; j++) {
00156       int ii=i;
00157       int jj=j;
00158       if (ii > jj) { int tmp=ii; ii=jj; jj=tmp; }
00159       const int reductionOffset = (ii*numAtomTypes - (ii*(ii+1))/2 + jj)*arraysize;
00160       for (int k=0; k<arraysize; k++) {
00161         arr[reductionOffset+k] += data[k];
00162       }
00163       data += arraysize;
00164     }
00165   }
00166   // copy into reduction
00167   reduction->add(nelems, arr);
00168   delete [] arr;
00169 }
00170   
00171 void ComputeNonbondedUtil::calc_error(nonbonded *) {
00172   NAMD_bug("Tried to call missing nonbonded compute routine.");
00173 }
00174   
00175 void ComputeNonbondedUtil::select(void)
00176 {
00177   if ( CkMyRank() ) return;
00178 
00179   // These defaults die cleanly if nothing appropriate is assigned.
00180   ComputeNonbondedUtil::calcPair = calc_error;
00181   ComputeNonbondedUtil::calcPairEnergy = calc_error;
00182   ComputeNonbondedUtil::calcSelf = calc_error;
00183   ComputeNonbondedUtil::calcSelfEnergy = calc_error;
00184   ComputeNonbondedUtil::calcFullPair = calc_error;
00185   ComputeNonbondedUtil::calcFullPairEnergy = calc_error;
00186   ComputeNonbondedUtil::calcFullSelf = calc_error;
00187   ComputeNonbondedUtil::calcFullSelfEnergy = calc_error;
00188   ComputeNonbondedUtil::calcMergePair = calc_error;
00189   ComputeNonbondedUtil::calcMergePairEnergy = calc_error;
00190   ComputeNonbondedUtil::calcMergeSelf = calc_error;
00191   ComputeNonbondedUtil::calcMergeSelfEnergy = calc_error;
00192   ComputeNonbondedUtil::calcSlowPair = calc_error;
00193   ComputeNonbondedUtil::calcSlowPairEnergy = calc_error;
00194   ComputeNonbondedUtil::calcSlowSelf = calc_error;
00195   ComputeNonbondedUtil::calcSlowSelfEnergy = calc_error;
00196 
00197   SimParameters * simParams = Node::Object()->simParameters;
00198 
00199   commOnly = simParams->commOnly;
00200   fixedAtomsOn = ( simParams->fixedAtomsOn && ! simParams->fixedAtomsForces );
00201 
00202   cutoff = simParams->cutoff;
00203   cutoff2 = cutoff*cutoff;
00204 
00205 //fepb
00206   fepOn = simParams->fepOn;
00207   thermInt = simParams->thermInt;
00208   lambda = lambda2 = 0;
00209   lesOn = simParams->lesOn;
00210   lesScaling = lesFactor = 0;
00211   fepVdwShiftCoeff = simParams->fepVdwShiftCoeff;
00212   fepVdwLambdaEnd = simParams->fepVdwLambdaEnd;
00213   fepElecLambdaStart = simParams->fepElecLambdaStart;
00214 
00215   decouple = simParams->decouple;
00216 
00217   delete [] lambda_table;
00218   lambda_table = 0;
00219 
00220   pairInteractionOn = simParams->pairInteractionOn;
00221   pairInteractionSelf = simParams->pairInteractionSelf;
00222   pressureProfileOn = simParams->pressureProfileOn;
00223 
00224   if ( fepOn ) {
00225     lambda = simParams->lambda;
00226     lambda2 = simParams->lambda2;
00227     ComputeNonbondedUtil::calcPair = calc_pair_energy_fep;
00228     ComputeNonbondedUtil::calcPairEnergy = calc_pair_energy_fep;
00229     ComputeNonbondedUtil::calcSelf = calc_self_energy_fep;
00230     ComputeNonbondedUtil::calcSelfEnergy = calc_self_energy_fep;
00231     ComputeNonbondedUtil::calcFullPair = calc_pair_energy_fullelect_fep;
00232     ComputeNonbondedUtil::calcFullPairEnergy = calc_pair_energy_fullelect_fep;
00233     ComputeNonbondedUtil::calcFullSelf = calc_self_energy_fullelect_fep;
00234     ComputeNonbondedUtil::calcFullSelfEnergy = calc_self_energy_fullelect_fep;
00235     ComputeNonbondedUtil::calcMergePair = calc_pair_energy_merge_fullelect_fep;
00236     ComputeNonbondedUtil::calcMergePairEnergy = calc_pair_energy_merge_fullelect_fep;
00237     ComputeNonbondedUtil::calcMergeSelf = calc_self_energy_merge_fullelect_fep;
00238     ComputeNonbondedUtil::calcMergeSelfEnergy = calc_self_energy_merge_fullelect_fep;
00239     ComputeNonbondedUtil::calcSlowPair = calc_pair_energy_slow_fullelect_fep;
00240     ComputeNonbondedUtil::calcSlowPairEnergy = calc_pair_energy_slow_fullelect_fep;
00241     ComputeNonbondedUtil::calcSlowSelf = calc_self_energy_slow_fullelect_fep;
00242     ComputeNonbondedUtil::calcSlowSelfEnergy = calc_self_energy_slow_fullelect_fep;
00243   }  else if ( thermInt ) {
00244     lambda = simParams->lambda;
00245     ComputeNonbondedUtil::calcPair = calc_pair_ti;
00246     ComputeNonbondedUtil::calcPairEnergy = calc_pair_energy_ti;
00247     ComputeNonbondedUtil::calcSelf = calc_self_ti;
00248     ComputeNonbondedUtil::calcSelfEnergy = calc_self_energy_ti;
00249     ComputeNonbondedUtil::calcFullPair = calc_pair_fullelect_ti;
00250     ComputeNonbondedUtil::calcFullPairEnergy = calc_pair_energy_fullelect_ti;
00251     ComputeNonbondedUtil::calcFullSelf = calc_self_fullelect_ti;
00252     ComputeNonbondedUtil::calcFullSelfEnergy = calc_self_energy_fullelect_ti;
00253     ComputeNonbondedUtil::calcMergePair = calc_pair_merge_fullelect_ti;
00254     ComputeNonbondedUtil::calcMergePairEnergy = calc_pair_energy_merge_fullelect_ti;
00255     ComputeNonbondedUtil::calcMergeSelf = calc_self_merge_fullelect_ti;
00256     ComputeNonbondedUtil::calcMergeSelfEnergy = calc_self_energy_merge_fullelect_ti;
00257     ComputeNonbondedUtil::calcSlowPair = calc_pair_slow_fullelect_ti;
00258     ComputeNonbondedUtil::calcSlowPairEnergy = calc_pair_energy_slow_fullelect_ti;
00259     ComputeNonbondedUtil::calcSlowSelf = calc_self_slow_fullelect_ti;
00260     ComputeNonbondedUtil::calcSlowSelfEnergy = calc_self_energy_slow_fullelect_ti;
00261   } else if ( lesOn ) {
00262     lesFactor = simParams->lesFactor;
00263     lesScaling = 1.0 / (double)lesFactor;
00264     lambda_table = new BigReal[(lesFactor+1)*(lesFactor+1)];
00265     for ( int ip=0; ip<=lesFactor; ++ip ) {
00266       for ( int jp=0; jp<=lesFactor; ++jp ) {
00267         BigReal lambda_pair = 1.0;
00268         if (ip || jp ) {
00269           if (ip && jp && ip != jp) {
00270             lambda_pair = 0.0;
00271           } else {
00272             lambda_pair = lesScaling;
00273           }
00274         }
00275         lambda_table[(lesFactor+1)*ip+jp] = lambda_pair;
00276       }
00277     }
00278     ComputeNonbondedUtil::calcPair = calc_pair_les;
00279     ComputeNonbondedUtil::calcPairEnergy = calc_pair_energy_les;
00280     ComputeNonbondedUtil::calcSelf = calc_self_les;
00281     ComputeNonbondedUtil::calcSelfEnergy = calc_self_energy_les;
00282     ComputeNonbondedUtil::calcFullPair = calc_pair_fullelect_les;
00283     ComputeNonbondedUtil::calcFullPairEnergy = calc_pair_energy_fullelect_les;
00284     ComputeNonbondedUtil::calcFullSelf = calc_self_fullelect_les;
00285     ComputeNonbondedUtil::calcFullSelfEnergy = calc_self_energy_fullelect_les;
00286     ComputeNonbondedUtil::calcMergePair = calc_pair_merge_fullelect_les;
00287     ComputeNonbondedUtil::calcMergePairEnergy = calc_pair_energy_merge_fullelect_les;
00288     ComputeNonbondedUtil::calcMergeSelf = calc_self_merge_fullelect_les;
00289     ComputeNonbondedUtil::calcMergeSelfEnergy = calc_self_energy_merge_fullelect_les;
00290     ComputeNonbondedUtil::calcSlowPair = calc_pair_slow_fullelect_les;
00291     ComputeNonbondedUtil::calcSlowPairEnergy = calc_pair_energy_slow_fullelect_les;
00292     ComputeNonbondedUtil::calcSlowSelf = calc_self_slow_fullelect_les;
00293     ComputeNonbondedUtil::calcSlowSelfEnergy = calc_self_energy_slow_fullelect_les;
00294   } else if ( pressureProfileOn) {
00295     pressureProfileSlabs = simParams->pressureProfileSlabs;
00296     pressureProfileAtomTypes = simParams->pressureProfileAtomTypes;
00297 
00298     ComputeNonbondedUtil::calcPair = calc_pair_pprof;
00299     ComputeNonbondedUtil::calcPairEnergy = calc_pair_energy_pprof;
00300     ComputeNonbondedUtil::calcSelf = calc_self_pprof;
00301     ComputeNonbondedUtil::calcSelfEnergy = calc_self_energy_pprof;
00302     ComputeNonbondedUtil::calcFullPair = calc_pair_fullelect_pprof;
00303     ComputeNonbondedUtil::calcFullPairEnergy = calc_pair_energy_fullelect_pprof;
00304     ComputeNonbondedUtil::calcFullSelf = calc_self_fullelect_pprof;
00305     ComputeNonbondedUtil::calcFullSelfEnergy = calc_self_energy_fullelect_pprof;
00306     ComputeNonbondedUtil::calcMergePair = calc_pair_merge_fullelect_pprof;
00307     ComputeNonbondedUtil::calcMergePairEnergy = calc_pair_energy_merge_fullelect_pprof;
00308     ComputeNonbondedUtil::calcMergeSelf = calc_self_merge_fullelect_pprof;
00309     ComputeNonbondedUtil::calcMergeSelfEnergy = calc_self_energy_merge_fullelect_pprof;
00310     ComputeNonbondedUtil::calcSlowPair = calc_pair_slow_fullelect_pprof;
00311     ComputeNonbondedUtil::calcSlowPairEnergy = calc_pair_energy_slow_fullelect_pprof;
00312     ComputeNonbondedUtil::calcSlowSelf = calc_self_slow_fullelect_pprof;
00313     ComputeNonbondedUtil::calcSlowSelfEnergy = calc_self_energy_slow_fullelect_pprof;
00314   } else if ( pairInteractionOn ) {
00315     ComputeNonbondedUtil::calcPairEnergy = calc_pair_energy_int;
00316     ComputeNonbondedUtil::calcSelfEnergy = calc_self_energy_int;
00317     ComputeNonbondedUtil::calcFullPairEnergy = calc_pair_energy_fullelect_int;
00318     ComputeNonbondedUtil::calcFullSelfEnergy = calc_self_energy_fullelect_int;
00319     ComputeNonbondedUtil::calcMergePairEnergy = calc_pair_energy_merge_fullelect_int;
00320     ComputeNonbondedUtil::calcMergeSelfEnergy = calc_self_energy_merge_fullelect_int;
00321   } else {
00322     ComputeNonbondedUtil::calcPair = calc_pair;
00323     ComputeNonbondedUtil::calcPairEnergy = calc_pair_energy;
00324     ComputeNonbondedUtil::calcSelf = calc_self;
00325     ComputeNonbondedUtil::calcSelfEnergy = calc_self_energy;
00326     ComputeNonbondedUtil::calcFullPair = calc_pair_fullelect;
00327     ComputeNonbondedUtil::calcFullPairEnergy = calc_pair_energy_fullelect;
00328     ComputeNonbondedUtil::calcFullSelf = calc_self_fullelect;
00329     ComputeNonbondedUtil::calcFullSelfEnergy = calc_self_energy_fullelect;
00330     ComputeNonbondedUtil::calcMergePair = calc_pair_merge_fullelect;
00331     ComputeNonbondedUtil::calcMergePairEnergy = calc_pair_energy_merge_fullelect;
00332     ComputeNonbondedUtil::calcMergeSelf = calc_self_merge_fullelect;
00333     ComputeNonbondedUtil::calcMergeSelfEnergy = calc_self_energy_merge_fullelect;
00334     ComputeNonbondedUtil::calcSlowPair = calc_pair_slow_fullelect;
00335     ComputeNonbondedUtil::calcSlowPairEnergy = calc_pair_energy_slow_fullelect;
00336     ComputeNonbondedUtil::calcSlowSelf = calc_self_slow_fullelect;
00337     ComputeNonbondedUtil::calcSlowSelfEnergy = calc_self_energy_slow_fullelect;
00338   }
00339 
00340 //fepe
00341 
00342   dielectric_1 = 1.0/simParams->dielectric;
00343   if ( ! ljTable ) ljTable = new LJTable;
00344   mol = Node::Object()->molecule;
00345   scaling = simParams->nonbondedScaling;
00346   if ( simParams->exclude == SCALED14 )
00347   {
00348     scale14 = simParams->scale14;
00349   }
00350   else
00351   {
00352     scale14 = 1.;
00353   }
00354   if ( simParams->switchingActive )
00355   {
00356     switchOn = simParams->switchingDist;
00357     switchOn_1 = 1.0/switchOn;
00358     // d0 = 1.0/(cutoff-switchOn);
00359     switchOn2 = switchOn*switchOn;
00360     c0 = 1.0/(cutoff2-switchOn2);
00361   }
00362   else
00363   {
00364     switchOn = cutoff;
00365     switchOn_1 = 1.0/switchOn;
00366     // d0 = 0.;  // avoid division by zero
00367     switchOn2 = switchOn*switchOn;
00368     c0 = 0.;  // avoid division by zero
00369   }
00370   c1 = c0*c0*c0;
00371   c3 = 3.0 * (cutoff2 - switchOn2);
00372   c5 = 0;
00373   c6 = 0;
00374   c7 = 0;
00375   c8 = 0;
00376 
00377   const int PMEOn = simParams->PMEOn;
00378 
00379   if ( PMEOn ) {
00380     ewaldcof = simParams->PMEEwaldCoefficient;
00381     BigReal TwoBySqrtPi = 1.12837916709551;
00382     pi_ewaldcof = TwoBySqrtPi * ewaldcof;
00383   }
00384 
00385   int splitType = SPLIT_NONE;
00386   if ( simParams->switchingActive ) splitType = SPLIT_SHIFT;
00387   if ( simParams->fullDirectOn || simParams->FMAOn || PMEOn ) {
00388     switch ( simParams->longSplitting ) {
00389       case C1:
00390       splitType = SPLIT_C1;
00391       break;
00392 
00393       case XPLOR:
00394       NAMD_die("Sorry, XPLOR splitting not supported.");
00395       break;
00396 
00397       case SHARP:
00398       NAMD_die("Sorry, SHARP splitting not supported.");
00399       break;
00400 
00401       default:
00402       NAMD_die("Unknown splitting type found!");
00403 
00404     }
00405   }
00406 
00407   BigReal r2_tol = 0.1;
00408   
00409   r2_delta = 1.0;
00410   r2_delta_exp = 0;
00411   while ( r2_delta > r2_tol ) { r2_delta /= 2.0; r2_delta_exp += 1; }
00412   r2_delta_1 = 1.0 / r2_delta;
00413 
00414   if ( ! CkMyPe() ) {
00415     iout << iINFO << "NONBONDED TABLE R-SQUARED SPACING: " <<
00416                                 r2_delta << "\n" << endi;
00417   }
00418 
00419   BigReal r2_tmp = 1.0;
00420   int cutoff2_exp = 0;
00421   while ( (cutoff2 + r2_delta) > r2_tmp ) { r2_tmp *= 2.0; cutoff2_exp += 1; }
00422 
00423   int i;
00424   int n = (r2_delta_exp + cutoff2_exp) * 64 + 1;
00425 
00426   if ( ! CkMyPe() ) {
00427     iout << iINFO << "NONBONDED TABLE SIZE: " <<
00428                                 n << " POINTS\n" << endi;
00429   }
00430 
00431   if ( table_alloc ) delete [] table_alloc;
00432   table_alloc = new BigReal[61*n+16];
00433   BigReal *table_align = table_alloc;
00434   while ( ((long)table_align) % 128 ) ++table_align;
00435   table_noshort = table_align;
00436   table_short = table_align + 16*n;
00437   slow_table = table_align + 32*n;
00438   fast_table = table_align + 36*n;
00439   scor_table = table_align + 40*n;
00440   corr_table = table_align + 44*n;
00441   full_table = table_align + 48*n;
00442   vdwa_table = table_align + 52*n;
00443   vdwb_table = table_align + 56*n;
00444   r2_table = table_align + 60*n;
00445   BigReal *fast_i = fast_table + 4;
00446   BigReal *scor_i = scor_table + 4;
00447   BigReal *slow_i = slow_table + 4;
00448   BigReal *vdwa_i = vdwa_table + 4;
00449   BigReal *vdwb_i = vdwb_table + 4;
00450   BigReal *r2_i = r2_table;  *(r2_i++) = r2_delta;
00451   BigReal r2_limit = simParams->limitDist * simParams->limitDist;
00452   if ( r2_limit < r2_delta ) r2_limit = r2_delta;
00453   int r2_delta_i = 0;  // entry for r2 == r2_delta
00454 
00455   // fill in the table, fix up i==0 (r2==0) below
00456   for ( i=1; i<n; ++i ) {
00457 
00458     const BigReal r2_base = r2_delta * ( 1 << (i/64) );
00459     const BigReal r2_del = r2_base / 64.0;
00460     const BigReal r2 = r2_base - r2_delta + r2_del * (i%64);
00461 
00462     if ( r2 <= r2_limit ) r2_delta_i = i;
00463 
00464     const BigReal r = sqrt(r2);
00465     const BigReal r_1 = 1.0/r;
00466     const BigReal r_2 = 1.0/r2;
00467 
00468     // fast_ is defined as (full_ - slow_)
00469     // corr_ and fast_ are both zero at the cutoff, full_ is not
00470     // all three are approx 1/r at short distances
00471 
00472     // for actual interpolation, we use fast_ for fast forces and
00473     // scor_ = slow_ + corr_ - full_ and slow_ for slow forces
00474     // since these last two are of small magnitude
00475 
00476     BigReal fast_energy, fast_gradient;
00477     BigReal scor_energy, scor_gradient;
00478     BigReal slow_energy, slow_gradient;
00479 
00480     // corr_ is PME direct sum, or similar correction term
00481     // corr_energy is multiplied by r until later
00482     // corr_gradient is multiplied by -r^2 until later
00483     BigReal corr_energy, corr_gradient;
00484 
00485     
00486     if ( PMEOn ) {
00487       BigReal tmp_a = r * ewaldcof;
00488       BigReal tmp_b = erfc(tmp_a);
00489       corr_energy = tmp_b;
00490       corr_gradient = pi_ewaldcof*exp(-(tmp_a*tmp_a))*r + tmp_b;
00491     } else {
00492       corr_energy = corr_gradient = 0;
00493     }
00494 
00495     switch(splitType) {
00496       case SPLIT_NONE:
00497         fast_energy = 1.0/r;
00498         fast_gradient = -1.0/r2;
00499         scor_energy = scor_gradient = 0;
00500         slow_energy = slow_gradient = 0;
00501         break;
00502       case SPLIT_SHIFT: {
00503         BigReal shiftVal = r2/cutoff2 - 1.0;
00504         shiftVal *= shiftVal;
00505         BigReal dShiftVal = 2.0 * (r2/cutoff2 - 1.0) * 2.0*r/cutoff2;
00506         fast_energy = shiftVal/r;
00507         fast_gradient = dShiftVal/r - shiftVal/r2;
00508         scor_energy = scor_gradient = 0;
00509         slow_energy = slow_gradient = 0;
00510         } 
00511         break;
00512       case SPLIT_C1:
00513         // calculate actual energy and gradient
00514         slow_energy = 0.5/cutoff * (3.0 - (r2/cutoff2));
00515         slow_gradient = -1.0/cutoff2 * (r/cutoff);
00516         // calculate scor from slow and corr
00517         scor_energy = slow_energy + (corr_energy - 1.0)/r;
00518         scor_gradient = slow_gradient - (corr_gradient - 1.0)/r2;
00519         // calculate fast from slow
00520         fast_energy = 1.0/r - slow_energy;
00521         fast_gradient = -1.0/r2 - slow_gradient;
00522         break;
00523     }
00524 
00525     // foo_gradient is calculated as ( d foo_energy / d r )
00526     // and now divided by 2r to get ( d foo_energy / d r2 )
00527 
00528     fast_gradient *= 0.5 * r_1;
00529     scor_gradient *= 0.5 * r_1;
00530     slow_gradient *= 0.5 * r_1;
00531 
00532     // let modf be 1 if excluded, 1-scale14 if modified, 0 otherwise,
00533     // add scor_ - modf * slow_ to slow terms and
00534     // add fast_ - modf * fast_ to fast terms.
00535 
00536     BigReal vdwa_energy, vdwa_gradient;
00537     BigReal vdwb_energy, vdwb_gradient;
00538 
00539     const BigReal r_6 = r_2*r_2*r_2;
00540     const BigReal r_12 = r_6*r_6;
00541 
00542     // Lennard-Jones switching function
00543     const BigReal c2 = cutoff2-r2;
00544     const BigReal c4 = c2*(c3-2.0*c2);
00545     const BigReal switchVal =         // used for Lennard-Jones
00546                         ( r2 > switchOn2 ? c2*c4*c1 : 1.0 );
00547     const BigReal dSwitchVal =        // d switchVal / d r2
00548                         ( r2 > switchOn2 ? 2*c1*(c2*c2-c4) : 0.0 );
00549 
00550     vdwa_energy = switchVal * r_12;
00551     vdwb_energy = switchVal * r_6;
00552 
00553     vdwa_gradient = ( dSwitchVal - 6.0 * switchVal * r_2 ) * r_12;
00554     vdwb_gradient = ( dSwitchVal - 3.0 * switchVal * r_2 ) * r_6;
00555 
00556 
00557     *(fast_i++) = fast_energy;
00558     *(fast_i++) = fast_gradient;
00559     *(fast_i++) = 0;
00560     *(fast_i++) = 0;
00561     *(scor_i++) = scor_energy;
00562     *(scor_i++) = scor_gradient;
00563     *(scor_i++) = 0;
00564     *(scor_i++) = 0;
00565     *(slow_i++) = slow_energy;
00566     *(slow_i++) = slow_gradient;
00567     *(slow_i++) = 0;
00568     *(slow_i++) = 0;
00569     *(vdwa_i++) = vdwa_energy;
00570     *(vdwa_i++) = vdwa_gradient;
00571     *(vdwa_i++) = 0;
00572     *(vdwa_i++) = 0;
00573     *(vdwb_i++) = vdwb_energy;
00574     *(vdwb_i++) = vdwb_gradient;
00575     *(vdwb_i++) = 0;
00576     *(vdwb_i++) = 0;
00577     *(r2_i++) = r2 + r2_delta;
00578 
00579   }
00580 
00581   if ( ! r2_delta_i ) {
00582     NAMD_bug("Failed to find table entry for r2 == r2_limit\n");
00583   }
00584   if ( r2_table[r2_delta_i] > r2_limit + r2_delta ) {
00585     NAMD_bug("Found bad table entry for r2 == r2_limit\n");
00586   }
00587 
00588   int j;
00589   const char *table_name = "XXXX";
00590   int smooth_short = 0;
00591   for ( j=0; j<5; ++j ) {
00592     BigReal *t0 = 0;
00593     switch (j) {
00594       case 0: 
00595         t0 = fast_table;
00596         table_name = "FAST";
00597         smooth_short = 1;
00598       break;
00599       case 1: 
00600         t0 = scor_table;
00601         table_name = "SCOR";
00602         smooth_short = 0;
00603       break;
00604       case 2: 
00605         t0 = slow_table;
00606         table_name = "SLOW";
00607         smooth_short = 0;
00608       break;
00609       case 3: 
00610         t0 = vdwa_table;
00611         table_name = "VDWA";
00612         smooth_short = 1;
00613       break;
00614       case 4: 
00615         t0 = vdwb_table;
00616         table_name = "VDWB";
00617         smooth_short = 1;
00618       break;
00619     }
00620     // patch up data for i=0
00621     t0[0] = t0[4] - t0[5] * ( r2_delta / 64.0 );  // energy
00622     t0[1] = t0[5];  // gradient
00623     t0[2] = 0;
00624     t0[3] = 0;
00625     if ( smooth_short ) {
00626       BigReal energy0 = t0[4*r2_delta_i];
00627       BigReal gradient0 = t0[4*r2_delta_i+1];
00628       BigReal r20 = r2_table[r2_delta_i];
00629       t0[0] = energy0 - gradient0 * (r20 - r2_table[0]);  // energy
00630       t0[1] = gradient0;  // gradient
00631     }
00632     BigReal *t;
00633     for ( i=0,t=t0; i<(n-1); ++i,t+=4 ) {
00634       BigReal x = ( r2_delta * ( 1 << (i/64) ) ) / 64.0;
00635       if ( r2_table[i+1] != r2_table[i] + x ) {
00636         NAMD_bug("Bad table delta calculation.\n");
00637       }
00638       if ( smooth_short && i+1 < r2_delta_i ) {
00639         BigReal energy0 = t0[4*r2_delta_i];
00640         BigReal gradient0 = t0[4*r2_delta_i+1];
00641         BigReal r20 = r2_table[r2_delta_i];
00642         t[4] = energy0 - gradient0 * (r20 - r2_table[i+1]);  // energy
00643         t[5] = gradient0;  // gradient
00644       }
00645       BigReal v1 = t[0];
00646       BigReal g1 = t[1];
00647       BigReal v2 = t[4];
00648       BigReal g2 = t[5];
00649       // explicit formulas for v1 + g1 x + c x^2 + d x^3
00650       BigReal c = ( 3.0 * (v2 - v1) - x * (2.0 * g1 + g2) ) / ( x * x );
00651       BigReal d = ( -2.0 * (v2 - v1) + x * (g1 + g2) ) / ( x * x * x );
00652       // since v2 - v1 is imprecise, we refine c and d numerically
00653       // important because we need accurate forces (more than energies!)
00654       for ( int k=0; k < 2; ++k ) {
00655         BigReal dv = (v1 - v2) + ( ( d * x + c ) * x + g1 ) * x;
00656         BigReal dg = (g1 - g2) + ( 3.0 * d * x + 2.0 * c ) * x;
00657         c -= ( 3.0 * dv - x * dg ) / ( x * x );
00658         d -= ( -2.0 * dv + x * dg ) / ( x * x * x );
00659       }
00660       // store in the array;
00661       t[2] = c;  t[3] = d;
00662     }
00663 
00664     if ( ! CkMyPe() ) {
00665     BigReal dvmax = 0;
00666     BigReal dgmax = 0;
00667     BigReal dvmax_r = 0;
00668     BigReal dgmax_r = 0;
00669     BigReal fdvmax = 0;
00670     BigReal fdgmax = 0;
00671     BigReal fdvmax_r = 0;
00672     BigReal fdgmax_r = 0;
00673     for ( i=0,t=t0; i<(n-1); ++i,t+=4 ) {
00674       const BigReal r2_base = r2_delta * ( 1 << (i/64) );
00675       const BigReal r2_del = r2_base / 64.0;
00676       const BigReal r2 = r2_base - r2_delta + r2_del * (i%64);
00677       const BigReal r = sqrt(r2);
00678       BigReal x = r2_del;
00679       BigReal dv = ( ( t[3] * x + t[2] ) * x + t[1] ) * x + t[0] - t[4];
00680       BigReal dg = ( 3.0 * t[3] * x + 2.0 * t[2] ) * x + t[1] - t[5];
00681       if ( t[4] != 0. && fabs(dv/t[4]) > fdvmax ) {
00682         fdvmax = fabs(dv/t[4]); fdvmax_r = r;
00683       }
00684       if ( fabs(dv) > dvmax ) {
00685         dvmax = fabs(dv); dvmax_r = r;
00686       }
00687       if ( t[5] != 0. && fabs(dg/t[5]) > fdgmax ) {
00688         fdgmax = fabs(dg/t[5]); fdgmax_r = r;
00689       }
00690       if ( fabs(dg) > dgmax ) {
00691         dgmax = fabs(dg); dgmax_r = r;
00692       }
00693 #if 0
00694       if (dv != 0.) CkPrintf("TABLE %d ENERGY ERROR %g AT %g (%d)\n",j,dv,r,i);
00695       if (dg != 0.) CkPrintf("TABLE %d FORCE ERROR %g AT %g (%d)\n",j,dg,r,i);
00696 #endif
00697     }
00698     if ( dvmax != 0.0 ) {
00699       iout << iINFO << "ABSOLUTE IMPRECISION IN " << table_name <<
00700         " TABLE ENERGY: " << dvmax << " AT " << dvmax_r << "\n" << endi;
00701     }
00702     if ( fdvmax != 0.0 ) {
00703       iout << iINFO << "RELATIVE IMPRECISION IN " << table_name <<
00704         " TABLE ENERGY: " << fdvmax << " AT " << fdvmax_r << "\n" << endi;
00705     }
00706     if ( dgmax != 0.0 ) {
00707       iout << iINFO << "ABSOLUTE IMPRECISION IN " << table_name <<
00708         " TABLE FORCE: " << dgmax << " AT " << dgmax_r << "\n" << endi;
00709     }
00710     if ( fdgmax != 0.0 ) {
00711       iout << iINFO << "RELATIVE IMPRECISION IN " << table_name <<
00712         " TABLE FORCE: " << fdgmax << " AT " << fdgmax_r << "\n" << endi;
00713     }
00714     }
00715 
00716   }
00717 
00718   for ( i=0; i<4*n; ++i ) {
00719     corr_table[i] = fast_table[i] + scor_table[i];
00720     full_table[i] = fast_table[i] + slow_table[i];
00721   }
00722 
00723 #if 0  
00724   for ( i=0; i<n; ++i ) {
00725    for ( int j=0; j<4; ++j ) {
00726     table_short[16*i+6-2*j] = table_noshort[16*i+6-2*j] = vdwa_table[4*i+j];
00727     table_short[16*i+7-2*j] = table_noshort[16*i+7-2*j] = vdwb_table[4*i+j];
00728     table_short[16*i+8+3-j] = fast_table[4*i+j];
00729     table_short[16*i+12+3-j] = scor_table[4*i+j];
00730     table_noshort[16*i+8+3-j] = corr_table[4*i+j];
00731     table_noshort[16*i+12+3-j] = full_table[4*i+j];
00732    }
00733   }
00734 #endif 
00735 
00736   for ( i=0; i<n; ++i ) {
00737     table_short[16*i+ 0] = table_noshort[16*i+0] = -6.*vdwa_table[4*i+3];
00738     table_short[16*i+ 2] = table_noshort[16*i+2] = -6.*vdwb_table[4*i+3];
00739     table_short[16*i+ 4] = table_noshort[16*i+4] = -2.*vdwa_table[4*i+1];
00740     table_short[16*i+ 6] = table_noshort[16*i+6] = -2.*vdwb_table[4*i+1];
00741     
00742     table_short[16*i+1] = table_noshort[16*i+1] = -4.*vdwa_table[4*i+2];
00743     table_short[16*i+3] = table_noshort[16*i+3] = -4.*vdwb_table[4*i+2];
00744     table_short[16*i+5] = table_noshort[16*i+5] = -1.*vdwa_table[4*i+0];
00745     table_short[16*i+7] = table_noshort[16*i+7] = -1.*vdwb_table[4*i+0];
00746     
00747     table_short[16*i+8]  = -6.*fast_table[4*i+3];
00748     table_short[16*i+9]  = -4.*fast_table[4*i+2];
00749     table_short[16*i+10] = -2.*fast_table[4*i+1];
00750     table_short[16*i+11] = -1.*fast_table[4*i+0];
00751 
00752     table_noshort[16*i+8]  = -6.*corr_table[4*i+3];
00753     table_noshort[16*i+9]  = -4.*corr_table[4*i+2];
00754     table_noshort[16*i+10] = -2.*corr_table[4*i+1];
00755     table_noshort[16*i+11] = -1.*corr_table[4*i+0];
00756 
00757     table_short[16*i+12] = -6.*scor_table[4*i+3];
00758     table_short[16*i+13] = -4.*scor_table[4*i+2];
00759     table_short[16*i+14] = -2.*scor_table[4*i+1];
00760     table_short[16*i+15] = -1.*scor_table[4*i+0];
00761 
00762     table_noshort[16*i+12] = -6.*full_table[4*i+3];
00763     table_noshort[16*i+13] = -4.*full_table[4*i+2];
00764     table_noshort[16*i+14] = -2.*full_table[4*i+1];
00765     table_noshort[16*i+15] = -1.*full_table[4*i+0];
00766   }
00767 
00768 #if 0
00769   char fname[100];
00770   sprintf(fname,"/tmp/namd.table.pe%d.dat",CkMyPe());
00771   FILE *f = fopen(fname,"w");
00772   for ( i=0; i<(n-1); ++i ) {
00773     const BigReal r2_base = r2_delta * ( 1 << (i/64) );
00774     const BigReal r2_del = r2_base / 64.0;
00775     const BigReal r2 = r2_base - r2_delta + r2_del * (i%64);
00776     BigReal *t;
00777     if ( r2 + r2_delta != r2_table[i] ) fprintf(f,"r2 error! ");
00778     fprintf(f,"%g",r2);
00779     t = fast_table + 4*i;
00780     fprintf(f,"   %g %g %g %g", t[0], t[1], t[2], t[3]);
00781     t = scor_table + 4*i;
00782     fprintf(f,"   %g %g %g %g", t[0], t[1], t[2], t[3]);
00783     t = slow_table + 4*i;
00784     fprintf(f,"   %g %g %g %g", t[0], t[1], t[2], t[3]);
00785     t = corr_table + 4*i;
00786     fprintf(f,"   %g %g %g %g", t[0], t[1], t[2], t[3]);
00787     t = full_table + 4*i;
00788     fprintf(f,"   %g %g %g %g", t[0], t[1], t[2], t[3]);
00789     t = vdwa_table + 4*i;
00790     fprintf(f,"   %g %g %g %g", t[0], t[1], t[2], t[3]);
00791     t = vdwb_table + 4*i;
00792     fprintf(f,"   %g %g %g %g", t[0], t[1], t[2], t[3]);
00793     fprintf(f,"\n");
00794   }
00795   fclose(f);
00796 #endif
00797 
00798 }
00799 

Generated on Mon Sep 8 04:07:41 2008 for NAMD by  doxygen 1.3.9.1