00001
00007
00008
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
00060
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
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
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
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
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
00146
00147
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
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
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
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
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
00359 switchOn2 = switchOn*switchOn;
00360 c0 = 1.0/(cutoff2-switchOn2);
00361 }
00362 else
00363 {
00364 switchOn = cutoff;
00365 switchOn_1 = 1.0/switchOn;
00366
00367 switchOn2 = switchOn*switchOn;
00368 c0 = 0.;
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;
00454
00455
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
00469
00470
00471
00472
00473
00474
00475
00476 BigReal fast_energy, fast_gradient;
00477 BigReal scor_energy, scor_gradient;
00478 BigReal slow_energy, slow_gradient;
00479
00480
00481
00482
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
00514 slow_energy = 0.5/cutoff * (3.0 - (r2/cutoff2));
00515 slow_gradient = -1.0/cutoff2 * (r/cutoff);
00516
00517 scor_energy = slow_energy + (corr_energy - 1.0)/r;
00518 scor_gradient = slow_gradient - (corr_gradient - 1.0)/r2;
00519
00520 fast_energy = 1.0/r - slow_energy;
00521 fast_gradient = -1.0/r2 - slow_gradient;
00522 break;
00523 }
00524
00525
00526
00527
00528 fast_gradient *= 0.5 * r_1;
00529 scor_gradient *= 0.5 * r_1;
00530 slow_gradient *= 0.5 * r_1;
00531
00532
00533
00534
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
00543 const BigReal c2 = cutoff2-r2;
00544 const BigReal c4 = c2*(c3-2.0*c2);
00545 const BigReal switchVal =
00546 ( r2 > switchOn2 ? c2*c4*c1 : 1.0 );
00547 const BigReal dSwitchVal =
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
00621 t0[0] = t0[4] - t0[5] * ( r2_delta / 64.0 );
00622 t0[1] = t0[5];
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]);
00630 t0[1] = gradient0;
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]);
00643 t[5] = gradient0;
00644 }
00645 BigReal v1 = t[0];
00646 BigReal g1 = t[1];
00647 BigReal v2 = t[4];
00648 BigReal g2 = t[5];
00649
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
00653
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
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