Example #1
0
/*  This is necessary to ensure a minimal state at checkpoint time.
    sim::Commit() requires a minimum advancement in GVT (currently 100
    ticks) before the event queue commits its events.  As a result,
    some events could be left in the queue.  This function takes care
    of that.
*/
void sim::CheckpointCommit() {
  if (active < 0)  return; // object is migrating
#if !CMK_TRACE_DISABLED
  double critStart;
  if(pose_config.trace)
    critStart= CmiWallTimer();  // trace timing
  int tstat;
  if(pose_config.stats) {
    tstat = localStats->TimerRunning();
    if (!tstat)  localStats->TimerStart(SIM_TIMER);
    else localStats->SwitchTimer(SIM_TIMER);
  }
  if(pose_config.stats)
    localStats->SwitchTimer(FC_TIMER);
#endif
  int curGVT = localPVT->getGVT();
  lastGVT = curGVT;
  eq->CommitEvents(this, lastGVT); // commit everything up to the current GVT
#if !CMK_TRACE_DISABLED
  if(pose_config.trace) {
    traceUserBracketEvent(50, critStart, CmiWallTimer());
    critStart = CmiWallTimer();
  }
  if(pose_config.stats)
    localStats->SwitchTimer(SIM_TIMER);
#endif
#if !CMK_TRACE_DISABLED
  if(pose_config.stats)
    if (!tstat)  localStats->TimerStop();
    else localStats->SwitchTimer(tstat);
  if(pose_config.trace)
    traceUserBracketEvent(60, critStart, CmiWallTimer());
#endif
}
Example #2
0
/// Add m to cancellation list
void sim::Cancel(cancelMsg *m) 
{
#if !CMK_TRACE_DISABLED
  if(pose_config.stats)
    localStats->TimerStart(CAN_TIMER);
#endif
  //  char str[20];
  //  CkPrintf("[%d] RECV(cancel) %s at %d...\n", CkMyPe(), m->evID.sdump(str), m->timestamp);      
  //localPVT = (PVT *)CkLocalBranch(ThePVT);
  cancels.Insert(m->timestamp, m->evID); // add to cancellations list
  localPVT->objUpdate(m->timestamp, RECV); // tell PVT branch about recv
  CkFreeMsg(m);

#if !CMK_TRACE_DISABLED
  double critStart;
  if(pose_config.trace)
    critStart= CmiWallTimer();  // trace timing
  if(pose_config.stats)
    localStats->SwitchTimer(SIM_TIMER);      
#endif

  myStrat->Step(); // call Step to handle cancellation

#if !CMK_TRACE_DISABLED
  if(pose_config.stats)
    localStats->TimerStop();
  if(pose_config.trace)
    traceUserBracketEvent(60, critStart, CmiWallTimer());
#endif
}
Example #3
0
/// Commit events based on new GVT estimate
void sim::Commit()
{
  if (active < 0)  return; // object is migrating
#if !CMK_TRACE_DISABLED
  double critStart;
  if(pose_config.trace)
    critStart= CmiWallTimer();  // trace timing
  int tstat;
  if(pose_config.stats) {
    tstat = localStats->TimerRunning();
    if (!tstat)  localStats->TimerStart(SIM_TIMER);
    else localStats->SwitchTimer(SIM_TIMER);
  }
  if(pose_config.stats)
    localStats->SwitchTimer(FC_TIMER);
#endif
  int isDone=localPVT->done(); 
  int curGVT=localPVT->getGVT();
  if (isDone) { // simulation inactive
    eq->CommitEvents(this, POSE_endtime); // commit all events in queue
    Terminate();// call terminus on all posers
  }
  else if (curGVT > lastGVT + 100) {  // What's the constant doing to us?
    lastGVT = curGVT;
    eq->CommitEvents(this, lastGVT); // commit events up to GVT
  }
#if !CMK_TRACE_DISABLED
  if(pose_config.trace) {
    traceUserBracketEvent(50, critStart, CmiWallTimer());
    critStart = CmiWallTimer();
  }
  if(pose_config.stats)
    localStats->SwitchTimer(SIM_TIMER);
#endif
  if (!isDone && (eq->currentPtr->timestamp > -1))
    Step(); // not done; try stepping again

#if !CMK_TRACE_DISABLED
  if(pose_config.stats)
    if (!tstat)  localStats->TimerStop();
    else localStats->SwitchTimer(tstat);
  if(pose_config.trace)
    traceUserBracketEvent(60, critStart, CmiWallTimer());
#endif
}
Example #4
0
/// Start a forward execution step on myStrat
void sim::Step()
{
  if (active < 0) return; // object is migrating; deactivate it 

#if !CMK_TRACE_DISABLED
  double critStart;
  if(pose_config.trace)
    critStart=CmiWallTimer();  // trace timing
  int tstat;
  if(pose_config.stats)
    {
      tstat= localStats->TimerRunning();
      if (!tstat)  localStats->TimerStart(SIM_TIMER);
      else localStats->SwitchTimer(SIM_TIMER);
    }
#endif

  prioMsg *pm;
  switch (myStrat->STRAT_T) { // step based on strategy type
  case SEQ_T:
  case CONS_T:
  case OPT_T:
  case OPT2_T: // pass this step call directly to strategy
  case OPT3_T: // prioritize this step call if work exists
  case SPEC_T:
  case ADAPT_T:
  case ADAPT2_T:
  case ADAPT3_T:
  case ADAPT4_T:
  case ADAPT5_T: // pass this step call directly to strategy
    myStrat->Step();
    break;
  default: 
    CkPrintf("Invalid strategy type: %d\n", myStrat->STRAT_T); 
    break;
  }
#if !CMK_TRACE_DISABLED
  if(pose_config.stats)  
    {
      if (!tstat)  localStats->TimerStop();
      else localStats->SwitchTimer(tstat);
    }
  if(pose_config.trace)
    traceUserBracketEvent(60, critStart, CmiWallTimer());
#endif
}
Example #5
0
//============================================================================
// This function when the density FFT from Rho_R is complete
//============================================================================
//cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
//============================================================================
void CP_Rho_GSpacePlane::acceptRhoData() {
#ifdef _CP_DEBUG_RHOG_VERBOSE_
  CkPrintf("{%d} Rho GS [%d] acceptRhoData\n", thisInstance.proxyOffset, thisIndex);
#endif
#ifdef _CP_DEBUG_RHOG_RHOG_
  char myFileName[100];
  sprintf(myFileName, "Rho_Gspace_%d.out", thisIndex);
  std::vector< gridPoint > & dpoints = (*myPoints);
  FILE *fp = fopen(myFileName,"w");
  for (int i = 0; i < numPoints; i++){
    fprintf(fp," %d %d %d : %g %g\n", dpoints[i].d3, dpoints[i].d2, dpoints[i].d1,
      divRhoX[dpoints[i].offset].re, divRhoX[dpoints[i].offset].im);
  }//endfor
  fclose(fp);
#endif
  //============================================================================
  // I) Communicate rho(g) to RHoGHartExt to compute eext and hart part of vks
  //     or print out that you are taking the day off

  //------------------------------------------------
  // Hartree is on, send rhoG to the harteext-G chare
#ifndef _CP_DEBUG_HARTEEXT_OFF_  // hartree is cooking
  //create first message to be able to copy
  RhoGHartMsg *msg, *base_msg = new (numPoints) RhoGHartMsg;
  complex *dest = base_msg->data;
  std::vector< gridPoint > & points = (*myPoints);
  for(int p = 0; p < numPoints; p++) {
    int off = points[p].offset;
    dest[p] = divRhoX[off];
  }

  int nchareHartAtmT = config.nchareHartAtmT;
  for(int j = 0; j < nchareHartAtmT; j++) {
    if(j != (nchareHartAtmT - 1)) {
      msg = new (numPoints) RhoGHartMsg;
      CmiMemcpy(msg->data, base_msg->data, numPoints * sizeof(complex));
    } else {
      msg = base_msg;
    }
    msg->size        = numPoints;
    //------------------------------------------------
    //RAZ: This is important:  
    // This is spin modified logic to send to up 
    // instance GHartExt Calc.
    // No way spin down should go there.
    // We are sending Grho from data_out
    //------------------------------------------------
    if (mySpinIndex==0){
      UrhoGHartExtProxy[thisInstance.proxyOffset](thisIndex,j).acceptData(msg);
    }else if(mySpinIndex==1){
      UberCollection upinstance=thisInstance;
      // flip the spin
      upinstance.idxU.s= !upinstance.idxU.s;
      // get new offset
      int Offset2RhoUp=upinstance.setPO();
      UrhoGHartExtProxy[Offset2RhoUp](thisIndex,j).acceptData(msg);
    }//endif spin logic

  }//endfor : atmType parallelization
#else // Hartree is off, chill
  if(thisIndex == 0) {
    CkPrintf("EHART       = OFF FOR DEBUGGING\n");
    CkPrintf("EExt        = OFF FOR DEBUGGING\n");
    CkPrintf("EWALD_recip = OFF FOR DEBUGGING\n");
  }//endif
#endif

  //============================================================================
  // III) Start grad corr computations if necessary

#if CMK_TRACE_ENABLED
  double StartTime=CmiWallTimer();
#endif
  if(simReadOnly.cp_grad_corr_on != 0) {
    divRhoVksGspace();
  }
#if CMK_TRACE_ENABLED
  traceUserBracketEvent(divRhoVksGspace_, StartTime, CmiWallTimer());
#endif

  //============================================================================
  //kick off NL if its our job

  launchNlG();

  //---------------------------------------------------------------------------
}//end routine
Example #6
0
/// Single forward execution step
void adapt5::Step()
{
  Event *ev;
  POSE_TimeType lastGVT = localPVT->getGVT();
  POSE_TimeType maxTimeLeash, offset;
  double critStart;

  rbFlag = 0;
  if (!parent->cancels.IsEmpty()) CancelUnexecutedEvents();
  if (eq->RBevent) Rollback();
  if (!parent->cancels.IsEmpty()) CancelEvents();
  parent->Status();

/*
  if (rbFlag) { // adjust leash according to rollback
    timeLeash = avgRBoffset;
  }
  else if (timeLeash < theMaxLeash) { // adjust according to state
    if (eq->currentPtr->timestamp > POSE_UnsetTS) { // adjust to next event
      if (eq->currentPtr->timestamp - lastGVT > timeLeash)
	timeLeash == eq->currentPtr->timestamp - lastGVT;
      // else leave it alone
    }
    // no next event; leave it alone
  }
  // Put leash back into reasonable bounds
  if (timeLeash > theMaxLeash) {
    timeLeash = theMaxLeash;
  }
  else if (timeLeash < 0) timeLeash = 0;
*/


/*
  int i = timeLeash >> 6;
  if (i > 1) {
    if (rbFlag) {
      timeLeash -= i;
    } else {
      timeLeash += i;
    }
  } else {
    if (rbFlag) {
      timeLeash--;
    } else {
      timeLeash++;
    }
  }

  if (timeLeash <= 0) {
    timeLeash = 10;
  }
*/
/*
  if (rbFlag) {
    timeLeash = timeLeash >> 1;
  } else {
    timeLeash++;
  }
*/

// other possibilities:
// -run for a number of events with a fixed timeleash, then analyze
// and adjust
// -simply use recentAvgEventSparsity * avgEventsPerRB
// -add code that looks at the number of RBs this poser is responsible
// for and don't punish it if it doesn't have a lot

  ev = eq->currentPtr;

  if (parent->basicStats[1] > 0) {
    avgEventsPerRB = (int)(parent->basicStats[0] / parent->basicStats[1]);
    if (avgEventsPerRB < 1) {
      avgEventsPerRB = 1;
    }
  }

  // ======== attempt 1 ========
#if ALGORITHM_TO_USE == 1
  if (rbFlag) {
    recentAvgRBLeashCount++;
    recentTotalRBLeash += timeLeash;
    // initial rollback calculation to quickly set recentAvgRBLeash to a reasonable value
    if (initialAvgRBLeashCalc) {
      recentAvgRBLeash = avgRBoffset;
      recentTotalRBLeash = 0;
      recentAvgRBLeashCount = 0;
      initialAvgRBLeashCalc = false;
    }
    // calculate the recent average timeleash when rollbacks occur
    if (recentAvgRBLeashCount >= AVG_LEASH_CALC_PERIOD) {
      recentAvgRBLeash = recentTotalRBLeash / recentAvgRBLeashCount;
      recentTotalRBLeash = 0;
      recentAvgRBLeashCount = 0;
    }
    if (timeLeash > recentAvgRBLeash) {
      timeLeash = recentAvgRBLeash;
    } else {
      timeLeash = recentAvgRBLeash / 2;
    }
  } else {
    timeLeash += recentAvgEventSparsity;
  }

  if (avgRBsPerGVTIter > MAX_RB_PER_GVT_ITER) {
    maxTimeLeash = recentAvgRBLeash / 2;
  } else {
    maxTimeLeash = (POSE_TimeType)MAX_LEASH_MULTIPLIER * (POSE_TimeType)recentAvgEventSparsity * (POSE_TimeType)avgEventsPerRB;
  }

  if (maxTimeLeash > 50000) {
    maxTimeLeash = 50000;
  }
  if (timeLeash > maxTimeLeash) {
    timeLeash = maxTimeLeash;
  }
  if (timeLeash < 1) {
    timeLeash = 1;
  }
#endif

  // ======== attempt 2 ========
#if ALGORITHM_TO_USE == 2
  timeLeash = recentAvgEventSparsity * avgEventsPerRB;

  if (timeLeash > 50000) {
    timeLeash = 50000;
  }

  if (timeLeash < 1) {
    timeLeash = 1;
  }
#endif

  // ======== attempt 3 ========
#if ALGORITHM_TO_USE == 3
  timeLeash += recentAvgEventSparsity;

  if (avgRBsPerGVTIter > MAX_RB_PER_GVT_ITER) {
    maxTimeLeash = ((POSE_TimeType)MAX_LEASH_MULTIPLIER * (POSE_TimeType)recentAvgEventSparsity * (POSE_TimeType)avgEventsPerRB) / (4 * (POSE_TimeType)avgRBsPerGVTIter);
  } else {
    maxTimeLeash = 1000;
  }  

  if (maxTimeLeash > 50000) {
    maxTimeLeash = 50000;
  }
  if (timeLeash > maxTimeLeash) {
    timeLeash = maxTimeLeash;
  }
  if (timeLeash < 1) {
    timeLeash = 1;
  }
#endif

  // ======== attempt 4 ========
#if ALGORITHM_TO_USE == 4
  if (timeLeash > 10000) {
    timeLeash = 10000;
  }
  if (timeLeash < 1) {
    timeLeash = 1;
  }
#endif


/*
  if (rbFlag) {
    GVT *localGVT = (GVT *)CkLocalBranch(TheGVT);
    int numRollbacks = parent->basicStats[1];
    int numGVTIters = localGVT->gvtIterationCount;
    if (userObj->myHandle == 32) {
      CkPrintf("*** ROLLBACK: numRollbacks=%d numGVTIters=%d\n", numRollbacks, numGVTIters);
    }
    if ((numGVTIters > 0) && (((96 * numRollbacks) / numGVTIters) > 2)) {
      timeLeash = avgRBoffset;
    } else {
      timeLeash++;
    }
  } else {
    timeLeash++;
  }

  if (timeLeash > (avgRBoffset << 1)) {
    timeLeash = avgRBoffset << 1;
  }
*/


  // can also just hard-code the time leash
//  timeLeash = 1000;


  //  if (stepCalls == 0) {
  //    timeLeashTotal = 0LL;
  //  }

  //  if (timeLeash < 1000000) {
  //    stepCalls++;
  //    timeLeashTotal += timeLeash;
  //  }

/*
  if (itersAllowed < 1) {
    itersAllowed = 1;
  }
  else {
    itersAllowed = (int)((double)specEventCount * specTol);
    itersAllowed -= specEventCount - eventCount;
    if (itersAllowed < 1) itersAllowed = 1;
  }
*/


  // Prepare to execute an event
  offset = lastGVT + timeLeash;
  // Shorten the leash as we near POSE_endtime
  if ((POSE_endtime > POSE_UnsetTS) && ((offset > POSE_endtime) ||
					(offset <= POSE_UnsetTS)))
    offset = POSE_endtime;

  while ((ev->timestamp > POSE_UnsetTS) && (ev->timestamp <= offset) ){
#ifdef MEM_COARSE
    // Check to see if we should hold off on forward execution to save on 
    // memory.
    // NOTE: to avoid deadlock, make sure we have executed something
    // beyond current GVT before worrying about memory usage
    if (((ev->timestamp > lastGVT) || (userObj->OVT() > lastGVT))
	&& (eq->mem_usage > objUsage)) { // don't deadlock
      break;
    }
#endif

    iter++;
    currentEvent = ev;
    ev->done = 2;
    localPVT->incSpecEventCount();
    localPVT->incEventCount();
    specEventCount++;
    eventCount++;
#ifndef CMK_OPTIMIZE
    if(pose_config.trace)
      critStart = CmiWallTimer();  // trace timing
#endif
    parent->ResolveFn(ev->fnIdx, ev->msg); // execute it
#ifndef CMK_OPTIMIZE
    if(pose_config.trace)
      traceUserBracketEvent(10, critStart, CmiWallTimer());
#endif
    ev->done = 1; // flag the event as executed
    eq->mem_usage++;
    eq->ShiftEvent(); // shift to next event
    ev = eq->currentPtr;
  }
#ifndef CMK_OPTIMIZE
  if(pose_config.stats)
    if (iter > 0) localStats->Loop();
#endif
}
int ComputeNonbondedPair::noWork() {

  if (patch[0]->flags.doGBIS) {
    gbisPhase = 1 + (gbisPhase % 3);//1->2->3->1...
  }

#ifndef NAMD_CUDA
  if ( patch[0]->flags.doNonbonded && (numAtoms[0] && numAtoms[1]) ) {
    return 0;  // work to do, enqueue as usual
  } else {
#else
  {
#endif

    if (patch[0]->flags.doGBIS) {
     if (gbisPhase == 1) {
      for (int i=0; i<2; i++) {
        psiSumBox[i]->skip();
        intRadBox[i]->skip();
      }
      if (patch[0]->flags.doNonbonded) return 1;
      else gbisPhase = 2;
     }
     if (gbisPhase == 2) {
      for (int i=0; i<2; i++) {
        bornRadBox[i]->skip();
        dEdaSumBox[i]->skip();
      }
      if (patch[0]->flags.doNonbonded) return 1;
      else gbisPhase = 3;
     }
     if (gbisPhase == 3) {
      for (int i=0; i<2; i++) {
        dHdrPrefixBox[i]->skip();
      }
     }
    }

    // skip all boxes
    for (int i=0; i<2; i++) {
      positionBox[i]->skip();
      forceBox[i]->skip();
      if ( patch[0]->flags.doMolly ) avgPositionBox[i]->skip();
      // BEGIN LA
      if (patch[0]->flags.doLoweAndersen) velocityBox[i]->skip();
      // END LA
    }

    reduction->item(REDUCTION_COMPUTE_CHECKSUM) += 1.;
    reduction->submit();
    if (accelMDOn) amd_reduction->submit();
    if (pressureProfileOn) 
      pressureProfileReduction->submit();

#ifndef NAMD_CUDA
    // Inform load balancer
    LdbCoordinator::Object()->skipWork(ldObjHandle);
#endif

    return 1;  // no work to do, do not enqueue
  }
}

void ComputeNonbondedPair::doForce(CompAtom* p[2], CompAtomExt* pExt[2], Results* r[2])
{
  // Inform load balancer. 
  // I assume no threads will suspend until endWork is called

  //single phase declarations
  int doEnergy = patch[0]->flags.doEnergy;
  int a = 0;  int b = 1;
  // swap to place more atoms in inner loop (second patch)
  if ( numAtoms[0] > numAtoms[1] ) { a = 1; b = 0; }
  CompAtom* v[2];


/*******************************************************************************
 * Prepare Parameters
*******************************************************************************/
  if (!patch[0]->flags.doGBIS || gbisPhase == 1) {

#ifdef TRACE_COMPUTE_OBJECTS
    double traceObjStartTime = CmiWallTimer();
#endif

  DebugM(2,"doForce() called.\n");
  DebugM(2, numAtoms[0] << " patch #1 atoms and " <<
	numAtoms[1] << " patch #2 atoms\n");


  for ( int i = 0; i < reductionDataSize; ++i )
    reductionData[i] = 0;
  if (pressureProfileOn) {
    int n = pressureProfileAtomTypes; 
    memset(pressureProfileData, 0, 3*n*n*pressureProfileSlabs*sizeof(BigReal));
    // adjust lattice dimensions to allow constant pressure
    const Lattice &lattice = patch[0]->lattice;
    pressureProfileThickness = lattice.c().z / pressureProfileSlabs;
    pressureProfileMin = lattice.origin().z - 0.5*lattice.c().z;
  }

    params.reduction = reductionData;
    params.pressureProfileReduction = pressureProfileData;

    params.minPart = minPart;
    params.maxPart = maxPart;
    params.numParts = numParts;

    params.workArrays = workArrays;

    params.pairlists = &pairlists;
    params.savePairlists = 0;
    params.usePairlists = 0;
    if ( patch[0]->flags.savePairlists ) {
      params.savePairlists = 1;
      params.usePairlists = 1;
    } else if ( patch[0]->flags.usePairlists && patch[1]->flags.usePairlists ) {
      if ( ! pairlistsValid ||
           ( patch[0]->flags.maxAtomMovement +
             patch[1]->flags.maxAtomMovement > pairlistTolerance ) ) {
        reductionData[pairlistWarningIndex] += 1;
      } else {
        params.usePairlists = 1;
      }
    }
    if ( ! params.usePairlists ) {
      pairlistsValid = 0;
    }
    params.plcutoff = cutoff;
    params.groupplcutoff = cutoff +
	patch[0]->flags.maxGroupRadius + patch[1]->flags.maxGroupRadius;
    if ( params.savePairlists ) {
      pairlistsValid = 1;
      pairlistTolerance = patch[0]->flags.pairlistTolerance +
                          patch[1]->flags.pairlistTolerance;
      params.plcutoff += pairlistTolerance;
      params.groupplcutoff += pairlistTolerance;
    }


    const Lattice &lattice = patch[0]->lattice;
    params.offset = lattice.offset(trans[a]) - lattice.offset(trans[b]);

    // Atom Sorting : If we are sorting the atoms along the line connecting
    //   the patch centers, then calculate a normalized vector pointing from
    //   patch a to patch b (i.e. outer loop patch to inner loop patch).
    #if NAMD_ComputeNonbonded_SortAtoms != 0

      // Center of patch a (outer-loop; i-loop) and patch b (inner-loop; j/k-loop)
      PatchMap* patchMap = PatchMap::Object();
      ScaledPosition p_a_center, p_b_center;
      p_a_center.x = patchMap->min_a(patchID[a]);
      p_a_center.y = patchMap->min_b(patchID[a]);
      p_a_center.z = patchMap->min_c(patchID[a]);
      p_b_center.x = patchMap->min_a(patchID[b]);
      p_b_center.y = patchMap->min_b(patchID[b]);
      p_b_center.z = patchMap->min_c(patchID[b]);
      p_a_center.x += patchMap->max_a(patchID[a]);
      p_a_center.y += patchMap->max_b(patchID[a]);
      p_a_center.z += patchMap->max_c(patchID[a]);
      p_b_center.x += patchMap->max_a(patchID[b]);
      p_b_center.y += patchMap->max_b(patchID[b]);
      p_b_center.z += patchMap->max_c(patchID[b]);
      p_a_center *= (BigReal)0.5;
      p_b_center *= (BigReal)0.5;
      p_a_center = lattice.unscale(p_a_center);
      p_b_center = lattice.unscale(p_b_center);

      // Adjust patch a's center by the offset
      p_a_center.x += params.offset.x;
      p_a_center.y += params.offset.y;
      p_a_center.z += params.offset.z;

      // Calculate and fill in the projected line vector
      params.projLineVec = p_b_center - p_a_center;
      params.projLineVec /= params.projLineVec.length(); // Normalize the vector

    #endif

      params.p[0] = p[a];
      params.p[1] = p[b];
      params.pExt[0] = pExt[a]; 
      params.pExt[1] = pExt[b];
      // BEGIN LA
      params.doLoweAndersen = patch[0]->flags.doLoweAndersen;
      if (params.doLoweAndersen) {
	  DebugM(4, "opening velocity boxes\n");
	  v[0] = velocityBox[0]->open();
	  v[1] = velocityBox[1]->open();
	  params.v[0] = v[a];
	  params.v[1] = v[b];
      }
      // END LA
      params.ff[0] = r[a]->f[Results::nbond];
      params.ff[1] = r[b]->f[Results::nbond];
      params.numAtoms[0] = numAtoms[a];
      params.numAtoms[1] = numAtoms[b];

      // DMK - Atom Separation (water vs. non-water)
      #if NAMD_SeparateWaters != 0
        params.numWaterAtoms[0] = numWaterAtoms[a];
        params.numWaterAtoms[1] = numWaterAtoms[b];
      #endif


/*******************************************************************************
 * Call Nonbonded Functions
*******************************************************************************/
      if (numAtoms[0] && numAtoms[1]) {//only do if has atoms since gbis noWork doesn't account for no atoms

      //force calculation calls
      if ( patch[0]->flags.doFullElectrostatics )
      {
	params.fullf[0] = r[a]->f[Results::slow];
	params.fullf[1] = r[b]->f[Results::slow];
	if ( patch[0]->flags.doMolly ) {
          if ( doEnergy )
            calcPairEnergy(&params);
	  else calcPair(&params);
	  CompAtom *p_avg[2];
	  p_avg[0] = avgPositionBox[0]->open();
	  p_avg[1] = avgPositionBox[1]->open();
	  params.p[0] = p_avg[a];
	  params.p[1] = p_avg[b];
	  if ( doEnergy ) calcSlowPairEnergy(&params);
	  else calcSlowPair(&params);
	  avgPositionBox[0]->close(&p_avg[0]);
	  avgPositionBox[1]->close(&p_avg[1]);
        } else if ( patch[0]->flags.maxForceMerged == Results::slow ) {
          if ( doEnergy ) calcMergePairEnergy(&params);
    else calcMergePair(&params);
  } else {
    if ( doEnergy ) calcFullPairEnergy(&params);
    else calcFullPair(&params);
  }
      }
      else
        if ( doEnergy ) calcPairEnergy(&params);
        else calcPair(&params);

      }//end if has atoms
      
      // BEGIN LA
      if (params.doLoweAndersen) {
	  DebugM(4, "closing velocity boxes\n");
	  velocityBox[0]->close(&v[0]);
	  velocityBox[1]->close(&v[1]);
      }
      // END LA
    }// end not gbis

/*******************************************************************************
 * gbis Loop
*******************************************************************************/
if (patch[0]->flags.doGBIS) {
  SimParameters *simParams = Node::Object()->simParameters;
  gbisParams.sequence = sequence();
  gbisParams.doGBIS = patch[0]->flags.doGBIS;
  gbisParams.numPatches = 2;//pair
  gbisParams.gbisPhase = gbisPhase;
  gbisParams.doFullElectrostatics = patch[0]->flags.doFullElectrostatics;
  gbisParams.epsilon_s = simParams->solvent_dielectric;
  gbisParams.epsilon_p = simParams->dielectric;
  gbisParams.rho_0 = simParams->coulomb_radius_offset;
  gbisParams.kappa = simParams->kappa;
  gbisParams.cutoff = simParams->cutoff;
  gbisParams.doSmoothing = simParams->switchingActive;
  gbisParams.a_cut = simParams->alpha_cutoff;
  gbisParams.delta = simParams->gbis_delta;
  gbisParams.beta = simParams->gbis_beta;
  gbisParams.gamma = simParams->gbis_gamma;
  gbisParams.alpha_max = simParams->alpha_max;
  gbisParams.cid = cid;
  gbisParams.patchID[0] = patch[a]->getPatchID();
  gbisParams.patchID[1] = patch[b]->getPatchID();
  gbisParams.maxGroupRadius = patch[0]->flags.maxGroupRadius;
  if (patch[1]->flags.maxGroupRadius > gbisParams.maxGroupRadius)
    gbisParams.maxGroupRadius = patch[1]->flags.maxGroupRadius;
  gbisParams.doEnergy = doEnergy;
  gbisParams.fsMax = simParams->fsMax;
  for (int i = 0; i < numGBISPairlists; i++)
    gbisParams.gbisStepPairlists[i] = &gbisStepPairlists[i];

  //open boxes
  if (gbisPhase == 1) {
      gbisParams.intRad[0] = intRadBox[a]->open();
      gbisParams.intRad[1] = intRadBox[b]->open();
      gbisParams.psiSum[0] = psiSumBox[a]->open();
      gbisParams.psiSum[1] = psiSumBox[b]->open();
      gbisParams.gbInterEnergy=0;
      gbisParams.gbSelfEnergy=0;

  } else if (gbisPhase == 2) {
      gbisParams.bornRad[0] = bornRadBox[a]->open();
      gbisParams.bornRad[1] = bornRadBox[b]->open();
      gbisParams.dEdaSum[0] = dEdaSumBox[a]->open();
      gbisParams.dEdaSum[1] = dEdaSumBox[b]->open();
  } else if (gbisPhase == 3) {
      gbisParams.dHdrPrefix[0] = dHdrPrefixBox[a]->open();
      gbisParams.dHdrPrefix[1] = dHdrPrefixBox[b]->open();
  }

  //make call to calculate GBIS
  if ( !ComputeNonbondedUtil::commOnly ) {
    calcGBIS(&params,&gbisParams);
  }

  //close boxes
  if (gbisPhase == 1) {
      psiSumBox[0]->close(&(gbisParams.psiSum[a]));
      psiSumBox[1]->close(&(gbisParams.psiSum[b]));
  } else if (gbisPhase == 2) {
      dEdaSumBox[0]->close(&(gbisParams.dEdaSum[a]));
      dEdaSumBox[1]->close(&(gbisParams.dEdaSum[b]));


  } else if (gbisPhase == 3) {
      bornRadBox[0]->close(&(gbisParams.bornRad[a]));
      bornRadBox[1]->close(&(gbisParams.bornRad[b]));
      reduction->item(REDUCTION_ELECT_ENERGY) += gbisParams.gbInterEnergy;
      reduction->item(REDUCTION_ELECT_ENERGY) += gbisParams.gbSelfEnergy;
      intRadBox[0]->close(&(gbisParams.intRad[a]));
      intRadBox[1]->close(&(gbisParams.intRad[b]));
      dHdrPrefixBox[0]->close(&(gbisParams.dHdrPrefix[a]));
      dHdrPrefixBox[1]->close(&(gbisParams.dHdrPrefix[b]));
  }

}//end if doGBIS


  if (!patch[0]->flags.doGBIS || gbisPhase == 3) {
  submitReductionData(reductionData,reduction);
  if (accelMDOn) submitReductionData(reductionData,amd_reduction);
  if (pressureProfileOn)
    submitPressureProfileData(pressureProfileData, pressureProfileReduction);

#ifdef TRACE_COMPUTE_OBJECTS
    traceUserBracketEvent(TRACE_COMPOBJ_IDOFFSET+cid, traceObjStartTime, CmiWallTimer());
#endif


  reduction->submit();
  if (accelMDOn) amd_reduction->submit();
  if (pressureProfileOn)
    pressureProfileReduction->submit();
  }//end gbis end phase

}//end do Force