void ComputeMgr:: recvComputeDPMEResults(ComputeDPMEResultsMsg *msg) { if ( computeDPMEObject ) { #ifdef DPME computeDPMEObject->recvResults(msg); #endif } else if ( ! (PatchMap::Object())->numHomePatches() ) delete msg; else NAMD_die("ComputeMgr::computeDPMEObject is NULL!"); }
void ComputeMgr:: recvComputeGlobalResults(ComputeGlobalResultsMsg *msg) { if ( computeGlobalObject ) { CmiEnableUrgentSend(1); computeGlobalObject->recvResults(msg); CmiEnableUrgentSend(0); } else if ( ! (PatchMap::Object())->numHomePatches() ) delete msg; else NAMD_die("ComputeMgr::computeGlobalObject is NULL!"); }
void ScriptTcl::doCallback(const char *labels, const char *data) { if ( ! callbackname ) return; int len = strlen(callbackname) + strlen(labels) + strlen(data) + 7; char *cmd = new char[len]; sprintf(cmd, "%s {%s} {%s}", callbackname, labels, data); int rval = Tcl_Eval(interp,cmd); delete [] cmd; if (rval != TCL_OK) { const char *errorInfo = Tcl_GetVar(interp,"errorInfo",0); NAMD_die(errorInfo); } }
void ComputeGridForce::doForce(FullAtom* p, Results* r) { SimParameters *simParams = Node::Object()->simParameters; Molecule *mol = Node::Object()->molecule; Force *forces = r->f[Results::normal]; BigReal energy = 0; Force extForce = 0.; Tensor extVirial; int numAtoms = homePatch->getNumAtoms(); if ( mol->numGridforceGrids < 1 ) NAMD_bug("No grids loaded in ComputeGridForce::doForce()"); for (int gridnum = 0; gridnum < mol->numGridforceGrids; gridnum++) { GridforceGrid *grid = mol->get_gridfrc_grid(gridnum); if (homePatch->flags.step % GF_OVERLAPCHECK_FREQ == 0) { // only check on node 0 and every GF_OVERLAPCHECK_FREQ steps if (simParams->langevinPistonOn || simParams->berendsenPressureOn) { // check for grid overlap if pressure control is on // not needed without pressure control, since the check is also performed on startup if (!grid->fits_lattice(homePatch->lattice)) { char errmsg[512]; if (simParams->gridforcechecksize) { sprintf(errmsg, "Warning: Periodic cell basis too small for Gridforce grid %d. Set gridforcechecksize off in configuration file to ignore.\n", gridnum); NAMD_die(errmsg); } } } } Position center = grid->get_center(); if (homePatch->flags.step % 100 == 1) { DebugM(3, "center = " << center << "\n" << endi); DebugM(3, "e = " << grid->get_e() << "\n" << endi); } if (grid->get_grid_type() == GridforceGrid::GridforceGridTypeFull) { GridforceFullMainGrid *g = (GridforceFullMainGrid *)grid; do_calc(g, gridnum, p, numAtoms, mol, forces, energy, extForce, extVirial); } else if (grid->get_grid_type() == GridforceGrid::GridforceGridTypeLite) { GridforceLiteGrid *g = (GridforceLiteGrid *)grid; do_calc(g, gridnum, p, numAtoms, mol, forces, energy, extForce, extVirial); } } reduction->item(REDUCTION_MISC_ENERGY) += energy; ADD_VECTOR_OBJECT(reduction,REDUCTION_EXT_FORCE_NORMAL,extForce); ADD_TENSOR_OBJECT(reduction,REDUCTION_VIRIAL_NORMAL,extVirial); reduction->submit(); }
int ScriptTcl::Tcl_output(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) { ScriptTcl *script = (ScriptTcl *)clientData; script->initcheck(); if (argc < 2) { Tcl_SetResult(interp,"too few args",TCL_VOLATILE); return TCL_ERROR; } if (argc > 3) { Tcl_SetResult(interp,"too many args",TCL_VOLATILE); return TCL_ERROR; } int filenamearg = argc-1; if (strlen(argv[filenamearg]) > MAX_SCRIPT_PARAM_SIZE) { Tcl_SetResult(interp,"file name too long",TCL_VOLATILE); return TCL_ERROR; } int dorestart = 1; int doforces = 0; if (argc == 3) { if ( ! strcmp(argv[1], "withforces") ) { doforces = 1; } else if ( ! strcmp(argv[1], "onlyforces") ) { dorestart = 0; doforces = 1; } else { Tcl_SetResult(interp, "first arg not withforces or onlyforces",TCL_VOLATILE); return TCL_ERROR; } } SimParameters *simParams = Node::Object()->simParameters; char oldname[MAX_SCRIPT_PARAM_SIZE+1]; strncpy(oldname,simParams->outputFilename,MAX_SCRIPT_PARAM_SIZE); script->setParameter("outputname",argv[filenamearg]); iout << "TCL: Writing to files with basename " << simParams->outputFilename << ".\n" << endi; if ( doforces && ! script->runWasCalled ) NAMD_die( "No forces to output; must call run or minimize first."); if ( dorestart ) script->runController(SCRIPT_OUTPUT); if ( doforces ) script->runController(SCRIPT_FORCEOUTPUT); script->setParameter("outputname",oldname); return TCL_OK; }
void ComputeMgr:: sendComputeDPMEData(ComputeDPMEDataMsg *msg) { if ( computeDPMEObject ) { #ifdef DPME int node = computeDPMEObject->getMasterNode(); CProxy_ComputeMgr cm(CkpvAccess(BOCclass_group).computeMgr); cm.recvComputeDPMEData(msg,node); #endif } else if ( ! (PatchMap::Object())->numHomePatches() ) delete msg; else NAMD_die("ComputeMgr::computeDPMEObject is NULL!"); }
int ScriptTcl::Tcl_abort(ClientData, Tcl_Interp *, int argc, char *argv[]) { Tcl_DString msg; Tcl_DStringInit(&msg); Tcl_DStringAppend(&msg,"TCL:",-1); for ( int i = 1; i < argc; ++i ) { Tcl_DStringAppend(&msg," ",-1); Tcl_DStringAppend(&msg,argv[i],-1); } NAMD_die(Tcl_DStringValue(&msg)); Tcl_DStringFree(&msg); return TCL_OK; }
// unregister submit from child void ReductionMgr::remoteUnregister(ReductionRegisterMsg *msg) { int setID = msg->reductionSetID; ReductionSet *set = reductionSets[setID]; if ( set->getData(set->nextSequenceNumber)->submitsRecorded ) { NAMD_die("SubmitReduction deleted while reductions outstanding on parent!"); } set->submitsRegistered--; delSet(setID); delete msg; }
// register require RequireReduction* ReductionMgr::willRequire(int setID, int size) { ReductionSet *set = getSet(setID,size); set->requireRegistered++; if ( set->getData(set->nextSequenceNumber)->submitsRecorded ) { NAMD_die("ReductionMgr::willRequire called while reductions outstanding!"); } RequireReduction *handle = new RequireReduction; handle->reductionSetID = setID; handle->sequenceNumber = set->nextSequenceNumber; handle->master = this; return handle; }
// possibly delete data for a particular seqNum ReductionSetData* ReductionSet::removeData(int seqNum) { ReductionSetData **current = &dataQueue; while ( *current ) { if ( (*current)->sequenceNumber == seqNum ) break; current = &((*current)->next); } if ( ! *current ) { NAMD_die("ReductionSet::removeData on missing seqNum"); } ReductionSetData *toremove = *current; *current = (*current)->next; return toremove; }
/* * Begin Ewald messages */ void ComputeMgr:: sendComputeEwaldData(ComputeEwaldMsg *msg) { if (computeEwaldObject) { int node = computeEwaldObject->getMasterNode(); CProxy_ComputeMgr cm(CkpvAccess(BOCclass_group).computeMgr); cm[node].recvComputeEwaldData(msg); } else if (!PatchMap::Object()->numHomePatches()) { CkPrintf("skipping message on Pe(%d)\n", CkMyPe()); delete msg; } else NAMD_die("ComputeMgr::computeEwaldObject is NULL!"); }
void ScriptTcl::load(char *scriptFile) { #ifdef NAMD_TCL int code = Tcl_EvalFile(interp,scriptFile); const char *result = Tcl_GetStringResult(interp); if (*result != 0) CkPrintf("TCL: %s\n",result); if (code != TCL_OK) { const char *errorInfo = Tcl_GetVar(interp,"errorInfo",0); NAMD_die(errorInfo); } #else NAMD_bug("ScriptTcl::load called without Tcl."); #endif }
void GlobalMasterFreeEnergy::initialize() { DebugM(4,"Initializing master\n"); // Get our script StringList *script = Node::Object()->configList->find("freeEnergyConfig"); config = new char[1]; config[0] = '\0'; for ( ; script; script = script->next) { if ( strstr(script->data,"\n") ) { size_t add_len = strlen(script->data); size_t config_len = 0; config_len = strlen(config); char *new_config = new char[config_len + add_len + 2]; strcpy(new_config,config); strcat(new_config,script->data); strcat(new_config,"\n"); // just to be safe delete [] config; config = new_config; } else { FILE *infile = fopen(script->data,"r"); if ( ! infile ) { char errmsg[256]; sprintf(errmsg,"Error trying to read file %s!\n",script->data); NAMD_die(errmsg); } fseek(infile,0,SEEK_END); size_t add_len = ftell(infile); size_t config_len = 0; config_len = strlen(config); char *new_config = new char[config_len + add_len + 3]; strcpy(new_config,config); delete [] config; config = new_config; new_config += config_len; rewind(infile); fread(new_config,sizeof(char),add_len,infile); new_config += add_len; new_config[0] = '\n'; new_config[1] = '\0'; fclose(infile); } } // iout << iDEBUG << "Free energy perturbation - initialize()\n" << endi; user_initialize(); }
void CollectionMaster::receiveDataStream(DataStreamMsg *msg) { if ( ! dataStreamFile ) { char *fname = Node::Object()->simParameters->auxFilename; // iout has large file linking issues on AIX // iout << iINFO << "OPENING AUXILIARY DATA STREAM FILE " // << fname << "\n" << endi; CkPrintf("Info: OPENING AUXILIARY DATA STREAM FILE %s\n", fname); NAMD_backup_file(fname); dataStreamFile = fopen(fname,"w"); if ( ! dataStreamFile ) NAMD_die("Can't open auxiliary data stream file!"); } fprintf(dataStreamFile,"%s",msg->data.begin()); fflush(dataStreamFile); delete msg; }
// register local submit SubmitReduction* ReductionMgr::willSubmit(int setID, int size) { ReductionSet *set = getSet(setID, size); ReductionSetData *data = set->getData(set->nextSequenceNumber); if ( data->submitsRecorded ) { NAMD_die("ReductionMgr::willSubmit called while reductions outstanding!"); } set->submitsRegistered++; SubmitReduction *handle = new SubmitReduction; handle->reductionSetID = setID; handle->sequenceNumber = set->nextSequenceNumber; handle->master = this; handle->data = data->data; return handle; }
// register submit from child void ReductionMgr::remoteRegister(ReductionRegisterMsg *msg) { int setID = msg->reductionSetID; int size = msg->dataSize; ReductionSet *set = getSet(setID,size); if ( set->getData(set->nextSequenceNumber)->submitsRecorded ) { NAMD_die("ReductionMgr::remoteRegister called while reductions outstanding on parent!"); } set->submitsRegistered++; set->addToRemoteSequenceNumber[childIndex(msg->sourceNode)] = set->nextSequenceNumber; // CkPrintf("[%d] reduction register received from node[%d] %d\n", // CkMyPe(),childIndex(msg->sourceNode),msg->sourceNode); delete msg; }
// common code for submission and delivery void ReductionMgr::mergeAndDeliver(ReductionSet *set, int seqNum) { //iout << "seq " << seqNum << " complete on " << CkMyPe() << "\n" << endi; set->nextSequenceNumber++; // should match all clients ReductionSetData *data = set->getData(seqNum); if ( data->submitsRecorded != set->submitsRegistered ) { NAMD_bug("ReductionMgr::mergeAndDeliver not ready to deliver."); } if ( isRoot() ) { if ( set->requireRegistered ) { if ( set->threadIsWaiting && set->waitingForSequenceNumber == seqNum) { // awaken the thread so it can take the data CthAwaken(set->waitingThread); } } else { NAMD_die("ReductionSet::deliver will never deliver data"); } } else { // send data to parent int size = set->dataSize; ReductionSubmitMsg *msg = new(&size,1) ReductionSubmitMsg; msg->reductionSetID = set->reductionSetID; msg->sourceNode = CkMyPe(); msg->sequenceNumber = seqNum; msg->dataSize = set->dataSize; for ( int i = 0; i < msg->dataSize; ++i ) { msg->data[i] = data->data[i]; } CProxy_ReductionMgr reductionProxy(thisgroup); reductionProxy[myParent].remoteSubmit(msg); delete set->removeData(seqNum); } }
int NamdState::configListInit(ConfigList *cfgList) { configList = cfgList; if (!configList->okay()) { NAMD_die("Simulation config file is incomplete or contains errors."); } DebugM(1,"NamdState::configFileInit configList okay\n"); char *currentdir = 0; simParameters = new SimParameters(configList,currentdir); fflush(stdout); lattice = simParameters->lattice; //Check features that are not supported in the memory optimized //version. --Chao Mei #ifdef MEM_OPT_VERSION checkMemOptCompatibility(); #endif //Check rigidBonds type when generating the compressed psf files. if(simParameters->genCompressedPsf) { if(simParameters->rigidBonds == RIGID_NONE){ //default to RIGID_ALL simParameters->rigidBonds = RIGID_ALL; } } StringList *molInfoFilename; // If it's AMBER force field, read the AMBER style files; // if it's GROMACS, read the GROMACS files; // Otherwise read the CHARMM style files if (simParameters->amberOn) { StringList *parmFilename = configList->find("parmfile"); molInfoFilename = parmFilename; StringList *coorFilename = configList->find("ambercoor"); // "amber" is a temporary data structure, which records all // the data from the parm file. After copying them into // molecule, parameter and pdb structures, it will be deleted. Ambertoppar *amber; amber = new Ambertoppar; if (amber->readparm(parmFilename->data)) { parameters = new Parameters(amber, simParameters->vdwscale14); molecule = new Molecule(simParameters, parameters, amber); if (coorFilename != NULL) pdb = new PDB(coorFilename->data,amber); delete amber; } else NAMD_die("Failed to read AMBER parm file!"); parameters->print_param_summary(); } else if (simParameters->gromacsOn) { StringList *topFilename = configList->find("grotopfile"); molInfoFilename = topFilename; StringList *coorFilename = configList->find("grocoorfile"); // "gromacsFile" is a temporary data structure, which records all // the data from the topology file. After copying it into the // molecule and parameter and pdb, it will be deleted. GromacsTopFile *gromacsFile; gromacsFile = new GromacsTopFile(topFilename->data); parameters = new Parameters(gromacsFile,simParameters->minimizeCGOn); if (coorFilename != NULL) pdb = new PDB(coorFilename->data,gromacsFile); molecule = new Molecule(simParameters, parameters, gromacsFile); // XXX does Molecule(needAll,these,arguments)? delete gromacsFile; // XXX unimplemented // XXX add error handling when the file doesn't exist // XXX make sure the right things happen when the parameters are // not even specified. // NAMD_die("Failed to read AMBER parm file!"); parameters->print_param_summary(); } else if (simParameters->usePluginIO){ #ifdef MEM_OPT_VERSION NAMD_die("Using plugin IO is not supported in memory optimized version!"); #else PluginIOMgr *pIOMgr = new PluginIOMgr(); iout << iWARN << "Plugin-based I/O is still in development and may still have bugs\n" << endi; molfile_plugin_t *pIOHandle = pIOMgr->getPlugin(); if (pIOHandle == NULL) { NAMD_die("ERROR: Failed to match requested plugin type"); } if ( pIOHandle->open_file_read == NULL ) NAMD_die("ERROR: Selected plugin type cannot open files"); if ( pIOHandle->read_structure == NULL ) NAMD_die("ERROR: Selected plugin type cannot read structures"); if ( pIOHandle->read_next_timestep == NULL ) NAMD_die("ERROR: Selected plugin type cannot read coordinates"); StringList *moleculeFilename = configList->find("structure"); molInfoFilename = moleculeFilename; StringList *parameterFilename = configList->find("parameters"); //****** BEGIN CHARMM/XPLOR type changes // For AMBER use different constructor based on parm_struct!!! -JCP parameters = new Parameters(simParameters, parameterFilename); parameters->print_param_summary(); int numAtoms = 0; //TODO: not sure about the name field in the handler void *plgFile = pIOHandle->open_file_read(moleculeFilename->data, pIOHandle->name, &numAtoms); if(plgFile == NULL) { NAMD_die("ERROR: Opening structure file failed!"); } double fileReadTime = CmiWallTimer(); molecule = new Molecule(simParameters, parameters, pIOHandle, plgFile, numAtoms); iout << iINFO << "TIME FOR LOAD MOLECULE STRUCTURE INFORMATION: " << CmiWallTimer() - fileReadTime << "\n" << endi; /* If we are only generating compressed molecule information, the PDB object is not needed */ if(!simParameters->genCompressedPsf) { fileReadTime = CmiWallTimer(); //get the occupancy data from the Molecule object and then free it //as it is stored in the Molecule object. pdb = new PDB(pIOHandle, plgFile, molecule->numAtoms, molecule->getOccupancyData(), molecule->getBFactorData()); molecule->freeOccupancyData(); molecule->freeBFactorData(); iout << iINFO << "TIME FOR LOADING ATOMS' COORDINATES INFORMATION: " << CmiWallTimer() - fileReadTime << "\n" << endi; } pIOHandle->close_file_read(plgFile); delete pIOMgr; #endif } else { StringList *moleculeFilename = configList->find("structure"); molInfoFilename = moleculeFilename; StringList *parameterFilename = configList->find("parameters"); //****** BEGIN CHARMM/XPLOR type changes // For AMBER use different constructor based on parm_struct!!! -JCP parameters = new Parameters(simParameters, parameterFilename); //****** END CHARMM/XPLOR type changes parameters->print_param_summary(); double fileReadTime = CmiWallTimer(); molecule = new Molecule(simParameters, parameters, moleculeFilename->data, configList); iout << iINFO << "TIME FOR READING PSF FILE: " << CmiWallTimer() - fileReadTime << "\n" << endi; } fflush(stdout); #ifdef MEM_OPT_VERSION //upon knowing the number of atoms, it's good time to estimate the number of //input/output processors if their value is not set if(simParameters->numinputprocs==0){ int numatoms = molecule->numAtoms; long estval = (sizeof(InputAtom)+2*sizeof(int)+1)*((long)(numatoms)); int numprocs = estval>>26; //considering every input proc consumes about 64M. if(numprocs==0){ numprocs=1; }else if(numprocs>CkNumPes()){ numprocs=CkNumPes(); } simParameters->numinputprocs=numprocs; }
/** * This function implements a strategy similar to the one used in the * centralized case in NamdCentLB. */ CLBMigrateMsg* NamdHybridLB::GrpLevelStrategy(LDStats* stats) { int numProcessors = stats->nprocs(); // number of processors at group level int numPatches = PatchMap::Object()->numPatches(); ComputeMap *computeMap = ComputeMap::Object(); const int numComputes = computeMap->numComputes(); const int numGroupComputes = stats->n_migrateobjs; const SimParameters* simParams = Node::Object()->simParameters; if ( ! processorArray ) processorArray = new processorInfo[numProcessors]; // these data structures are global and need to be distributed if ( ! patchArray ) patchArray = new patchInfo[numPatches]; if ( ! computeArray ) computeArray = new computeInfo[numGroupComputes]; if ( ! from_procs ) from_procs = new int[numGroupComputes]; int nMoveableComputes = buildData(stats); CmiAssert(nMoveableComputes <= numGroupComputes); #if LDB_DEBUG #define DUMP_LDBDATA 1 #define LOAD_LDBDATA 1 #endif #if DUMP_LDBDATA dumpDataASCII("ldbd_before", numProcessors, numPatches, nMoveableComputes); #elif LOAD_LDBDATA loadDataASCII("ldbd_before.5", numProcessors, numPatches, nMoveableComputes); // CkExit(); #endif double averageLoad = 0.; double avgCompute; double maxCompute; int maxComputeId; int numPesAvailable; { int i; double total = 0.; maxCompute = 0.; int maxi = 0; for (i=0; i<nMoveableComputes; i++) { double load = computeArray[i].load; total += load; if ( load > maxCompute ) { maxCompute = load; maxi = i; } } avgCompute = total / nMoveableComputes; maxComputeId = computeArray[maxi].handle.id.id[0]; int P = stats->nprocs(); numPesAvailable = 0; for (i=0; i<P; i++) { if (processorArray[i].available) { ++numPesAvailable; total += processorArray[i].backgroundLoad; } } if (numPesAvailable == 0) NAMD_die("No processors available for load balancing!\n"); averageLoad = total/numPesAvailable; } int i_split = 0; double maxUnsplit = 0.; if ( step() == 1 ) { for (int i=0; i<nMoveableComputes; i++) { const int cid = computeArray[i].handle.id.id[0]; if ( computeMap->numPartitions(cid) == 0 ) { const double load = computeArray[i].load; if ( load > maxUnsplit ) maxUnsplit = load; continue; } ++i_split; } } { SplitComputesMsg *msg = new(i_split,i_split) SplitComputesMsg; msg->maxUnsplit = maxUnsplit; msg->averageLoad = averageLoad; msg->avgCompute = avgCompute; msg->maxCompute = maxCompute; msg->maxComputeId = maxComputeId; msg->nMoveableComputes = nMoveableComputes; msg->numPesAvailable = numPesAvailable; msg->n = i_split; if ( step() == 1 ) { i_split = 0; for (int i=0; i<nMoveableComputes; i++) { computeArray[i].processor = computeArray[i].oldProcessor; const int cid = computeArray[i].handle.id.id[0]; if ( computeMap->numPartitions(cid) == 0 ) { continue; } msg->cid[i_split] = cid; msg->load[i_split] = computeArray[i].load; ++i_split; } } thisProxy[0].splitComputes(msg); } if ( step() == 1 ) { // compute splitting only } else if (simParams->ldbStrategy == LDBSTRAT_DEFAULT) { // default if (step() < 4) TorusLB(computeArray, patchArray, processorArray, nMoveableComputes, numPatches, numProcessors); else RefineTorusLB(computeArray, patchArray, processorArray, nMoveableComputes, numPatches, numProcessors, 1); } else if (simParams->ldbStrategy == LDBSTRAT_COMPREHENSIVE) { TorusLB(computeArray, patchArray, processorArray, nMoveableComputes, numPatches, numProcessors); } else if (simParams->ldbStrategy == LDBSTRAT_REFINEONLY) { RefineTorusLB(computeArray, patchArray, processorArray, nMoveableComputes, numPatches, numProcessors, 1); } else if (simParams->ldbStrategy == LDBSTRAT_OLD) { NAMD_die("Old load balancer strategy is not compatible with hybrid balancer."); if (step() < 4) Alg7(computeArray, patchArray, processorArray, nMoveableComputes, numPatches, numProcessors); else RefineOnly(computeArray, patchArray, processorArray, nMoveableComputes, numPatches, numProcessors); } #if LDB_DEBUG && USE_TOPOMAP TopoManager tmgr; int pe1, pe2, pe3, hops=0; /* This is double counting the hops for(int i=0; i<nMoveableComputes; i++) { pe1 = computeArray[i].processor; pe2 = patchArray[computeArray[i].patch1].processor; pe3 = patchArray[computeArray[i].patch2].processor; hops += tmgr.getHopsBetweenRanks(pe1, pe2); if(computeArray[i].patch1 != computeArray[i].patch2) hops += tmgr.getHopsBetweenRanks(pe1, pe3); }*/ for (int i=0; i<numPatches; i++) { //int num = patchArray[i].proxiesOn.numElements(); pe1 = patchArray[i].processor; Iterator nextProc; processorInfo *p = (processorInfo *)patchArray[i].proxiesOn.iterator((Iterator *)&nextProc); while (p) { pe2 = p->Id; hops += tmgr.getHopsBetweenRanks(pe1, pe2); p = (processorInfo *)patchArray[i].proxiesOn.next((Iterator*)&nextProc); } } CkPrintf("Load Balancing: Number of Hops: %d\n", hops); #endif #if DUMP_LDBDATA dumpDataASCII("ldbd_after", numProcessors, numPatches, nMoveableComputes); #elif LOAD_LDBDATA dumpDataASCII("ldbd_after.5", numProcessors, numPatches, nMoveableComputes); // loadDataASCII("ldbd_after", numProcessors, numPatches, nMoveableComputes); // CkExit(); #endif // For error checking: // Count up computes, to see if somebody doesn't have any computes int i; #if 0 int* computeCount = new int[numProcessors]; for(i=0; i<numProcessors; i++) computeCount[i]=0; for(i=0; i<nMoveableComputes; i++) computeCount[computeArray[i].processor]++; for(i=0; i<numProcessors; i++) { if (computeCount[i]==0) iout << iINFO <<"Warning: Processor " << i << " has NO moveable computes.\n" << endi; } delete [] computeCount; #endif CkVec<MigrateInfo *> migrateInfo; for(i=0;i<nMoveableComputes;i++) { if (computeArray[i].processor != from_procs[i]+stats->procs[0].pe) { /* CkPrintf("[%d] Obj %d migrating from %d (%d) to %d\n", CkMyPe(),computeArray[i].handle.id.id[0], from_procs[i], computeArray[i].oldProcessor, computeArray[i].processor); */ MigrateInfo *migrateMe = new MigrateInfo; migrateMe->obj = computeArray[i].handle; //migrateMe->from_pe = computeArray[i].oldProcessor; int frompe = from_procs[i]; if (frompe == numProcessors) frompe = -1; else frompe = frompe + stats->procs[0].pe; migrateMe->from_pe = frompe; migrateMe->to_pe = computeArray[i].processor; if (frompe == -1) { // don't know yet which processor this compute belongs to, but // inform receiver LDObjData obj; obj.handle = computeArray[i].handle; thisProxy[computeArray[i].processor].ObjMigrated(obj, NULL, 0, currentLevel-1); } migrateInfo.insertAtEnd(migrateMe); // sneak in updates to ComputeMap //ERASE CkPrintf("%d setting %d to processor %d\n",CkMyPe(),computeArray[i].handle.id.id[0],computeArray[i].processor); computeMap->setNewNode(computeArray[i].handle.id.id[0], computeArray[i].processor); } } // CkPrintf("LOAD BALANCING READY %d\n",CkMyPe()); LBMigrateMsg* msg; msg = createMigrateMsg(migrateInfo, numProcessors); peLoads = new double [numProcessors]; startPE = processorArray[0].Id; endPE = processorArray[numProcessors-1].Id; // CkPrintf("[%d] numProcessors=%d, %d to %d\n",CkMyPe(),numProcessors,processorArray[0].Id,processorArray[numProcessors-1].Id); for (i=0; i<numProcessors; i++) { peLoads[i] = processorArray[i].load; } delete [] from_procs; delete [] processorArray; delete [] patchArray; delete [] computeArray; from_procs = NULL; processorArray = NULL; patchArray = NULL; computeArray = NULL; return msg; }
int NAMD_read_line(FILE *fd, char *buf, int bufsize) { int i=0; // Current position in buf int c; // Character read in from file /* Loop and read characters until we get either an EOF or a */ /* newline */ while ( ((c=fgetc(fd)) != EOF) && (c != '\n') ) { /* If we encounter a bracketed comment, skip it. This */ /* basically means read EVERYTHING until the next } and*/ /* throw it into the big bit bucket */ if (c == '{') { while ( ((c=fgetc(fd)) != EOF) && (c!='}') ) { } if (c==EOF) { buf[i]=STRINGNULL; char *err_msg = new char[128 + strlen(buf)]; sprintf(err_msg, "ABNORMAL EOF FOUND - buffer=*%s*\n", buf); NAMD_die(err_msg); } continue; } /* Also, use this little piece of logic to remove */ /* any leading spaces from the line */ if ((i>0) || !isspace(c)) { buf[i] = c; i++; if ( i == bufsize ) { i--; buf[i]=STRINGNULL; char *err_msg = new char[128 + strlen(buf)]; sprintf(err_msg, "BUFFER OVERRUN - buffer=*%s*\n", buf); NAMD_die(err_msg); } } } /* NULL terminate the string */ buf[i]=STRINGNULL; /* Check for an EOF in the middle of a line */ if ((c==EOF) && (i!=0)) { buf[i]=STRINGNULL; char *err_msg = new char[128 + strlen(buf)]; sprintf(err_msg, "ABNORMAL EOF FOUND - buffer=*%s*\n", buf); NAMD_die(err_msg); } /* Return the appropriate value */ if (c==EOF) return(-1); else return(0); }
int NAMD_read_int(FILE *fd, const char *msg) { int i; // Loop counter int c; // Character read in from file char tmp_string[11]; // Temporary string for integer int isNeg; /* Skip white space */ while ( ((c=fgetc(fd)) == '\n') || isspace(c) ) { } /* Check to make sure we didn't hit EOF */ if (c==EOF) { char err_msg[128]; sprintf(err_msg, "EOF ENCOUNTERED READING %s FROM PSF FILE", msg); NAMD_die(err_msg); } /* Now read in the integer itself */ i=0; /* Modified to read an integer with '-' or '+' sign --Chao Mei */ isNeg = 0; if(c=='-'){ c = fgetc(fd); isNeg = 1; } if(c=='+') c = fgetc(fd); while (!isspace(c)) { /* Check to make sure we only get #'s */ if (!isdigit(c)) { char err_msg[128]; sprintf(err_msg, "ALPHA CHARCTER ENCOUNTERED WHILE READING %s FROM PSF FILE", msg); NAMD_die(err_msg); } tmp_string[i] = c; i++; c=fgetc(fd); /* Check to make sure we didn't hit EOF*/ if (c==EOF) { char err_msg[128]; sprintf(err_msg, "EOF ENCOUNTERED WHILE READING %s FROM PSF FILE", msg); NAMD_die(err_msg); } } tmp_string[i]=STRINGNULL; /* Convert the string to an integer and return its value */ if(isNeg) return(-atoi(tmp_string)); else return(atoi(tmp_string)); }
void ComputeMgr:: recvComputeEwaldData(ComputeEwaldMsg *msg) { if (computeEwaldObject) computeEwaldObject->recvData(msg); else NAMD_die("ComputeMgr::computeEwaldObject in recvData is NULL!"); }
void LdbCoordinator::initialize(PatchMap *pMap, ComputeMap *cMap, int reinit) { const SimParameters *simParams = Node::Object()->simParameters; #if 0 static int lbcreated = 0; // XXX static variables are unsafe for SMP // PE0 first time Create a load balancer if (CkMyPe() == 0 && !lbcreated) { if (simParams->ldbStrategy == LDBSTRAT_ALGNBOR) CreateNamdNborLB(); else { // CreateCentralLB(); CreateNamdCentLB(); } lbcreated = 1; } #endif // DebugM(10,"stepsPerLdbCycle initialized\n"); stepsPerLdbCycle = simParams->ldbPeriod; firstLdbStep = simParams->firstLdbStep; int lastLdbStep = simParams->lastLdbStep; int stepsPerCycle = simParams->stepsPerCycle; computeMap = cMap; patchMap = pMap; // Set the number of received messages correctly for node 0 nStatsMessagesExpected = Node::Object()->numNodes(); nStatsMessagesReceived = 0; if (patchNAtoms) delete [] patchNAtoms; // Depends on delete NULL to do nothing nPatches = patchMap->numPatches(); patchNAtoms = new int[nPatches]; typedef Sequencer *seqPtr; if ( ! reinit ) { delete [] sequencerThreads; // Depends on delete NULL to do nothing sequencerThreads = new seqPtr[nPatches]; } nLocalPatches=0; int i; for(i=0;i<nPatches;i++) { if (patchMap->node(i) == Node::Object()->myid()) { nLocalPatches++; patchNAtoms[i]=0; } else { patchNAtoms[i]=-1; } if ( ! reinit ) sequencerThreads[i]=NULL; } if ( ! reinit ) controllerThread = NULL; if (nLocalPatches != patchMap->numHomePatches()) NAMD_die("Disaggreement in patchMap data.\n"); const int oldNumComputes = numComputes; nLocalComputes = 0; numComputes = computeMap->numComputes(); for(i=0;i<numComputes;i++) { if ( (computeMap->node(i) == Node::Object()->myid()) && ( 0 #ifndef NAMD_CUDA || (computeMap->type(i) == computeNonbondedSelfType) || (computeMap->type(i) == computeNonbondedPairType) #endif || (computeMap->type(i) == computeLCPOType) || (computeMap->type(i) == computeSelfExclsType) || (computeMap->type(i) == computeSelfBondsType) || (computeMap->type(i) == computeSelfAnglesType) || (computeMap->type(i) == computeSelfDihedralsType) || (computeMap->type(i) == computeSelfImpropersType) || (computeMap->type(i) == computeSelfTholeType) || (computeMap->type(i) == computeSelfAnisoType) || (computeMap->type(i) == computeSelfCrosstermsType) || (computeMap->type(i) == computeBondsType) || (computeMap->type(i) == computeExclsType) || (computeMap->type(i) == computeAnglesType) || (computeMap->type(i) == computeDihedralsType) || (computeMap->type(i) == computeImpropersType) || (computeMap->type(i) == computeTholeType) || (computeMap->type(i) == computeAnisoType) || (computeMap->type(i) == computeCrosstermsType) ) ) { nLocalComputes++; } } // New LB frameworks registration // Allocate data structure to save incoming migrations. Processor // zero will get all migrations // If this is the first time through, we need it register patches if (ldbCycleNum == reg_all_objs) { if ( Node::Object()->simParameters->ldBalancer == LDBAL_CENTRALIZED ) { reg_all_objs = 3; } // Tell the lbdb that I'm registering objects, until I'm done // registering them. theLbdb->RegisteringObjects(myHandle); if ( ldbCycleNum == 1 ) { patchHandles = new LDObjHandle[nLocalPatches]; int patch_count=0; int i; for(i=0;i<nPatches;i++) if (patchMap->node(i) == Node::Object()->myid()) { LDObjid elemID; elemID.id[0] = i; elemID.id[1] = elemID.id[2] = elemID.id[3] = -2; if (patch_count >= nLocalPatches) { iout << iFILE << iERROR << iPE << "LdbCoordinator found too many local patches!" << endi; CkExit(); } HomePatch *p = patchMap->homePatch(i); p->ldObjHandle = patchHandles[patch_count] = theLbdb->RegisterObj(myHandle,elemID,0,0); patch_count++; } } if ( numComputes > oldNumComputes ) { // Register computes for(i=oldNumComputes; i<numComputes; i++) { if ( computeMap->node(i) == Node::Object()->myid()) { if ( 0 #ifndef NAMD_CUDA || (computeMap->type(i) == computeNonbondedSelfType) || (computeMap->type(i) == computeNonbondedPairType) #endif || (computeMap->type(i) == computeLCPOType) || (computeMap->type(i) == computeSelfExclsType) || (computeMap->type(i) == computeSelfBondsType) || (computeMap->type(i) == computeSelfAnglesType) || (computeMap->type(i) == computeSelfDihedralsType) || (computeMap->type(i) == computeSelfImpropersType) || (computeMap->type(i) == computeSelfTholeType) || (computeMap->type(i) == computeSelfAnisoType) || (computeMap->type(i) == computeSelfCrosstermsType) ) { // Register the object with the load balancer // Store the depended patch IDs in the rest of the element ID LDObjid elemID; elemID.id[0] = i; if (computeMap->numPids(i) > 2) elemID.id[3] = computeMap->pid(i,2); else elemID.id[3] = -1; if (computeMap->numPids(i) > 1) elemID.id[2] = computeMap->pid(i,1); else elemID.id[2] = -1; if (computeMap->numPids(i) > 0) elemID.id[1] = computeMap->pid(i,0); else elemID.id[1] = -1; Compute *c = computeMap->compute(i); if ( ! c ) NAMD_bug("LdbCoordinator::initialize() null compute pointer"); c->ldObjHandle = theLbdb->RegisterObj(myHandle,elemID,0,1); } else if ( (computeMap->type(i) == computeBondsType) || (computeMap->type(i) == computeExclsType) || (computeMap->type(i) == computeAnglesType) || (computeMap->type(i) == computeDihedralsType) || (computeMap->type(i) == computeImpropersType) || (computeMap->type(i) == computeTholeType) || (computeMap->type(i) == computeAnisoType) || (computeMap->type(i) == computeCrosstermsType) ) { // Register the object with the load balancer // Store the depended patch IDs in the rest of the element ID LDObjid elemID; elemID.id[0] = i; elemID.id[1] = elemID.id[2] = elemID.id[3] = -3; Compute *c = computeMap->compute(i); if ( ! c ) NAMD_bug("LdbCoordinator::initialize() null compute pointer"); c->ldObjHandle = theLbdb->RegisterObj(myHandle,elemID,0,0); } } } } theLbdb->DoneRegisteringObjects(myHandle); } // process saved migration messages, if any while ( migrateMsgs ) { LdbMigrateMsg *m = migrateMsgs; migrateMsgs = m->next; Compute *c = computeMap->compute(m->handle.id.id[0]); if ( ! c ) NAMD_bug("LdbCoordinator::initialize() null compute pointer 2"); c->ldObjHandle = m->handle; delete m; } // Fixup to take care of the extra timestep at startup // This is pretty ugly here, but it makes the count correct // iout << "LDB Cycle Num: " << ldbCycleNum << "\n"; if ( simParams->ldBalancer == LDBAL_CENTRALIZED ) { if (ldbCycleNum == 1 || ldbCycleNum == 3) { numStepsToRun = stepsPerCycle; totalStepsDone += numStepsToRun; takingLdbData = 0; theLbdb->CollectStatsOff(); } else if (ldbCycleNum == 2 || ldbCycleNum == 4) { numStepsToRun = firstLdbStep - stepsPerCycle; while ( numStepsToRun <= 0 ) numStepsToRun += stepsPerCycle; totalStepsDone += numStepsToRun; takingLdbData = 1; theLbdb->CollectStatsOn(); } else if ( (ldbCycleNum <= 6) || !takingLdbData ) { totalStepsDone += firstLdbStep; if(lastLdbStep != -1 && totalStepsDone > lastLdbStep) { numStepsToRun = -1; takingLdbData = 0; theLbdb->CollectStatsOff(); } else { numStepsToRun = firstLdbStep; takingLdbData = 1; theLbdb->CollectStatsOn(); } } else { totalStepsDone += stepsPerLdbCycle - firstLdbStep; if(lastLdbStep != -1 && totalStepsDone > lastLdbStep) { numStepsToRun = -1; takingLdbData = 0; theLbdb->CollectStatsOff(); } else { numStepsToRun = stepsPerLdbCycle - firstLdbStep; takingLdbData = 0; theLbdb->CollectStatsOff(); } } } else { if (ldbCycleNum==1) { totalStepsDone += firstLdbStep; numStepsToRun = firstLdbStep; takingLdbData = 0; theLbdb->CollectStatsOff(); } else if ( (ldbCycleNum <= 4) || !takingLdbData ) { totalStepsDone += firstLdbStep; if(lastLdbStep != -1 && totalStepsDone > lastLdbStep) { numStepsToRun = -1; takingLdbData = 0; theLbdb->CollectStatsOff(); } else { numStepsToRun = firstLdbStep; takingLdbData = 1; theLbdb->CollectStatsOn(); } } else { totalStepsDone += stepsPerLdbCycle - firstLdbStep; if(lastLdbStep != -1 && totalStepsDone > lastLdbStep) { numStepsToRun = -1; takingLdbData = 0; theLbdb->CollectStatsOff(); } else { numStepsToRun = stepsPerLdbCycle - firstLdbStep; takingLdbData = 0; theLbdb->CollectStatsOff(); } } } /*-----------------------------------------------------------------------------* * --------------------------------------------------------------------------- * * Comments inserted by Abhinav to clarify relation between ldbCycleNum, * * load balancing step numbers (printed by the step() function) and * * tracing of the steps * * --------------------------------------------------------------------------- * * If trace is turned off in the beginning, then tracing is turned on * * at ldbCycleNum = 4 and turned off at ldbCycleNum = 8. ldbCycleNum can * * be adjusted by specifying firstLdbStep and ldbPeriod which are set by * * default to 5*stepspercycle and 200*stepspercycle if not specified. * * * * If we choose firstLdbStep = 20 and ldbPeriod = 100, we have the * * following timeline (for these particular numbers): * * * * Tracing : <------ off ------><------------- on -----------><-- off * * Ldb Step() No : 1 2 3 4 5 6 7 * * Iteration Steps : 00====20====40====60====80======160====180=====260====280 * * ldbCycleNum : 1 2 3 4 5 6 7 8 9 * * Instrumention : Inst Inst Inst Inst Inst * * LDB Strategy : TLB RLB RLB RLB RLB * * * * TLB = TorusLB * * RLB = RefineTorusLB * * Inst = Instrumentation Phase (no real load balancing) * * --------------------------------------------------------------------------- * *-----------------------------------------------------------------------------* */ #if 0 //replaced by traceBarrier at Controller and Sequencer if (traceAvailable()) { static int specialTracing = 0; // XXX static variables are unsafe for SMP if (ldbCycleNum == 1 && traceIsOn() == 0) specialTracing = 1; if (specialTracing) { if (ldbCycleNum == 4) traceBegin(); if (ldbCycleNum == 8) traceEnd(); } } #endif nPatchesReported = 0; nPatchesExpected = nLocalPatches; nComputesReported = 0; nComputesExpected = nLocalComputes * numStepsToRun; controllerReported = 0; controllerExpected = ! CkMyPe(); if (CkMyPe() == 0) { if (computeArray == NULL) computeArray = new computeInfo[numComputes]; if (patchArray == NULL) patchArray = new patchInfo[nPatches]; if (processorArray == NULL) processorArray = new processorInfo[CkNumPes()]; } theLbdb->ClearLoads(); }
void ComputeNonbondedUtil::select(void) { if ( CkMyRank() ) return; // These defaults die cleanly if nothing appropriate is assigned. ComputeNonbondedUtil::calcPair = calc_error; ComputeNonbondedUtil::calcPairEnergy = calc_error; ComputeNonbondedUtil::calcSelf = calc_error; ComputeNonbondedUtil::calcSelfEnergy = calc_error; ComputeNonbondedUtil::calcFullPair = calc_error; ComputeNonbondedUtil::calcFullPairEnergy = calc_error; ComputeNonbondedUtil::calcFullSelf = calc_error; ComputeNonbondedUtil::calcFullSelfEnergy = calc_error; ComputeNonbondedUtil::calcMergePair = calc_error; ComputeNonbondedUtil::calcMergePairEnergy = calc_error; ComputeNonbondedUtil::calcMergeSelf = calc_error; ComputeNonbondedUtil::calcMergeSelfEnergy = calc_error; ComputeNonbondedUtil::calcSlowPair = calc_error; ComputeNonbondedUtil::calcSlowPairEnergy = calc_error; ComputeNonbondedUtil::calcSlowSelf = calc_error; ComputeNonbondedUtil::calcSlowSelfEnergy = calc_error; SimParameters * simParams = Node::Object()->simParameters; Parameters * params = Node::Object()->parameters; table_ener = params->table_ener; rowsize = params->rowsize; columnsize = params->columnsize; commOnly = simParams->commOnly; fixedAtomsOn = ( simParams->fixedAtomsOn && ! simParams->fixedAtomsForces ); cutoff = simParams->cutoff; cutoff2 = cutoff*cutoff; //fepb alchFepOn = simParams->alchFepOn; Fep_WCA_repuOn = simParams->alchFepWCARepuOn; Fep_WCA_dispOn = simParams->alchFepWCADispOn; alchThermIntOn = simParams->alchThermIntOn; alchLambda = alchLambda2 = 0; lesOn = simParams->lesOn; lesScaling = lesFactor = 0; Bool tabulatedEnergies = simParams->tabulatedEnergies; alchVdwShiftCoeff = simParams->alchVdwShiftCoeff; WCA_rcut1 = simParams->alchFepWCArcut1; WCA_rcut2 = simParams->alchFepWCArcut2; alchVdwLambdaEnd = simParams->alchVdwLambdaEnd; alchElecLambdaStart = simParams->alchElecLambdaStart; alchDecouple = simParams->alchDecouple; delete [] lambda_table; lambda_table = 0; pairInteractionOn = simParams->pairInteractionOn; pairInteractionSelf = simParams->pairInteractionSelf; pressureProfileOn = simParams->pressureProfileOn; // Ported by JLai -- Original JE - Go goForcesOn = simParams->goForcesOn; goMethod = simParams->goMethod; // End of port accelMDOn = simParams->accelMDOn; drudeNbthole = simParams->drudeOn && (simParams->drudeNbtholeCut > 0.0); if ( drudeNbthole ) { #ifdef NAMD_CUDA NAMD_die("drudeNbthole is not supported in CUDA version"); #endif if ( alchFepOn ) NAMD_die("drudeNbthole is not supported with alchemical free-energy perturbation"); if ( alchThermIntOn ) NAMD_die("drudeNbthole is not supported with alchemical thermodynamic integration"); if ( lesOn ) NAMD_die("drudeNbthole is not supported with locally enhanced sampling"); if ( pairInteractionOn ) NAMD_die("drudeNbthole is not supported with pair interaction calculation"); if ( pressureProfileOn ) NAMD_die("drudeNbthole is not supported with pressure profile calculation"); } if ( alchFepOn ) { #ifdef NAMD_CUDA NAMD_die("Alchemical free-energy perturbation is not supported in CUDA version"); #endif alchLambda = simParams->alchLambda; alchLambda2 = simParams->alchLambda2; ComputeNonbondedUtil::calcPair = calc_pair_energy_fep; ComputeNonbondedUtil::calcPairEnergy = calc_pair_energy_fep; ComputeNonbondedUtil::calcSelf = calc_self_energy_fep; ComputeNonbondedUtil::calcSelfEnergy = calc_self_energy_fep; ComputeNonbondedUtil::calcFullPair = calc_pair_energy_fullelect_fep; ComputeNonbondedUtil::calcFullPairEnergy = calc_pair_energy_fullelect_fep; ComputeNonbondedUtil::calcFullSelf = calc_self_energy_fullelect_fep; ComputeNonbondedUtil::calcFullSelfEnergy = calc_self_energy_fullelect_fep; ComputeNonbondedUtil::calcMergePair = calc_pair_energy_merge_fullelect_fep; ComputeNonbondedUtil::calcMergePairEnergy = calc_pair_energy_merge_fullelect_fep; ComputeNonbondedUtil::calcMergeSelf = calc_self_energy_merge_fullelect_fep; ComputeNonbondedUtil::calcMergeSelfEnergy = calc_self_energy_merge_fullelect_fep; ComputeNonbondedUtil::calcSlowPair = calc_pair_energy_slow_fullelect_fep; ComputeNonbondedUtil::calcSlowPairEnergy = calc_pair_energy_slow_fullelect_fep; ComputeNonbondedUtil::calcSlowSelf = calc_self_energy_slow_fullelect_fep; ComputeNonbondedUtil::calcSlowSelfEnergy = calc_self_energy_slow_fullelect_fep; } else if ( alchThermIntOn ) { #ifdef NAMD_CUDA NAMD_die("Alchemical thermodynamic integration is not supported in CUDA version"); #endif alchLambda = simParams->alchLambda; ComputeNonbondedUtil::calcPair = calc_pair_ti; ComputeNonbondedUtil::calcPairEnergy = calc_pair_energy_ti; ComputeNonbondedUtil::calcSelf = calc_self_ti; ComputeNonbondedUtil::calcSelfEnergy = calc_self_energy_ti; ComputeNonbondedUtil::calcFullPair = calc_pair_fullelect_ti; ComputeNonbondedUtil::calcFullPairEnergy = calc_pair_energy_fullelect_ti; ComputeNonbondedUtil::calcFullSelf = calc_self_fullelect_ti; ComputeNonbondedUtil::calcFullSelfEnergy = calc_self_energy_fullelect_ti; ComputeNonbondedUtil::calcMergePair = calc_pair_merge_fullelect_ti; ComputeNonbondedUtil::calcMergePairEnergy = calc_pair_energy_merge_fullelect_ti; ComputeNonbondedUtil::calcMergeSelf = calc_self_merge_fullelect_ti; ComputeNonbondedUtil::calcMergeSelfEnergy = calc_self_energy_merge_fullelect_ti; ComputeNonbondedUtil::calcSlowPair = calc_pair_slow_fullelect_ti; ComputeNonbondedUtil::calcSlowPairEnergy = calc_pair_energy_slow_fullelect_ti; ComputeNonbondedUtil::calcSlowSelf = calc_self_slow_fullelect_ti; ComputeNonbondedUtil::calcSlowSelfEnergy = calc_self_energy_slow_fullelect_ti; } else if ( lesOn ) { #ifdef NAMD_CUDA NAMD_die("Locally enhanced sampling is not supported in CUDA version"); #endif lesFactor = simParams->lesFactor; lesScaling = 1.0 / (double)lesFactor; lambda_table = new BigReal[(lesFactor+1)*(lesFactor+1)]; for ( int ip=0; ip<=lesFactor; ++ip ) { for ( int jp=0; jp<=lesFactor; ++jp ) { BigReal lambda_pair = 1.0; if (ip || jp ) { if (ip && jp && ip != jp) { lambda_pair = 0.0; } else { lambda_pair = lesScaling; } } lambda_table[(lesFactor+1)*ip+jp] = lambda_pair; } } ComputeNonbondedUtil::calcPair = calc_pair_les; ComputeNonbondedUtil::calcPairEnergy = calc_pair_energy_les; ComputeNonbondedUtil::calcSelf = calc_self_les; ComputeNonbondedUtil::calcSelfEnergy = calc_self_energy_les; ComputeNonbondedUtil::calcFullPair = calc_pair_fullelect_les; ComputeNonbondedUtil::calcFullPairEnergy = calc_pair_energy_fullelect_les; ComputeNonbondedUtil::calcFullSelf = calc_self_fullelect_les; ComputeNonbondedUtil::calcFullSelfEnergy = calc_self_energy_fullelect_les; ComputeNonbondedUtil::calcMergePair = calc_pair_merge_fullelect_les; ComputeNonbondedUtil::calcMergePairEnergy = calc_pair_energy_merge_fullelect_les; ComputeNonbondedUtil::calcMergeSelf = calc_self_merge_fullelect_les; ComputeNonbondedUtil::calcMergeSelfEnergy = calc_self_energy_merge_fullelect_les; ComputeNonbondedUtil::calcSlowPair = calc_pair_slow_fullelect_les; ComputeNonbondedUtil::calcSlowPairEnergy = calc_pair_energy_slow_fullelect_les; ComputeNonbondedUtil::calcSlowSelf = calc_self_slow_fullelect_les; ComputeNonbondedUtil::calcSlowSelfEnergy = calc_self_energy_slow_fullelect_les; } else if ( pressureProfileOn) { #ifdef NAMD_CUDA NAMD_die("Pressure profile calculation is not supported in CUDA version"); #endif pressureProfileSlabs = simParams->pressureProfileSlabs; pressureProfileAtomTypes = simParams->pressureProfileAtomTypes; ComputeNonbondedUtil::calcPair = calc_pair_pprof; ComputeNonbondedUtil::calcPairEnergy = calc_pair_energy_pprof; ComputeNonbondedUtil::calcSelf = calc_self_pprof; ComputeNonbondedUtil::calcSelfEnergy = calc_self_energy_pprof; ComputeNonbondedUtil::calcFullPair = calc_pair_fullelect_pprof; ComputeNonbondedUtil::calcFullPairEnergy = calc_pair_energy_fullelect_pprof; ComputeNonbondedUtil::calcFullSelf = calc_self_fullelect_pprof; ComputeNonbondedUtil::calcFullSelfEnergy = calc_self_energy_fullelect_pprof; ComputeNonbondedUtil::calcMergePair = calc_pair_merge_fullelect_pprof; ComputeNonbondedUtil::calcMergePairEnergy = calc_pair_energy_merge_fullelect_pprof; ComputeNonbondedUtil::calcMergeSelf = calc_self_merge_fullelect_pprof; ComputeNonbondedUtil::calcMergeSelfEnergy = calc_self_energy_merge_fullelect_pprof; ComputeNonbondedUtil::calcSlowPair = calc_pair_slow_fullelect_pprof; ComputeNonbondedUtil::calcSlowPairEnergy = calc_pair_energy_slow_fullelect_pprof; ComputeNonbondedUtil::calcSlowSelf = calc_self_slow_fullelect_pprof; ComputeNonbondedUtil::calcSlowSelfEnergy = calc_self_energy_slow_fullelect_pprof; } else if ( pairInteractionOn ) { #ifdef NAMD_CUDA NAMD_die("Pair interaction calculation is not supported in CUDA version"); #endif ComputeNonbondedUtil::calcPairEnergy = calc_pair_energy_int; ComputeNonbondedUtil::calcSelfEnergy = calc_self_energy_int; ComputeNonbondedUtil::calcFullPairEnergy = calc_pair_energy_fullelect_int; ComputeNonbondedUtil::calcFullSelfEnergy = calc_self_energy_fullelect_int; ComputeNonbondedUtil::calcMergePairEnergy = calc_pair_energy_merge_fullelect_int; ComputeNonbondedUtil::calcMergeSelfEnergy = calc_self_energy_merge_fullelect_int; } else if ( tabulatedEnergies ) { #ifdef NAMD_CUDA NAMD_die("Tabulated energies is not supported in CUDA version"); #endif ComputeNonbondedUtil::calcPair = calc_pair_tabener; ComputeNonbondedUtil::calcPairEnergy = calc_pair_energy_tabener; ComputeNonbondedUtil::calcSelf = calc_self_tabener; ComputeNonbondedUtil::calcSelfEnergy = calc_self_energy_tabener; ComputeNonbondedUtil::calcFullPair = calc_pair_fullelect_tabener; ComputeNonbondedUtil::calcFullPairEnergy = calc_pair_energy_fullelect_tabener; ComputeNonbondedUtil::calcFullSelf = calc_self_fullelect_tabener; ComputeNonbondedUtil::calcFullSelfEnergy = calc_self_energy_fullelect_tabener; ComputeNonbondedUtil::calcMergePair = calc_pair_merge_fullelect_tabener; ComputeNonbondedUtil::calcMergePairEnergy = calc_pair_energy_merge_fullelect_tabener; ComputeNonbondedUtil::calcMergeSelf = calc_self_merge_fullelect_tabener; ComputeNonbondedUtil::calcMergeSelfEnergy = calc_self_energy_merge_fullelect_tabener; ComputeNonbondedUtil::calcSlowPair = calc_pair_slow_fullelect_tabener; ComputeNonbondedUtil::calcSlowPairEnergy = calc_pair_energy_slow_fullelect_tabener; ComputeNonbondedUtil::calcSlowSelf = calc_self_slow_fullelect_tabener; ComputeNonbondedUtil::calcSlowSelfEnergy = calc_self_energy_slow_fullelect_tabener; } else if ( goForcesOn ) { #ifdef NAMD_CUDA NAMD_die("Go forces is not supported in CUDA version"); #endif ComputeNonbondedUtil::calcPair = calc_pair_go; ComputeNonbondedUtil::calcPairEnergy = calc_pair_energy_go; ComputeNonbondedUtil::calcSelf = calc_self_go; ComputeNonbondedUtil::calcSelfEnergy = calc_self_energy_go; ComputeNonbondedUtil::calcFullPair = calc_pair_fullelect_go; ComputeNonbondedUtil::calcFullPairEnergy = calc_pair_energy_fullelect_go; ComputeNonbondedUtil::calcFullSelf = calc_self_fullelect_go; ComputeNonbondedUtil::calcFullSelfEnergy = calc_self_energy_fullelect_go; ComputeNonbondedUtil::calcMergePair = calc_pair_merge_fullelect_go; ComputeNonbondedUtil::calcMergePairEnergy = calc_pair_energy_merge_fullelect_go; ComputeNonbondedUtil::calcMergeSelf = calc_self_merge_fullelect_go; ComputeNonbondedUtil::calcMergeSelfEnergy = calc_self_energy_merge_fullelect_go; ComputeNonbondedUtil::calcSlowPair = calc_pair_slow_fullelect_go; ComputeNonbondedUtil::calcSlowPairEnergy = calc_pair_energy_slow_fullelect_go; ComputeNonbondedUtil::calcSlowSelf = calc_self_slow_fullelect_go; ComputeNonbondedUtil::calcSlowSelfEnergy = calc_self_energy_slow_fullelect_go; } else { ComputeNonbondedUtil::calcPair = calc_pair; ComputeNonbondedUtil::calcPairEnergy = calc_pair_energy; ComputeNonbondedUtil::calcSelf = calc_self; ComputeNonbondedUtil::calcSelfEnergy = calc_self_energy; ComputeNonbondedUtil::calcFullPair = calc_pair_fullelect; ComputeNonbondedUtil::calcFullPairEnergy = calc_pair_energy_fullelect; ComputeNonbondedUtil::calcFullSelf = calc_self_fullelect; ComputeNonbondedUtil::calcFullSelfEnergy = calc_self_energy_fullelect; ComputeNonbondedUtil::calcMergePair = calc_pair_merge_fullelect; ComputeNonbondedUtil::calcMergePairEnergy = calc_pair_energy_merge_fullelect; ComputeNonbondedUtil::calcMergeSelf = calc_self_merge_fullelect; ComputeNonbondedUtil::calcMergeSelfEnergy = calc_self_energy_merge_fullelect; ComputeNonbondedUtil::calcSlowPair = calc_pair_slow_fullelect; ComputeNonbondedUtil::calcSlowPairEnergy = calc_pair_energy_slow_fullelect; ComputeNonbondedUtil::calcSlowSelf = calc_self_slow_fullelect; ComputeNonbondedUtil::calcSlowSelfEnergy = calc_self_energy_slow_fullelect; } //fepe dielectric_1 = 1.0/simParams->dielectric; if ( ! ljTable ) ljTable = new LJTable; mol = Node::Object()->molecule; scaling = simParams->nonbondedScaling; if ( simParams->exclude == SCALED14 ) { scale14 = simParams->scale14; } else { scale14 = 1.; } if ( simParams->switchingActive ) { switchOn = simParams->switchingDist; switchOn_1 = 1.0/switchOn; // d0 = 1.0/(cutoff-switchOn); switchOn2 = switchOn*switchOn; c0 = 1.0/(cutoff2-switchOn2); if ( simParams->vdwForceSwitching ) { double switchOn3 = switchOn * switchOn2; double cutoff3 = cutoff * cutoff2; double switchOn6 = switchOn3 * switchOn3; double cutoff6 = cutoff3 * cutoff3; v_vdwa = -1. / ( switchOn6 * cutoff6 ); v_vdwb = -1. / ( switchOn3 * cutoff3 ); k_vdwa = cutoff6 / ( cutoff6 - switchOn6 ); k_vdwb = cutoff3 / ( cutoff3 - switchOn3 ); cutoff_3 = 1. / cutoff3; cutoff_6 = 1. / cutoff6; } } else { switchOn = cutoff; switchOn_1 = 1.0/switchOn; // d0 = 0.; // avoid division by zero switchOn2 = switchOn*switchOn; c0 = 0.; // avoid division by zero } c1 = c0*c0*c0; c3 = 3.0 * (cutoff2 - switchOn2); c5 = 0; c6 = 0; c7 = 0; c8 = 0; const int PMEOn = simParams->PMEOn; const int MSMOn = simParams->MSMOn; const int MSMSplit = simParams->MSMSplit; if ( PMEOn ) { ewaldcof = simParams->PMEEwaldCoefficient; BigReal TwoBySqrtPi = 1.12837916709551; pi_ewaldcof = TwoBySqrtPi * ewaldcof; } int splitType = SPLIT_NONE; if ( simParams->switchingActive ) splitType = SPLIT_SHIFT; if ( simParams->martiniSwitching ) splitType = SPLIT_MARTINI; if ( simParams->fullDirectOn || simParams->FMAOn || PMEOn || MSMOn ) { switch ( simParams->longSplitting ) { case C2: splitType = SPLIT_C2; break; case C1: splitType = SPLIT_C1; break; case XPLOR: NAMD_die("Sorry, XPLOR splitting not supported."); break; case SHARP: NAMD_die("Sorry, SHARP splitting not supported."); break; default: NAMD_die("Unknown splitting type found!"); } } BigReal r2_tol = 0.1; r2_delta = 1.0; r2_delta_exp = 0; while ( r2_delta > r2_tol ) { r2_delta /= 2.0; r2_delta_exp += 1; } r2_delta_1 = 1.0 / r2_delta; if ( ! CkMyPe() ) { iout << iINFO << "NONBONDED TABLE R-SQUARED SPACING: " << r2_delta << "\n" << endi; } BigReal r2_tmp = 1.0; int cutoff2_exp = 0; while ( (cutoff2 + r2_delta) > r2_tmp ) { r2_tmp *= 2.0; cutoff2_exp += 1; } int i; int n = (r2_delta_exp + cutoff2_exp) * 64 + 1; if ( ! CkMyPe() ) { iout << iINFO << "NONBONDED TABLE SIZE: " << n << " POINTS\n" << endi; } if ( table_alloc ) delete [] table_alloc; table_alloc = new BigReal[61*n+16]; BigReal *table_align = table_alloc; while ( ((long)table_align) % 128 ) ++table_align; table_noshort = table_align; table_short = table_align + 16*n; slow_table = table_align + 32*n; fast_table = table_align + 36*n; scor_table = table_align + 40*n; corr_table = table_align + 44*n; full_table = table_align + 48*n; vdwa_table = table_align + 52*n; vdwb_table = table_align + 56*n; r2_table = table_align + 60*n; BigReal *fast_i = fast_table + 4; BigReal *scor_i = scor_table + 4; BigReal *slow_i = slow_table + 4; BigReal *vdwa_i = vdwa_table + 4; BigReal *vdwb_i = vdwb_table + 4; BigReal *r2_i = r2_table; *(r2_i++) = r2_delta; BigReal r2_limit = simParams->limitDist * simParams->limitDist; if ( r2_limit < r2_delta ) r2_limit = r2_delta; int r2_delta_i = 0; // entry for r2 == r2_delta // fill in the table, fix up i==0 (r2==0) below for ( i=1; i<n; ++i ) { const BigReal r2_base = r2_delta * ( 1 << (i/64) ); const BigReal r2_del = r2_base / 64.0; const BigReal r2 = r2_base - r2_delta + r2_del * (i%64); if ( r2 <= r2_limit ) r2_delta_i = i; const BigReal r = sqrt(r2); const BigReal r_1 = 1.0/r; const BigReal r_2 = 1.0/r2; // fast_ is defined as (full_ - slow_) // corr_ and fast_ are both zero at the cutoff, full_ is not // all three are approx 1/r at short distances // for actual interpolation, we use fast_ for fast forces and // scor_ = slow_ + corr_ - full_ and slow_ for slow forces // since these last two are of small magnitude BigReal fast_energy, fast_gradient; BigReal scor_energy, scor_gradient; BigReal slow_energy, slow_gradient; // corr_ is PME direct sum, or similar correction term // corr_energy is multiplied by r until later // corr_gradient is multiplied by -r^2 until later BigReal corr_energy, corr_gradient; if ( PMEOn ) { BigReal tmp_a = r * ewaldcof; BigReal tmp_b = erfc(tmp_a); corr_energy = tmp_b; corr_gradient = pi_ewaldcof*exp(-(tmp_a*tmp_a))*r + tmp_b; } else if ( MSMOn ) { BigReal a_1 = 1.0/cutoff; BigReal r_a = r * a_1; BigReal g, dg; SPOLY(&g, &dg, r_a, MSMSplit); corr_energy = 1 - r_a * g; corr_gradient = 1 + r_a*r_a * dg; } else { corr_energy = corr_gradient = 0; } switch(splitType) { case SPLIT_NONE: fast_energy = 1.0/r; fast_gradient = -1.0/r2; scor_energy = scor_gradient = 0; slow_energy = slow_gradient = 0; break; case SPLIT_SHIFT: { BigReal shiftVal = r2/cutoff2 - 1.0; shiftVal *= shiftVal; BigReal dShiftVal = 2.0 * (r2/cutoff2 - 1.0) * 2.0*r/cutoff2; fast_energy = shiftVal/r; fast_gradient = dShiftVal/r - shiftVal/r2; scor_energy = scor_gradient = 0; slow_energy = slow_gradient = 0; } break; case SPLIT_MARTINI: { // in Martini, the Coulomb switching distance is zero const BigReal COUL_SWITCH = 0.; // Gromacs shifting function const BigReal p1 = 1.; BigReal A1 = p1 * ((p1+1)*COUL_SWITCH-(p1+4)*cutoff)/(pow(cutoff,p1+2)*pow(cutoff-COUL_SWITCH,2)); BigReal B1 = -p1 * ((p1+1)*COUL_SWITCH-(p1+3)*cutoff)/(pow(cutoff,p1+2)*pow(cutoff-COUL_SWITCH,3)); BigReal X1 = 1.0/pow(cutoff,p1)-A1/3.0*pow(cutoff-COUL_SWITCH,3)-B1/4.0*pow(cutoff-COUL_SWITCH,4); BigReal r12 = (r-COUL_SWITCH)*(r-COUL_SWITCH); BigReal r13 = (r-COUL_SWITCH)*(r-COUL_SWITCH)*(r-COUL_SWITCH); BigReal shiftVal = -(A1/3.0)*r13 - (B1/4.0)*r12*r12 - X1; BigReal dShiftVal = -A1*r12 - B1*r13; fast_energy = (1/r) + shiftVal; fast_gradient = -1/(r2) + dShiftVal; scor_energy = scor_gradient = 0; slow_energy = slow_gradient = 0; } break; case SPLIT_C1: // calculate actual energy and gradient slow_energy = 0.5/cutoff * (3.0 - (r2/cutoff2)); slow_gradient = -1.0/cutoff2 * (r/cutoff); // calculate scor from slow and corr scor_energy = slow_energy + (corr_energy - 1.0)/r; scor_gradient = slow_gradient - (corr_gradient - 1.0)/r2; // calculate fast from slow fast_energy = 1.0/r - slow_energy; fast_gradient = -1.0/r2 - slow_gradient; break; case SPLIT_C2: // // Quintic splitting function contributed by // Bruce Berne, Ruhong Zhou, and Joe Morrone // // calculate actual energy and gradient slow_energy = r2/(cutoff*cutoff2) * (6.0 * (r2/cutoff2) - 15.0*(r/cutoff) + 10.0); slow_gradient = r/(cutoff*cutoff2) * (24.0 * (r2/cutoff2) - 45.0 *(r/cutoff) + 20.0); // calculate scor from slow and corr scor_energy = slow_energy + (corr_energy - 1.0)/r; scor_gradient = slow_gradient - (corr_gradient - 1.0)/r2; // calculate fast from slow fast_energy = 1.0/r - slow_energy; fast_gradient = -1.0/r2 - slow_gradient; break; } // foo_gradient is calculated as ( d foo_energy / d r ) // and now divided by 2r to get ( d foo_energy / d r2 ) fast_gradient *= 0.5 * r_1; scor_gradient *= 0.5 * r_1; slow_gradient *= 0.5 * r_1; // let modf be 1 if excluded, 1-scale14 if modified, 0 otherwise, // add scor_ - modf * slow_ to slow terms and // add fast_ - modf * fast_ to fast terms. BigReal vdwa_energy, vdwa_gradient; BigReal vdwb_energy, vdwb_gradient; const BigReal r_6 = r_2*r_2*r_2; const BigReal r_12 = r_6*r_6; // Lennard-Jones switching function if ( simParams->vdwForceSwitching ) { // switch force // from Steinbach & Brooks, JCC 15, pgs 667-683, 1994, eqns 10-13 if ( r2 > switchOn2 ) { BigReal tmpa = r_6 - cutoff_6; vdwa_energy = k_vdwa * tmpa * tmpa; BigReal tmpb = r_1 * r_2 - cutoff_3; vdwb_energy = k_vdwb * tmpb * tmpb; vdwa_gradient = -6.0 * k_vdwa * tmpa * r_2 * r_6; vdwb_gradient = -3.0 * k_vdwb * tmpb * r_2 * r_2 * r_1; } else { vdwa_energy = r_12 + v_vdwa; vdwb_energy = r_6 + v_vdwb; vdwa_gradient = -6.0 * r_2 * r_12; vdwb_gradient = -3.0 * r_2 * r_6; } } else if ( simParams->martiniSwitching ) { // switching fxn for Martini RBCG BigReal r12 = (r-switchOn)*(r-switchOn); BigReal r13 = (r-switchOn)*(r-switchOn)*(r-switchOn); BigReal p6 = 6; BigReal A6 = p6 * ((p6+1)*switchOn-(p6+4)*cutoff)/(pow(cutoff,p6+2)*pow(cutoff-switchOn,2)); BigReal B6 = -p6 * ((p6+1)*switchOn-(p6+3)*cutoff)/(pow(cutoff,p6+2)*pow(cutoff-switchOn,3)); BigReal C6 = 1.0/pow(cutoff,p6)-A6/3.0*pow(cutoff-switchOn,3)-B6/4.0*pow(cutoff-switchOn,4); BigReal p12 = 12; BigReal A12 = p12 * ((p12+1)*switchOn-(p12+4)*cutoff)/(pow(cutoff,p12+2)*pow(cutoff-switchOn,2)); BigReal B12 = -p12 * ((p12+1)*switchOn-(p12+3)*cutoff)/(pow(cutoff,p12+2)*pow(cutoff-switchOn,3)); BigReal C12 = 1.0/pow(cutoff,p12)-A12/3.0*pow(cutoff-switchOn,3)-B12/4.0*pow(cutoff-switchOn,4); BigReal LJshifttempA = -(A12/3)*r13 - (B12/4)*r12*r12 - C12; BigReal LJshifttempB = -(A6/3)*r13 - (B6/4)*r12*r12 - C6; const BigReal shiftValA = // used for Lennard-Jones ( r2 > switchOn2 ? LJshifttempA : -C12); const BigReal shiftValB = // used for Lennard-Jones ( r2 > switchOn2 ? LJshifttempB : -C6); BigReal LJdshifttempA = -A12*r12 - B12*r13; BigReal LJdshifttempB = -A6*r12 - B6*r13; const BigReal dshiftValA = // used for Lennard-Jones ( r2 > switchOn2 ? LJdshifttempA*0.5*r_1 : 0 ); const BigReal dshiftValB = // used for Lennard-Jones ( r2 > switchOn2 ? LJdshifttempB*0.5*r_1 : 0 ); //have not addressed r > cutoff // dshiftValA*= 0.5*r_1; // dshiftValB*= 0.5*r_1; vdwa_energy = r_12 + shiftValA; vdwb_energy = r_6 + shiftValB; vdwa_gradient = -6/pow(r,14) + dshiftValA ; vdwb_gradient = -3/pow(r,8) + dshiftValB; } else { // switch energy const BigReal c2 = cutoff2-r2; const BigReal c4 = c2*(c3-2.0*c2); const BigReal switchVal = // used for Lennard-Jones ( r2 > switchOn2 ? c2*c4*c1 : 1.0 ); const BigReal dSwitchVal = // d switchVal / d r2 ( r2 > switchOn2 ? 2*c1*(c2*c2-c4) : 0.0 ); vdwa_energy = switchVal * r_12; vdwb_energy = switchVal * r_6; vdwa_gradient = ( dSwitchVal - 6.0 * switchVal * r_2 ) * r_12; vdwb_gradient = ( dSwitchVal - 3.0 * switchVal * r_2 ) * r_6; } *(fast_i++) = fast_energy; *(fast_i++) = fast_gradient; *(fast_i++) = 0; *(fast_i++) = 0; *(scor_i++) = scor_energy; *(scor_i++) = scor_gradient; *(scor_i++) = 0; *(scor_i++) = 0; *(slow_i++) = slow_energy; *(slow_i++) = slow_gradient; *(slow_i++) = 0; *(slow_i++) = 0; *(vdwa_i++) = vdwa_energy; *(vdwa_i++) = vdwa_gradient; *(vdwa_i++) = 0; *(vdwa_i++) = 0; *(vdwb_i++) = vdwb_energy; *(vdwb_i++) = vdwb_gradient; *(vdwb_i++) = 0; *(vdwb_i++) = 0; *(r2_i++) = r2 + r2_delta; } if ( ! r2_delta_i ) { NAMD_bug("Failed to find table entry for r2 == r2_limit\n"); } if ( r2_table[r2_delta_i] > r2_limit + r2_delta ) { NAMD_bug("Found bad table entry for r2 == r2_limit\n"); } int j; const char *table_name = "XXXX"; int smooth_short = 0; for ( j=0; j<5; ++j ) { BigReal *t0 = 0; switch (j) { case 0: t0 = fast_table; table_name = "FAST"; smooth_short = 1; break; case 1: t0 = scor_table; table_name = "SCOR"; smooth_short = 0; break; case 2: t0 = slow_table; table_name = "SLOW"; smooth_short = 0; break; case 3: t0 = vdwa_table; table_name = "VDWA"; smooth_short = 1; break; case 4: t0 = vdwb_table; table_name = "VDWB"; smooth_short = 1; break; } // patch up data for i=0 t0[0] = t0[4] - t0[5] * ( r2_delta / 64.0 ); // energy t0[1] = t0[5]; // gradient t0[2] = 0; t0[3] = 0; if ( smooth_short ) { BigReal energy0 = t0[4*r2_delta_i]; BigReal gradient0 = t0[4*r2_delta_i+1]; BigReal r20 = r2_table[r2_delta_i]; t0[0] = energy0 - gradient0 * (r20 - r2_table[0]); // energy t0[1] = gradient0; // gradient } BigReal *t; for ( i=0,t=t0; i<(n-1); ++i,t+=4 ) { BigReal x = ( r2_delta * ( 1 << (i/64) ) ) / 64.0; if ( r2_table[i+1] != r2_table[i] + x ) { NAMD_bug("Bad table delta calculation.\n"); } if ( smooth_short && i+1 < r2_delta_i ) { BigReal energy0 = t0[4*r2_delta_i]; BigReal gradient0 = t0[4*r2_delta_i+1]; BigReal r20 = r2_table[r2_delta_i]; t[4] = energy0 - gradient0 * (r20 - r2_table[i+1]); // energy t[5] = gradient0; // gradient } BigReal v1 = t[0]; BigReal g1 = t[1]; BigReal v2 = t[4]; BigReal g2 = t[5]; // explicit formulas for v1 + g1 x + c x^2 + d x^3 BigReal c = ( 3.0 * (v2 - v1) - x * (2.0 * g1 + g2) ) / ( x * x ); BigReal d = ( -2.0 * (v2 - v1) + x * (g1 + g2) ) / ( x * x * x ); // since v2 - v1 is imprecise, we refine c and d numerically // important because we need accurate forces (more than energies!) for ( int k=0; k < 2; ++k ) { BigReal dv = (v1 - v2) + ( ( d * x + c ) * x + g1 ) * x; BigReal dg = (g1 - g2) + ( 3.0 * d * x + 2.0 * c ) * x; c -= ( 3.0 * dv - x * dg ) / ( x * x ); d -= ( -2.0 * dv + x * dg ) / ( x * x * x ); } // store in the array; t[2] = c; t[3] = d; } if ( ! CkMyPe() ) { BigReal dvmax = 0; BigReal dgmax = 0; BigReal dvmax_r = 0; BigReal dgmax_r = 0; BigReal fdvmax = 0; BigReal fdgmax = 0; BigReal fdvmax_r = 0; BigReal fdgmax_r = 0; BigReal dgcdamax = 0; BigReal dgcdimax = 0; BigReal dgcaimax = 0; BigReal dgcdamax_r = 0; BigReal dgcdimax_r = 0; BigReal dgcaimax_r = 0; BigReal fdgcdamax = 0; BigReal fdgcdimax = 0; BigReal fdgcaimax = 0; BigReal fdgcdamax_r = 0; BigReal fdgcdimax_r = 0; BigReal fdgcaimax_r = 0; BigReal gcm = fabs(t0[1]); // gradient magnitude running average for ( i=0,t=t0; i<(n-1); ++i,t+=4 ) { const BigReal r2_base = r2_delta * ( 1 << (i/64) ); const BigReal r2_del = r2_base / 64.0; const BigReal r2 = r2_base - r2_delta + r2_del * (i%64); const BigReal r = sqrt(r2); if ( r > cutoff ) break; BigReal x = r2_del; BigReal dv = ( ( t[3] * x + t[2] ) * x + t[1] ) * x + t[0] - t[4]; BigReal dg = ( 3.0 * t[3] * x + 2.0 * t[2] ) * x + t[1] - t[5]; if ( t[4] != 0. && fabs(dv/t[4]) > fdvmax ) { fdvmax = fabs(dv/t[4]); fdvmax_r = r; } if ( fabs(dv) > dvmax ) { dvmax = fabs(dv); dvmax_r = r; } if ( t[5] != 0. && fabs(dg/t[5]) > fdgmax ) { fdgmax = fabs(dg/t[5]); fdgmax_r = r; } if ( fabs(dg) > dgmax ) { dgmax = fabs(dg); dgmax_r = r; } BigReal gcd = (t[4] - t[0]) / x; // centered difference gradient BigReal gcd_prec = (fabs(t[0]) + fabs(t[4])) * 1.e-15 / x; // roundoff gcm = 0.9 * gcm + 0.1 * fabs(t[5]); // magnitude running average BigReal gca = 0.5 * (t[1] + t[5]); // centered average gradient BigReal gci = ( 0.75 * t[3] * x + t[2] ) * x + t[1]; // interpolated BigReal rc = sqrt(r2 + 0.5 * x); BigReal dgcda = gcd - gca; if ( dgcda != 0. && fabs(dgcda) < gcd_prec ) { // CkPrintf("ERROR %g < PREC %g AT %g AVG VAL %g\n", dgcda, gcd_prec, rc, gca); dgcda = 0.; } BigReal dgcdi = gcd - gci; if ( dgcdi != 0. && fabs(dgcdi) < gcd_prec ) { // CkPrintf("ERROR %g < PREC %g AT %g INT VAL %g\n", dgcdi, gcd_prec, rc, gci); dgcdi = 0.; } BigReal dgcai = gca - gci; if ( t[1]*t[5] > 0. && gcm != 0. && fabs(dgcda/gcm) > fdgcdamax ) { fdgcdamax = fabs(dgcda/gcm); fdgcdamax_r = rc; } if ( fabs(dgcda) > fdgcdamax ) { dgcdamax = fabs(dgcda); dgcdamax_r = rc; } if ( t[1]*t[5] > 0. && gcm != 0. && fabs(dgcdi/gcm) > fdgcdimax ) { fdgcdimax = fabs(dgcdi/gcm); fdgcdimax_r = rc; } if ( fabs(dgcdi) > fdgcdimax ) { dgcdimax = fabs(dgcdi); dgcdimax_r = rc; } if ( t[1]*t[5] > 0. && gcm != 0. && fabs(dgcai/gcm) > fdgcaimax ) { fdgcaimax = fabs(dgcai/gcm); fdgcaimax_r = rc; } if ( fabs(dgcai) > fdgcaimax ) { dgcaimax = fabs(dgcai); dgcaimax_r = rc; } #if 0 CkPrintf("TABLE %s %g %g %g %g\n",table_name,rc,dgcda/gcm,dgcda,gci); if (dv != 0.) CkPrintf("TABLE %d ENERGY ERROR %g AT %g (%d)\n",j,dv,r,i); if (dg != 0.) CkPrintf("TABLE %d FORCE ERROR %g AT %g (%d)\n",j,dg,r,i); #endif } if ( dvmax != 0.0 ) { iout << iINFO << "ABSOLUTE IMPRECISION IN " << table_name << " TABLE ENERGY: " << dvmax << " AT " << dvmax_r << "\n" << endi; } if ( fdvmax != 0.0 ) { iout << iINFO << "RELATIVE IMPRECISION IN " << table_name << " TABLE ENERGY: " << fdvmax << " AT " << fdvmax_r << "\n" << endi; } if ( dgmax != 0.0 ) { iout << iINFO << "ABSOLUTE IMPRECISION IN " << table_name << " TABLE FORCE: " << dgmax << " AT " << dgmax_r << "\n" << endi; } if ( fdgmax != 0.0 ) { iout << iINFO << "RELATIVE IMPRECISION IN " << table_name << " TABLE FORCE: " << fdgmax << " AT " << fdgmax_r << "\n" << endi; } if (fdgcdamax != 0.0 ) { iout << iINFO << "INCONSISTENCY IN " << table_name << " TABLE ENERGY VS FORCE: " << fdgcdamax << " AT " << fdgcdamax_r << "\n" << endi; if ( fdgcdamax > 0.1 ) { iout << iERROR << "\n"; iout << iERROR << "CALCULATED " << table_name << " FORCE MAY NOT MATCH ENERGY! POSSIBLE BUG!\n"; iout << iERROR << "\n"; } } if (0 && fdgcdimax != 0.0 ) { iout << iINFO << "INCONSISTENCY IN " << table_name << " TABLE ENERGY VS FORCE: " << fdgcdimax << " AT " << fdgcdimax_r << "\n" << endi; } if ( 0 && fdgcaimax != 0.0 ) { iout << iINFO << "INCONSISTENCY IN " << table_name << " TABLE AVG VS INT FORCE: " << fdgcaimax << " AT " << fdgcaimax_r << "\n" << endi; } } } for ( i=0; i<4*n; ++i ) { corr_table[i] = fast_table[i] + scor_table[i]; full_table[i] = fast_table[i] + slow_table[i]; } #if 0 for ( i=0; i<n; ++i ) { for ( int j=0; j<4; ++j ) { table_short[16*i+6-2*j] = table_noshort[16*i+6-2*j] = vdwa_table[4*i+j]; table_short[16*i+7-2*j] = table_noshort[16*i+7-2*j] = vdwb_table[4*i+j]; table_short[16*i+8+3-j] = fast_table[4*i+j]; table_short[16*i+12+3-j] = scor_table[4*i+j]; table_noshort[16*i+8+3-j] = corr_table[4*i+j]; table_noshort[16*i+12+3-j] = full_table[4*i+j]; } } #endif for ( i=0; i<n; ++i ) { table_short[16*i+ 0] = table_noshort[16*i+0] = -6.*vdwa_table[4*i+3]; table_short[16*i+ 2] = table_noshort[16*i+2] = -6.*vdwb_table[4*i+3]; table_short[16*i+ 4] = table_noshort[16*i+4] = -2.*vdwa_table[4*i+1]; table_short[16*i+ 6] = table_noshort[16*i+6] = -2.*vdwb_table[4*i+1]; table_short[16*i+1] = table_noshort[16*i+1] = -4.*vdwa_table[4*i+2]; table_short[16*i+3] = table_noshort[16*i+3] = -4.*vdwb_table[4*i+2]; table_short[16*i+5] = table_noshort[16*i+5] = -1.*vdwa_table[4*i+0]; table_short[16*i+7] = table_noshort[16*i+7] = -1.*vdwb_table[4*i+0]; table_short[16*i+8] = -6.*fast_table[4*i+3]; table_short[16*i+9] = -4.*fast_table[4*i+2]; table_short[16*i+10] = -2.*fast_table[4*i+1]; table_short[16*i+11] = -1.*fast_table[4*i+0]; table_noshort[16*i+8] = -6.*corr_table[4*i+3]; table_noshort[16*i+9] = -4.*corr_table[4*i+2]; table_noshort[16*i+10] = -2.*corr_table[4*i+1]; table_noshort[16*i+11] = -1.*corr_table[4*i+0]; table_short[16*i+12] = -6.*scor_table[4*i+3]; table_short[16*i+13] = -4.*scor_table[4*i+2]; table_short[16*i+14] = -2.*scor_table[4*i+1]; table_short[16*i+15] = -1.*scor_table[4*i+0]; table_noshort[16*i+12] = -6.*full_table[4*i+3]; table_noshort[16*i+13] = -4.*full_table[4*i+2]; table_noshort[16*i+14] = -2.*full_table[4*i+1]; table_noshort[16*i+15] = -1.*full_table[4*i+0]; } #if 0 char fname[100]; sprintf(fname,"/tmp/namd.table.pe%d.dat",CkMyPe()); FILE *f = fopen(fname,"w"); for ( i=0; i<(n-1); ++i ) { const BigReal r2_base = r2_delta * ( 1 << (i/64) ); const BigReal r2_del = r2_base / 64.0; const BigReal r2 = r2_base - r2_delta + r2_del * (i%64); BigReal *t; if ( r2 + r2_delta != r2_table[i] ) fprintf(f,"r2 error! "); fprintf(f,"%g",r2); t = fast_table + 4*i; fprintf(f," %g %g %g %g", t[0], t[1], t[2], t[3]); t = scor_table + 4*i; fprintf(f," %g %g %g %g", t[0], t[1], t[2], t[3]); t = slow_table + 4*i; fprintf(f," %g %g %g %g", t[0], t[1], t[2], t[3]); t = corr_table + 4*i; fprintf(f," %g %g %g %g", t[0], t[1], t[2], t[3]); t = full_table + 4*i; fprintf(f," %g %g %g %g", t[0], t[1], t[2], t[3]); t = vdwa_table + 4*i; fprintf(f," %g %g %g %g", t[0], t[1], t[2], t[3]); t = vdwb_table + 4*i; fprintf(f," %g %g %g %g", t[0], t[1], t[2], t[3]); fprintf(f,"\n"); } fclose(f); #endif #ifdef NAMD_CUDA send_build_cuda_force_table(); #endif }
void ComputeDPMEMaster::recvData(ComputeDPMEDataMsg *msg) { DebugM(4,"ComputeDPMEMaster::recvData() " << msg->numParticles << " particles from node " << msg->node << "\n"); { homeNode.add(msg->node); Pme2Particle *data_ptr = localData + numLocalAtoms; for ( int j = 0; j < msg->numParticles; ++j, ++data_ptr ) { *data_ptr = msg->particles[j]; } numLocalAtoms += msg->numParticles; endForNode.add(numLocalAtoms); delete msg; } if ( homeNode.size() < numWorkingPes ) return; // messages outstanding DebugM(4,"ComputeDPMEMaster::recvData() running serial code.\n"); // single processor version Lattice lattice = host->getFlags()->lattice; SimParameters * simParams = Node::Object()->simParameters; int i; AtomInfo atom_info; atom_info.numatoms = numLocalAtoms; atom_info.atompnt = 0; // not used atom_info.freepnt = 0; // not used atom_info.nlocal = numLocalAtoms; atom_info.nother = 0; if ( ! lattice.orthogonal() ) { NAMD_die("DPME only supports orthogonal PBC's."); } BoxInfo box_info; box_info.box.x = lattice.a().x; box_info.box.y = lattice.b().y; box_info.box.z = lattice.c().z; box_info.box.origin = 0.; // why only one number? box_info.prd.x = box_info.box.x; box_info.prd.y = box_info.box.y; box_info.prd.z = box_info.box.z; box_info.prd2.x = 0.5 * box_info.box.x; box_info.prd2.y = 0.5 * box_info.box.y; box_info.prd2.z = 0.5 * box_info.box.z; box_info.cutoff = simParams->cutoff; box_info.rs = simParams->cutoff; box_info.mc2.x = 2. * ( box_info.prd.x - box_info.cutoff ); box_info.mc2.y = 2. * ( box_info.prd.y - box_info.cutoff ); box_info.mc2.z = 2. * ( box_info.prd.z - box_info.cutoff ); box_info.ewaldcof = ComputeNonbondedUtil::ewaldcof; box_info.dtol = simParams->PMETolerance; for (i = 0; i <= 8; i++) { box_info.recip[i] = 0.; /* assume orthogonal box */ } box_info.recip[0] = 1.0/box_info.box.x; box_info.recip[4] = 1.0/box_info.box.y; box_info.recip[8] = 1.0/box_info.box.z; GridInfo grid_info; grid_info.order = simParams->PMEInterpOrder; grid_info.nfftgrd.x = simParams->PMEGridSizeX; grid_info.nfftgrd.y = simParams->PMEGridSizeY; grid_info.nfftgrd.z = simParams->PMEGridSizeZ; grid_info.nfft = 0; grid_info.volume = lattice.volume(); PeInfo pe_info; // hopefully this isn't used for anything pe_info.myproc.node = 0; pe_info.myproc.nprocs = 1; pe_info.myproc.ncube = 0; pe_info.inst_node[0] = 0; pe_info.igrid = 0; PmeVector *localResults; double recip_vir[6]; int time_count = 0; int tsteps = 1; double mytime = 0.; // perform calculations BigReal electEnergy = 0; // calculate self energy Pme2Particle *data_ptr = localData; for(i=0; i<numLocalAtoms; ++i) { electEnergy += data_ptr->cg * data_ptr->cg; ++data_ptr; } electEnergy *= -1. * box_info.ewaldcof / SQRT_PI; DebugM(4,"Ewald self energy: " << electEnergy << "\n"); DebugM(4,"Calling dpme_eval_recip().\n"); double pme_start_time = 0; if ( runcount == 1 ) pme_start_time = CmiTimer(); electEnergy += dpme_eval_recip( atom_info, localData - 1, &localResults, recip_vir, grid_info, box_info, pe_info, time_count, tsteps, &mytime ); if ( runcount == 1 ) { iout << iINFO << "PME reciprocal sum CPU time per evaluation: " << (CmiTimer() - pme_start_time) << "\n" << endi; } DebugM(4,"Returned from dpme_eval_recip().\n"); // REVERSE SIGN OF VIRIAL RETURNED BY DPME for(i=0; i<6; ++i) recip_vir[i] *= -1.; // send out reductions DebugM(4,"Timestep : " << host->getFlags()->step << "\n"); DebugM(4,"Reciprocal sum energy: " << electEnergy << "\n"); DebugM(4,"Reciprocal sum virial: " << recip_vir[0] << " " << recip_vir[1] << " " << recip_vir[2] << " " << recip_vir[3] << " " << recip_vir[4] << " " << recip_vir[5] << "\n"); reduction->item(REDUCTION_ELECT_ENERGY_SLOW) += electEnergy; reduction->item(REDUCTION_VIRIAL_SLOW_XX) += (BigReal)(recip_vir[0]); reduction->item(REDUCTION_VIRIAL_SLOW_XY) += (BigReal)(recip_vir[1]); reduction->item(REDUCTION_VIRIAL_SLOW_XZ) += (BigReal)(recip_vir[2]); reduction->item(REDUCTION_VIRIAL_SLOW_YX) += (BigReal)(recip_vir[1]); reduction->item(REDUCTION_VIRIAL_SLOW_YY) += (BigReal)(recip_vir[3]); reduction->item(REDUCTION_VIRIAL_SLOW_YZ) += (BigReal)(recip_vir[4]); reduction->item(REDUCTION_VIRIAL_SLOW_ZX) += (BigReal)(recip_vir[2]); reduction->item(REDUCTION_VIRIAL_SLOW_ZY) += (BigReal)(recip_vir[4]); reduction->item(REDUCTION_VIRIAL_SLOW_ZZ) += (BigReal)(recip_vir[5]); reduction->submit(); PmeVector *results_ptr = localResults + 1; numLocalAtoms = 0; for ( i = 0; i < homeNode.size(); ++i ) { ComputeDPMEResultsMsg *msg = new ComputeDPMEResultsMsg; msg->node = homeNode[i]; msg->numParticles = endForNode[i] - numLocalAtoms; msg->forces = new PmeVector[msg->numParticles]; for ( int j = 0; j < msg->numParticles; ++j, ++results_ptr ) { msg->forces[j] = *results_ptr; } numLocalAtoms = endForNode[i]; host->comm->sendComputeDPMEResults(msg,homeNode[i]); } // reset runcount += 1; numLocalAtoms = 0; homeNode.resize(0); endForNode.resize(0); }
GromacsTopFile::GromacsTopFile(char *filename) { fudgeLJ = fudgeQQ = 1.0; /* open the file */ FILE *f = fopen(filename,"r"); char buf[LINESIZE]; char modename[20]; int mode; if(f==NULL) { sprintf(buf,"Error opening file '%s'",filename); NAMD_die(buf); } /* really bad parser XXX probably just works on the files we happen to have REWRITE THIS SOON. It should allow for \- line continuations, check for errors in the file, etc. */ while(fgets(buf,LINESIZE-1,f)) { char testchar; int i,j; /* defaults */ int nbfunc, combrule; char genpairs[20]; /* atom buffers */ int num, resnum, chargegp, typenum; char type[NAMESIZE+1], restype[NAMESIZE+1], atomname[NAMESIZE+1]; char particletype[NAMESIZE+1]; float charge, mass, c6, c12, junkf; /* moltype buffers */ int nrexcl; char molname[LONGNAMESIZE+1]; /* molInst buffers */ int copies; MolInst *moleculeinstance; /* general atomset buffers */ int atomi, atomj, atomk, atoml; char typea[NAMESIZE+1],typeb[NAMESIZE+1], typec[NAMESIZE+1],typed[NAMESIZE+1]; const char *tmptypea,*tmptypeb,*tmptypec,*tmptyped; int funct, index; float c0,c1; /* bonds */ float b0,kB,th0,kth; /* dihedrals */ float c[6]; int mult=0; /* check for comments */ if(sscanf(buf," %c",&testchar)==1) { if(testchar == ';') continue; } else { /* this is a blank line */ continue; } /* check for a new mode */ if(sscanf(buf," [ %19[^] ] ]",modename)==1) { /* switch the mode */ if(0==strcmp(modename,"atoms")) mode = ATOMS; else if(0==strcmp(modename,"atomtypes")) mode = ATOMTYPES; else if(0==strcmp(modename,"moleculetype")) mode = MOLECULETYPE; else if(0==strcmp(modename,"molecules")) mode = MOLECULES; else if(0==strcmp(modename,"system")) mode = SYSTEM; else if(0==strcmp(modename,"bonds")) mode = BONDS; else if(0==strcmp(modename,"bondtypes")) mode = BONDTYPES; else if(0==strcmp(modename,"angles")) mode = ANGLES; else if(0==strcmp(modename,"angletypes")) mode = ANGLETYPES; else if(0==strcmp(modename,"dihedrals")) mode = DIHEDRALS; else if(0==strcmp(modename,"dihedraltypes")) mode = DIHEDRALTYPES; else if(0==strcmp(modename,"defaults")) mode = DEFAULTS; else if(0==strcmp(modename,"nonbond_params")) mode = NONBOND; // JLai else if(0==strcmp(modename,"pairs")) mode = PAIRS; else if(0==strcmp(modename,"exclusions")) mode = EXCLUSIONS; else { fprintf(stderr,"Warning: unknown mode %s\n",modename); mode = UNKNOWN; } continue; } /* now do the appropriate thing based on the current mode */ switch(mode) { case SYSTEM: systemName = strdup(buf); break; case DEFAULTS: i = sscanf(buf," %d %d %20s %f %f", &nbfunc,&combrule,genpairs,&fudgeLJ,&fudgeQQ); if(i < 3) { // didn't get enough parameters fprintf(stderr,"syntax error in DEFAULTS\n"); exit(1); } if(nbfunc != 1) { // I don't know how it works with nbfunc=2 fprintf(stderr,"Non-bonded function != 1 unsupported in DEFAULTS\n"); exit(1); } if(combrule != 1) { // same here fprintf(stderr,"Combination rule != 1 unsupported in DEFAULTS\n"); exit(1); } if(0==strcmp(genpairs,"yes")) { genPairs=1; if(i!=5) { fprintf(stderr,"syntax error in DEFAULTS\n"); exit(1); } // else fudgeLJ and fudgeQQ got written automatically } else genPairs=0; break; case NONBOND: if(5 != sscanf(buf," %5s %5s %d %f %f", typea, typeb, &funct, &c6, &c12)) { fprintf(stderr,"Syntax error in NONBOND\n"); exit(1); } // convert kJ/mol*nm6 to kcal/mol*A6 and ..12 ..12 c6 = c6/JOULES_PER_CALORIE*1E6; c12= c12/JOULES_PER_CALORIE*1E12; vdwTable.addType(typea,typeb,c6,c12); break; case BONDS: i = sscanf(buf," %d %d %d %f %f", &atomi,&atomj,&funct,&c0,&c1); atomi--; // shift right away to a zero-indexing atomj--; if(i==3) { tmptypea = genericMols[genericMols.size()-1]->getAtom(atomi)->getType(); tmptypeb = genericMols[genericMols.size()-1]->getAtom(atomj)->getType(); /* find the index and parameters */ index = bondTable.getParams(tmptypea, tmptypeb, funct, &b0, &kB); if(index==-1) { fprintf(stderr,"Required bondtype %s--%s (function %d) not found.\n", tmptypea,tmptypeb,funct); exit(1); } } else if(i==5) { /* first set the values of b0 and kB correctly */ b0 = c0*ANGSTROMS_PER_NM; /* convert nm to A */ if(funct==1) { /* harmonic potential */ /* convert kJ/nm2 to kcal/A2 and use E=kx2 instead of half that. */ kB = c1/JOULES_PER_CALORIE/100/2; } else if(funct==2) { /* special fourth-order potential */ /* convert to the normal harmonic constant and kJ/nm2 to kcal/A2 */ kB = 2*c1*c0*c0/JOULES_PER_CALORIE/100; kB /= 2; /* use the NAMD system where E=kx2 */ } else { fprintf(stderr,"I don't know what funct=%d means in BONDS\n",funct); exit(1); } /* look up the index */ index = bondTable.getIndex(b0,kB,funct); } else { fprintf(stderr,"Syntax error in BONDS\n"); exit(1); } genericMols[genericMols.size()-1]->addBond(atomi,atomj,index); break; case BONDTYPES: if(5 != sscanf(buf," %5s %5s %d %f %f", typea,typeb,&funct,&c0,&c1)) { fprintf(stderr,"Syntax error in BONDTYPES\n"); exit(1); } /* first set the values of b0 and kB correctly */ b0 = c0*10; /* convert nm to A */ if(funct==1) { /* harmonic potential */ /* convert kJ/nm2 to kcal/A2 and use E=kx2 instead of half that. */ kB = c1/JOULES_PER_CALORIE/100/2; } else if(funct==2) { /* special fourth-order potential */ /* convert to the normal harmonic constant and kJ/nm2 to kcal/A2 */ kB = 2*c1*c0*c0/JOULES_PER_CALORIE/100; kB /= 2; /* use the NAMD system where E=kx2 */ } else { fprintf(stderr,"I don't know what funct=%d means in BONDTYPES\n",funct); exit(1); } bondTable.addType(typea,typeb,b0,kB,funct); break; case ANGLES: i = sscanf(buf," %d %d %d %d %f %f", &atomi,&atomj,&atomk,&funct,&c0,&c1); atomi--; // shift right away to a zero-indexing atomj--; atomk--; if(i == 4) { /* we have to look up the last two parameters */ tmptypea = genericMols[genericMols.size()-1]->getAtom(atomi)->getType(); tmptypeb = genericMols[genericMols.size()-1]->getAtom(atomj)->getType(); tmptypec = genericMols[genericMols.size()-1]->getAtom(atomk)->getType(); /* find the index and parameters */ index = angleTable.getParams(tmptypea, tmptypeb, tmptypec, funct, &th0, &kth); if(index==-1) { fprintf(stderr, "Required angletype %s--%s--%s (function %d) not found.\n", tmptypea,tmptypeb,tmptypec,funct); exit(1); } } else if(i == 6) { /* first set the values of th0 and kth correctly */ if(funct == 1) { th0 = c0; /* both are in degrees */ kth = c1/JOULES_PER_CALORIE/2; /* convert kJ/rad2 to kcal/rad2 and use E=kx2 */ } else if(funct == 2) { th0 = c0; /* both are in degrees */ /* convert G96 kJ to kcal/rad2 and use E=kx2 */ kth = sin(th0*PI/180)*sin(th0*PI/180)*c1/JOULES_PER_CALORIE/2; } else { fprintf(stderr,"I don't know what funct=%d means in ANGLES\n",funct); exit(1); } /* add the angle type to our table */ index = angleTable.getIndex(th0,kth,funct); } else { fprintf(stderr,"Syntax error (%d args) in ANGLES: %s\n",i,buf); exit(1); } /* add the angle to our table */ genericMols[genericMols.size()-1]->addAngle(atomi,atomj,atomk,index); break; case ANGLETYPES: if(6 != sscanf(buf," %5s %5s %5s %d %f %f", typea,typeb,typec,&funct,&c0,&c1)) { fprintf(stderr,"Syntax error in ANGLETYPES\n"); exit(1); } /* first set the values of th0 and kth correctly */ if(funct == 1) { th0 = c0; /* both are in degrees */ kth = c1/JOULES_PER_CALORIE/2; /* convert kJ/rad2 to kcal/rad2 and use E=kx2 */ } else if(funct == 2) { th0 = c0; /* both are in degrees */ /* convert G96 kJ to kcal/rad2 and use E=kx2 */ kth = sin(th0*PI/180)*sin(th0*PI/180)*c1/JOULES_PER_CALORIE/2; } else { fprintf(stderr,"I don't know what funct=%d means in ANGLETYPES\n", funct); exit(1); } angleTable.addType(typea,typeb,typec,th0,kth,funct); break; case DIHEDRALS: i = sscanf(buf," %d %d %d %d %d %f %f %f %f %f %f", &atomi,&atomj,&atomk,&atoml,&funct, &c[0],&c[1],&c[2],&c[3],&c[4],&c[5]); atomi--; // shift right away to a zero-indexing atomj--; atomk--; atoml--; if(i==5) { /* we have to look up the parameters */ tmptypea = genericMols[genericMols.size()-1]->getAtom(atomi)->getType(); tmptypeb = genericMols[genericMols.size()-1]->getAtom(atomj)->getType(); tmptypec = genericMols[genericMols.size()-1]->getAtom(atomk)->getType(); tmptyped = genericMols[genericMols.size()-1]->getAtom(atoml)->getType(); /* find the index and parameters */ index = dihedralTable.getParams(tmptypea, tmptypeb, tmptypec, tmptyped, funct, c, &mult); if(index==-1) { fprintf(stderr, "Required dihedraltype %s--%s--%s--%s (function %d) not found.\n", tmptypea,tmptypeb,tmptypec,tmptyped,funct); exit(1); } } else if(i==7 || i==8 || i==11) { /* the parameters are given */ if(funct==1 || funct==2) { /* we should have two parameters */ if(i!=7+(funct==1)) { /* plus a multiplicity for funct==1 */ fprintf(stderr,"Must have 7 args for funct=1,2\n"); exit(1); } c[0] = c[0]; /* both in deg */ if(i==7) { c[1] = c[1]/(2*JOULES_PER_CALORIE); /* convert kJ to kcal and still use E=kx2*/ } else if (i==8 || i==11) { c[1] = c[1]/(1*JOULES_PER_CALORIE); /* convert kJ to kcal and still use E=kx2*/ } //c[1] = c[1]/(2*JOULES_PER_CALORIE); /* convert kJ to kcal and still use E=kx2*/ /* for funct==1 these are both divided by rad^2 */ if(funct==1) { mult=(int)(c[2]+0.5); /* round to nearest integer :p */ } } else if(funct==3) { if(i!=11){ fprintf(stderr,"Must have 11 args for funct=3\n"); exit(1); } for(j=0;j<6;j++) { c[j] = c[j]/JOULES_PER_CALORIE; /* convert kJ to kcal and E=Cn cos^n */ } } else { fprintf(stderr, "I don't know what funct=%d means in DIHEDRALS\n",funct); exit(1); } index = dihedralTable.getIndex(c,mult,funct); } else { fprintf(stderr,"Syntax error (%d args) in DIHEDRALS: %s\n",i,buf); exit(1); } /* add the dihedrals to our table */ genericMols[genericMols.size()-1]->addDihedral(atomi,atomj,atomk,atoml, index); break; case DIHEDRALTYPES: i = sscanf(buf," %5s %5s %d %f %f %f %f %f %f", typea,typeb,&funct,&c[0],&c[1],&c[2],&c[3],&c[4],&c[5]); if(funct == 1 || funct == 2) { if(i!=5+(funct==1)) { /* 6 for f=2, 5 for f=1 */ fprintf(stderr,"Syntax error in DIHEDRALTYPES: %s\n",buf); exit(1); } c[0] = c[0]; /* both in deg */ c[1] = c[1]/JOULES_PER_CALORIE; /* convert kJ to kcal and still use E=kx2*/ /* for funct==1 these are both divided by rad^2 */ if(funct==1) { mult=(int)(c[2]+0.5); /* round to nearest integer :p */ } } else if(funct == 3) { if(i!=9) { fprintf(stderr,"Syntax error in DIHEDRALTYPES\n"); exit(1); } for(j=0;j<6;j++) { c[j] = c[j]/JOULES_PER_CALORIE; /* convert kJ to kcal and E=Cn cos^n */ } } else { fprintf(stderr,"I don't know what funct=%d means in DIHEDRALTYPES\n", funct); exit(1); } dihedralTable.addType(typea,typeb,c,mult,funct); break; case ATOMS: i = sscanf(buf," %d %5s %d %5s %5s %d %f %f", &num, type, &resnum, restype, atomname, &chargegp, &charge, &mass); if(i==7) { /* XXX temporary - I should be able to get more params */ typenum = atomTable.getParams(type,&mass,&junkf,&junkf,&junkf); i=8; } else { if(i!=8) { fprintf(stderr,"Syntax error in ATOMS\n"); exit(1); } // just get the type number typenum = atomTable.getParams(type,&junkf,&junkf,&junkf,&junkf); } genericMols[genericMols.size()-1]->addAtom(type,typenum,resnum, restype,atomname,charge,mass); break; case ATOMTYPES: if(6 != sscanf(buf," %5s %f %f %5s %f %f",type,&mass,&charge, particletype,&c6,&c12)) { fprintf(stderr,"Syntax error in ATOMTYPES: %s\n",buf); exit(1); } /* conversions: c6 - kJ/mol nm6 -> kcal/mol A6 c12 - kJ/mol nm12 -> kcal/mol A12 */ atomTable.addType(type,mass,charge, c6/(JOULES_PER_CALORIE)*1E6, c12/(JOULES_PER_CALORIE)*1E12); break; case MOLECULETYPE: if(2!=sscanf(buf," %20s %d",molname,&nrexcl)) { fprintf(stderr,"Syntax error in MOLECULETYPE: %s\n",buf); exit(1); } /* add another generic molecule holder */ genericMols.add(new GenericMol(molname)); break; case MOLECULES: if(2!=sscanf(buf," %20s %d",molname,&copies)) { fprintf(stderr,"Syntax error in MOLECULES: %s\n",buf); exit(1); } /* search for the specified molecule and make a molInst of it*/ moleculeinstance = NULL; for(i=0;i<genericMols.size();i++) { if(0==strcmp(molname,genericMols[i]->getName())) { moleculeinstance = new MolInst(genericMols[i],copies); break; } } if(moleculeinstance==NULL) { fprintf(stderr,"Molecule %s undefined.\n",molname); exit(1); } /* put it at the end of the list */ molInsts.add(moleculeinstance); break; case PAIRS: int indexA; int indexB; int pairFunction; Real fA; Real fB; Real fC; Real fD; Real fE; Real fF; int countVariables; countVariables = sscanf(buf," %d %d %d %f %f %f %f %f %f",&indexA,&indexB,&pairFunction,&fA,&fB,&fC,&fD,&fE,&fF); if ((countVariables >= 4 && countVariables >= 10)) { fprintf(stderr,"Syntax error in PAIRS: %s\n",buf); exit(1); } // Shift the atom indices to be zero-based indexA--; indexB--; // Make sure that the indexA is less than indexB /*if ( indexA > indexB ) { int tmpIndex = indexA; indexB = indexA; indexA = tmpIndex; }*/ if (pairFunction == 1) { // LJ code fA = (fA/JOULES_PER_CALORIE)*1E6; fB= (fB/JOULES_PER_CALORIE)*1E12; pairTable.addPairLJType2(indexA,indexB,fA,fB); } else if (pairFunction == 5){ // Bare Gaussian potential fA = (fA/JOULES_PER_CALORIE); //-->gaussA fB = (fB*ANGSTROMS_PER_NM); //-->gaussMu1 if(fC == 0) { char buff[100]; sprintf(buff,"GromacsTopFile.C::Attempting to load zero into gaussSigma. Please check the pair: %s\n",buf); NAMD_die(buff); } if(fC < 0 && !bool_negative_number_warning_flag) { iout << iWARN << "Attempting to load a negative standard deviation into the gaussSigma. Taking the absolute value of the standard deviation."; bool_negative_number_warning_flag = true; } fC = (fC*ANGSTROMS_PER_NM); //-->gaussSigma1 fC = 1.0/(2 * fC * fC); // Normalizes sigma pairTable.addPairGaussType2(indexA,indexB,fA,fB,fC); } else if (pairFunction == 6) { // Combined Gaussian + repulsive r^-12 potential fA = (fA/JOULES_PER_CALORIE); //-->gaussA fB = (fB*ANGSTROMS_PER_NM); //-->gaussMu1 if(fC == 0) { char buff[100]; sprintf(buff,"GromacsTopFile.C::Attempting to load zero into gaussSigma. Please check the pair: %s\n",buf); NAMD_die(buff); } if(fC < 0 && !bool_negative_number_warning_flag) { iout << iWARN << "Attempting to load a negative standard deviation into the gaussSigma. Taking the absolute value of the standard deviation."; bool_negative_number_warning_flag = true; } fC = (fC*ANGSTROMS_PER_NM); //-->gaussSigma1 fC = 1.0/(2 * fC * fC); // Normalizes sigma fD = (fD*ANGSTROMS_PER_NM); //-->gaussRepulsive pairTable.addPairGaussType2(indexA,indexB,fA,fB,fC,fD); } else if (pairFunction == 7) { // Double well Guassian function fA = (fA/JOULES_PER_CALORIE); //-->gaussA fB = (fB*ANGSTROMS_PER_NM); //-->gaussMu1 if(fC == 0 || fE == 0) { char buff[100]; sprintf(buff,"GromacsTopFile.C::Attempting to load zero into gaussSigma. Please check the pair: %s\n",buf); NAMD_die(buff); } if((fC < 0 || fE < 0)&& !bool_negative_number_warning_flag) { iout << iWARN << "Attempting to load a negative standard deviation into the gaussSigma. Taking the absolute value of the standard deviation."; bool_negative_number_warning_flag = true; } fC = (fC*ANGSTROMS_PER_NM); //-->gaussSigma1 fC = 1.0/(2 * fC * fC); // Normalizes sigma fD = (fD*ANGSTROMS_PER_NM); //-->gaussMu2 fE = (fE*ANGSTROMS_PER_NM); //-->gaussSigma2 fE = 1.0/(2 * fE * fE); // Normalizes sigma fF = (fE*ANGSTROMS_PER_NM); //-->gaussRepulsive pairTable.addPairGaussType2(indexA,indexB,fA,fB,fC,fD,fE,fF); } else { // Generic error statement fprintf(stderr,"Unknown pairFunction in GromacsTopFile.C under the PAIRS section: %d\n",pairFunction); } break; case EXCLUSIONS: /* Start of JLai modifications August 16th, 2012 */ if(2 != sscanf(buf," %d %d ",&atomi,&atomj)) { fprintf(stderr,"Syntax error in EXCLUSIONS: %s\n",buf); exit(1); } // Shift the atom indices to be zero-based atomi--; atomj--; /*Load exclusion information into file*/ exclusions_atom_i.add(atomi); exclusions_atom_j.add(atomj); numExclusion++; /* Reading in exclusions information from file and loading */ break; // End of JLai modifications August 16th, 2012 } } fclose(f); }
void ComputeExtMgr::recvCoord(ExtCoordMsg *msg) { if ( ! numSources ) { numSources = (PatchMap::Object())->numNodesWithPatches(); coordMsgs = new ExtCoordMsg*[numSources]; for ( int i=0; i<numSources; ++i ) { coordMsgs[i] = 0; } numArrived = 0; numAtoms = Node::Object()->molecule->numAtoms; coord = new ComputeExtAtom[numAtoms]; force = new ExtForce[numAtoms]; } int i; for ( i=0; i < msg->numAtoms; ++i ) { coord[msg->coord[i].id] = msg->coord[i]; } coordMsgs[numArrived] = msg; ++numArrived; if ( numArrived < numSources ) return; numArrived = 0; // ALL DATA ARRIVED --- CALCULATE FORCES Lattice lattice = msg->lattice; SimParameters *simParams = Node::Object()->simParameters; FILE *file; int iret; // write coordinates to file //iout << "writing to file " << simParams->extCoordFilename << "\n" << endi; file = fopen(simParams->extCoordFilename,"w"); if ( ! file ) { NAMD_die(strerror(errno)); } for ( i=0; i<numAtoms; ++i ) { int id = coord[i].id + 1; double charge = coord[i].charge; double x = coord[i].position.x; double y = coord[i].position.y; double z = coord[i].position.z; iret = fprintf(file,"%d %f %f %f %f\n",id,charge,x,y,z); if ( iret < 0 ) { NAMD_die(strerror(errno)); } } // write periodic cell lattice (0 0 0 if non-periodic) Vector a = lattice.a(); if ( ! lattice.a_p() ) a = Vector(0,0,0); Vector b = lattice.b(); if ( ! lattice.b_p() ) b = Vector(0,0,0); Vector c = lattice.c(); if ( ! lattice.c_p() ) c = Vector(0,0,0); iret = fprintf(file,"%f %f %f\n%f %f %f\n%f %f %f\n", a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z); if ( iret < 0 ) { NAMD_die(strerror(errno)); } fclose(file); // run user-specified command //iout << "running command " << simParams->extForcesCommand << "\n" << endi; iret = system(simParams->extForcesCommand); if ( iret == -1 ) { NAMD_die(strerror(errno)); } if ( iret ) { NAMD_die("Error running command for external forces."); } // remove coordinate file iret = remove(simParams->extCoordFilename); if ( iret ) { NAMD_die(strerror(errno)); } // read forces from file (overwrite positions) //iout << "reading from file " << simParams->extForceFilename << "\n" << endi; file = fopen(simParams->extForceFilename,"r"); if ( ! file ) { NAMD_die(strerror(errno)); } for ( i=0; i<numAtoms; ++i ) { int id, replace; double x, y, z; iret = fscanf(file,"%d %d %lf %lf %lf\n", &id, &replace, &x, &y, &z); if ( iret != 5 ) { NAMD_die("Error reading external forces file."); } if ( id != i + 1 ) { NAMD_die("Atom ID error in external forces file."); } force[i].force.x = x; force[i].force.y = y; force[i].force.z = z; force[i].replace = replace; } // read energy and virial if they are present // virial used by NAMD is -'ve of normal convention, so reverse it! // virial[i][j] in file should be sum of -1 * f_i * r_j double energy; double virial[3][3]; iret = fscanf(file,"%lf\n", &energy); if ( iret != 1 ) { energy = 0; for ( int k=0; k<3; ++k ) for ( int l=0; l<3; ++l ) virial[k][l] = 0; } else { iret = fscanf(file,"%lf %lf %lf\n%lf %lf %lf\n%lf %lf %lf\n", &virial[0][0], &virial[0][1], &virial[0][2], &virial[1][0], &virial[1][1], &virial[1][2], &virial[2][0], &virial[2][1], &virial[2][2]); if ( iret != 9 ) { for ( int k=0; k<3; ++k ) for ( int l=0; l<3; ++l ) virial[k][l] = 0; } else { // virial used by NAMD is -'ve of normal convention, so reverse it! for ( int k=0; k<3; ++k ) for ( int l=0; l<3; ++l ) virial[k][l] *= -1.0; } } fclose(file); // remove force file iret = remove(simParams->extForceFilename); if ( iret ) { NAMD_die(strerror(errno)); } // distribute forces for ( int j=0; j < numSources; ++j ) { ExtCoordMsg *cmsg = coordMsgs[j]; coordMsgs[j] = 0; ExtForceMsg *fmsg = new (cmsg->numAtoms, 0) ExtForceMsg; for ( int i=0; i < cmsg->numAtoms; ++i ) { fmsg->force[i] = force[cmsg->coord[i].id]; } if ( ! j ) { fmsg->energy = energy; for ( int k=0; k<3; ++k ) for ( int l=0; l<3; ++l ) fmsg->virial[k][l] = virial[k][l]; } else { fmsg->energy = 0; for ( int k=0; k<3; ++k ) for ( int l=0; l<3; ++l ) fmsg->virial[k][l] = 0; } extProxy[cmsg->sourceNode].recvForce(fmsg); delete cmsg; } }
void ComputeMsmSerialMgr::recvCoord(MsmSerialCoordMsg *msg) { if ( ! numSources ) { numSources = (PatchMap::Object())->numNodesWithPatches(); coordMsgs = new MsmSerialCoordMsg*[numSources]; for ( int i=0; i<numSources; ++i ) { coordMsgs[i] = 0; } numArrived = 0; numAtoms = Node::Object()->molecule->numAtoms; coord = new ComputeMsmSerialAtom[numAtoms]; force = new MsmSerialForce[numAtoms]; } int i; for ( i=0; i < msg->numAtoms; ++i ) { coord[msg->coord[i].id] = msg->coord[i]; } coordMsgs[numArrived] = msg; ++numArrived; if ( numArrived < numSources ) return; numArrived = 0; // ALL DATA ARRIVED --- CALCULATE FORCES Lattice lattice = msg->lattice; SimParameters *simParams = Node::Object()->simParameters; double energy = 0; double virial[3][3]; int rc = 0; // return code if ( ! msmsolver ) { // // setup MSM solver // msmsolver = NL_msm_create(); if ( ! msmsolver ) NAMD_die("unable to create MSM solver"); double dielectric = simParams->dielectric; double cutoff = simParams->cutoff; double gridspacing = simParams->MSMGridSpacing; double padding = simParams->MSMPadding; int approx = simParams->MSMApprox; int split = simParams->MSMSplit; int nlevels = simParams->MSMLevels; int msmflags = 0; msmflags |= (lattice.a_p() ? NL_MSM_PERIODIC_VEC1 : 0); msmflags |= (lattice.b_p() ? NL_MSM_PERIODIC_VEC2 : 0); msmflags |= (lattice.c_p() ? NL_MSM_PERIODIC_VEC3 : 0); msmflags |= NL_MSM_COMPUTE_LONG_RANGE; // compute only long-range part //msmflags |= NL_MSM_COMPUTE_ALL; //printf("msmflags = %x\n", msmflags); rc = NL_msm_configure(msmsolver, gridspacing, approx, split, nlevels); if (rc) NAMD_die("unable to configure MSM solver"); Vector u=lattice.a(), v=lattice.b(), w=lattice.c(), c=lattice.origin(); Vector ru=lattice.a_r(), rv=lattice.b_r(), rw=lattice.c_r(); if ((msmflags & NL_MSM_PERIODIC_ALL) != NL_MSM_PERIODIC_ALL) { // called only if there is some non-periodic boundary int isperiodic = (msmflags & NL_MSM_PERIODIC_ALL); //printf("calling rescale\n"); rescale_nonperiodic_cell(u, v, w, c, ru, rv, rw, isperiodic, numAtoms, coord, padding, gridspacing); } double vec1[3], vec2[3], vec3[3], center[3]; vec1[0] = u.x; vec1[1] = u.y; vec1[2] = u.z; vec2[0] = v.x; vec2[1] = v.y; vec2[2] = v.z; vec3[0] = w.x; vec3[1] = w.y; vec3[2] = w.z; center[0] = c.x; center[1] = c.y; center[2] = c.z; #if 0 printf("dielectric = %g\n", dielectric); printf("vec1 = %g %g %g\n", vec1[0], vec1[1], vec1[2]); printf("vec2 = %g %g %g\n", vec2[0], vec2[1], vec2[2]); printf("vec3 = %g %g %g\n", vec3[0], vec3[1], vec3[2]); printf("center = %g %g %g\n", center[0], center[1], center[2]); printf("cutoff = %g\n", cutoff); printf("numatoms = %d\n", numAtoms); #endif rc = NL_msm_setup(msmsolver, cutoff, vec1, vec2, vec3, center, msmflags); if (rc) NAMD_die("unable to set up MSM solver"); msmcoord = new double[4*numAtoms]; msmforce = new double[3*numAtoms]; if (msmcoord==0 || msmforce==0) NAMD_die("can't allocate MSM atom buffers"); // scale charges - these won't change double celec = sqrt(COULOMB / simParams->dielectric); for (i = 0; i < numAtoms; i++) { msmcoord[4*i+3] = celec * coord[i].charge; } } // evaluate long-range MSM forces for (i = 0; i < numAtoms; i++) { msmcoord[4*i ] = coord[i].position.x; msmcoord[4*i+1] = coord[i].position.y; msmcoord[4*i+2] = coord[i].position.z; } for (i = 0; i < numAtoms; i++) { msmforce[3*i ] = 0; msmforce[3*i+1] = 0; msmforce[3*i+2] = 0; } rc = NL_msm_compute_force(msmsolver, msmforce, &energy, msmcoord, numAtoms); if (rc) NAMD_die("error evaluating MSM forces"); for (i = 0; i < numAtoms; i++) { force[i].x = msmforce[3*i ]; force[i].y = msmforce[3*i+1]; force[i].z = msmforce[3*i+2]; } // MSM does not yet calculate virial for (int k=0; k < 3; k++) { for (int l=0; l < 3; l++) { virial[k][l] = 0; } } // distribute forces for (int j=0; j < numSources; j++) { MsmSerialCoordMsg *cmsg = coordMsgs[j]; coordMsgs[j] = 0; MsmSerialForceMsg *fmsg = new (cmsg->numAtoms, 0) MsmSerialForceMsg; for (int i=0; i < cmsg->numAtoms; i++) { fmsg->force[i] = force[cmsg->coord[i].id]; } if ( ! j ) { // set virial and energy only for first message fmsg->energy = energy; for (int k=0; k < 3; k++) { for (int l=0; l < 3; l++) { fmsg->virial[k][l] = virial[k][l]; } } } else { // set other messages to zero, add into reduction only once fmsg->energy = 0; for (int k=0; k < 3; k++) { for (int l=0; l < 3; l++) { fmsg->virial[k][l] = 0; } } } msmProxy[cmsg->sourceNode].recvForce(fmsg); delete cmsg; } }
void ReductionMgr::buildSpanTree(const int pe, const int max_intranode_children, const int max_internode_children, int* parent, int* num_children, int** children) { // If pe is a first-node, children are same-node pes and perhaps some // other first-nodes, and parents are other first-nodes. If pe is not a // first-node, build the spanning tree among the children, and the parent // is the corresponding first-node #if CHARM_VERSION < 60103 #define CmiPhysicalNodeID(X) X #define CmiNumPesOnPhysicalNode(X) 1 #define CmiGetFirstPeOnPhysicalNode(X) (X) #define CmiPeOnSamePhysicalNode(X,Y) ((X)==(Y)) #endif // No matter what, build list of PEs on my node first const int num_pes = CkNumPes(); const int num_node_pes = CmiNumPesOnPhysicalNode(CmiPhysicalNodeID(pe)); int *node_pes = new int[num_node_pes]; int pe_index; const int first_pe = CmiGetFirstPeOnPhysicalNode(CmiPhysicalNodeID(pe)); int num_nodes = 0; int *node_ids = new int[num_pes]; int first_pe_index; int my_parent_index; // Make sure PE 0 is a first-node if (pe == 0 && first_pe != pe) { NAMD_die("PE 0 is not the first physical node. This shouldn't happen"); } // Get all the PEs on my node, and also build the list of all first-nodes int i; int node_pe_count=0; for (i = 0; i < num_pes; i++) { // Save first-nodes if (CmiGetFirstPeOnPhysicalNode(CmiPhysicalNodeID(i)) == i) { node_ids[num_nodes] = i; if (i == first_pe) first_pe_index = num_nodes; num_nodes++; } // Also, find pes on my node const int i1 = (i + first_pe) % num_pes; if (CmiPeOnSamePhysicalNode(first_pe,i1)) { node_pes[node_pe_count] = i1; if (pe == i1) pe_index = node_pe_count; node_pe_count++; } } // Any PE might have children on the same node, plus, if its a first-node, // it may have several children on other nodes int first_loc_child_index = pe_index * max_intranode_children + 1; int last_loc_child_index = first_loc_child_index + max_intranode_children - 1; if (first_loc_child_index > num_node_pes) { first_loc_child_index = num_node_pes; last_loc_child_index = num_node_pes; } else { if (last_loc_child_index >= num_node_pes) last_loc_child_index = num_node_pes-1; } // CkPrintf("Local [%d] firstpe %d max %d num %d firstloc %d lastloc %d\n", // pe,pe_index,max_intranode_children,num_node_pes, // first_loc_child_index,last_loc_child_index); int first_rem_child_index = num_nodes; int last_rem_child_index = num_nodes; if (first_pe != pe) { // I'm not a first_pe, so I have no more children, and my parent // is someone else on my node my_parent_index = (pe_index-1)/max_intranode_children; *parent = node_pes[my_parent_index]; } else { // I am a first_pe, so I may have additional children // on other nodes, and my parent will be on another node if (pe == 0) { my_parent_index = -1; *parent = -1; } else { my_parent_index = (first_pe_index-1)/max_internode_children; *parent = node_ids[my_parent_index]; // CkPrintf("[%d] my_parent_index=%d parent=%d\n", // pe,my_parent_index,*parent); } first_rem_child_index = first_pe_index * max_internode_children + 1; last_rem_child_index = first_rem_child_index + max_internode_children -1; if (first_rem_child_index > num_nodes) { first_rem_child_index = num_nodes; last_rem_child_index = num_nodes; } else { if (last_rem_child_index >= num_nodes) last_rem_child_index = num_nodes-1; } // CkPrintf("Remote [%d] firstpe %d max %d num %d firstrem %d lastrem %d\n", // pe,first_pe_index,max_internode_children,num_nodes, // first_rem_child_index,last_rem_child_index); } *num_children = 0; //CkPrintf("TREE pe %d my_parent %d %d\n",pe,my_parent_index,*parent); int loc_children=0; if (first_loc_child_index != num_node_pes) { loc_children = last_loc_child_index - first_loc_child_index + 1; *num_children += loc_children; // CkPrintf("TREE pe %d %d local children\n",pe,loc_children); // } else { // CkPrintf("TREE pe %d No local children\n",pe); } int rem_children=0; if (first_rem_child_index != num_nodes) { rem_children = last_rem_child_index - first_rem_child_index + 1; *num_children += rem_children; // CkPrintf("TREE pe %d %d rem children\n",pe,rem_children); // } else { // CkPrintf("TREE pe %d No rem children\n",pe); } if (*num_children == 0) *children = 0; else { *children = new int[*num_children]; // CkPrintf("TREE pe %d children %d\n",pe,*num_children); int k; int child=0; if (loc_children > 0) { for(k=first_loc_child_index; k <= last_loc_child_index; k++) { // CkPrintf("TREE pe %d loc child[%d,%d] %d\n",pe,child,k,node_pes[k]); (*children)[child++]=node_pes[k]; } } if (rem_children > 0) { for(k=first_rem_child_index; k <= last_rem_child_index; k++) { // CkPrintf("TREE pe %d rem child[%d,%d] %d\n",pe,child,k,node_ids[k]); (*children)[child++]=node_ids[k]; } } } delete [] node_ids; delete [] node_pes; }
int ScriptTcl::Tcl_coorfile(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) { ScriptTcl *script = (ScriptTcl *)clientData; script->initcheck(); if (argc == 4 && !strcmp(argv[1], "open")) { if (strcmp(argv[2], "dcd")) { NAMD_die("Sorry, coorfile presently supports only DCD files"); } filehandle = dcdplugin->open_file_read(argv[3], "dcd", &numatoms); if (!filehandle) { Tcl_AppendResult(interp, "coorfile: Error opening file ", argv[3], NULL); return TCL_ERROR; } if (numatoms != Node::Object()->pdb->num_atoms()) { Tcl_AppendResult(interp, "Coordinate file ", argv[3], "\ncontains the wrong number of atoms.", NULL); return TCL_ERROR; } coords = new float[3*numatoms]; vcoords = new Vector[3*numatoms]; iout << iINFO << "Coordinate file " << argv[3] << " opened for reading.\n" << endi; } else if (argc == 2 && !strcmp(argv[1], "read")) { if (filehandle == NULL) { Tcl_AppendResult(interp, "coorfile read: Error, no file open for reading", NULL); return TCL_ERROR; } molfile_timestep_t ts; ts.coords = coords; int rc = dcdplugin->read_next_timestep(filehandle, numatoms, &ts); if (rc) { // EOF Tcl_SetObjResult(interp, Tcl_NewIntObj(-1)); return TCL_OK; } iout << iINFO << "Reading timestep from file.\n" << endi; Lattice lattice; if (get_lattice_from_ts(&lattice, &ts)) { iout << iINFO << "Updating unit cell from timestep.\n" << endi; if ( lattice.a_p() && ! script->state->lattice.a_p() || lattice.b_p() && ! script->state->lattice.b_p() || lattice.c_p() && ! script->state->lattice.c_p() ) { iout << iWARN << "Cell basis vectors should be specified before reading trajectory.\n" << endi; } // update Controller's lattice, but don't change the origin! Vector a(0.); if ( script->state->lattice.a_p() ) a = lattice.a(); Vector b(0.); if ( script->state->lattice.b_p() ) b = lattice.b(); Vector c(0.); if ( script->state->lattice.c_p() ) c = lattice.c(); script->state->lattice.set(a,b,c); SetLatticeMsg *msg = new SetLatticeMsg; msg->lattice = script->state->lattice; (CProxy_PatchMgr(CkpvAccess(BOCclass_group).patchMgr)).setLattice(msg); script->barrier(); } for (int i=0; i<numatoms; i++) { vcoords[i].x = coords[3*i+0]; vcoords[i].y = coords[3*i+1]; vcoords[i].z = coords[3*i+2]; } Node::Object()->pdb->set_all_positions(vcoords); script->reinitAtoms(); Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); } else if (argc == 2 && !strcmp(argv[1], "close")) { if (!filehandle) { Tcl_AppendResult(interp, "coorfile close: No file opened for reading!", NULL); return TCL_OK; } iout << iINFO << "Closing coordinate file.\n" << endi; dcdplugin->close_file_read(filehandle); filehandle = NULL; delete [] coords; delete [] vcoords; } else if (argc ==2 && !strcmp(argv[1], "skip")) { if (filehandle == NULL) { Tcl_AppendResult(interp, "coorfile skip: Error, no file open for reading", NULL); return TCL_ERROR; } int rc = dcdplugin->read_next_timestep(filehandle, numatoms, NULL); if (rc) { // EOF Tcl_SetObjResult(interp, Tcl_NewIntObj(-1)); return TCL_OK; } Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); } else { NAMD_die("Unknown option passed to coorfile"); } return TCL_OK; }