ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/devel_omp/src/brains/ForceManager.cpp
(Generate patch)

Comparing:
branches/development/src/brains/ForceManager.cpp (file contents), Revision 1583 by gezelter, Thu Jun 16 22:00:08 2011 UTC vs.
branches/devel_omp/src/brains/ForceManager.cpp (file contents), Revision 1614 by mciznick, Tue Aug 23 20:55:51 2011 UTC

# Line 38 | Line 38
38   * [3]  Sun, Lin & Gezelter, J. Chem. Phys. 128, 24107 (2008).          
39   * [4]  Vardeman & Gezelter, in progress (2009).                        
40   */
41 <
41 >
42   /**
43   * @file ForceManager.cpp
44   * @author tlin
# Line 47 | Line 47
47   * @version 1.0
48   */
49  
50
50   #include "brains/ForceManager.hpp"
51   #include "primitives/Molecule.hpp"
52   #define __OPENMD_C
# Line 63 | Line 62
62   #include <iostream>
63   #include <iomanip>
64  
65 + #include <omp.h>
66 + //#include <time.h>
67 + #include <sys/time.h>
68 +
69   using namespace std;
70   namespace OpenMD {
68  
69  ForceManager::ForceManager(SimInfo * info) : info_(info) {
70    forceField_ = info_->getForceField();
71    interactionMan_ = new InteractionManager();
72    fDecomp_ = new ForceMatrixDecomposition(info_, interactionMan_);
73  }
71  
72 <  /**
76 <   * setupCutoffs
77 <   *
78 <   * Sets the values of cutoffRadius, cutoffMethod, and cutoffPolicy
79 <   *
80 <   * cutoffRadius : realType
81 <   *  If the cutoffRadius was explicitly set, use that value.
82 <   *  If the cutoffRadius was not explicitly set:
83 <   *      Are there electrostatic atoms?  Use 12.0 Angstroms.
84 <   *      No electrostatic atoms?  Poll the atom types present in the
85 <   *      simulation for suggested cutoff values (e.g. 2.5 * sigma).
86 <   *      Use the maximum suggested value that was found.
87 <   *
88 <   * cutoffMethod : (one of HARD, SWITCHED, SHIFTED_FORCE, SHIFTED_POTENTIAL)
89 <   *      If cutoffMethod was explicitly set, use that choice.
90 <   *      If cutoffMethod was not explicitly set, use SHIFTED_FORCE
91 <   *
92 <   * cutoffPolicy : (one of MIX, MAX, TRADITIONAL)
93 <   *      If cutoffPolicy was explicitly set, use that choice.
94 <   *      If cutoffPolicy was not explicitly set, use TRADITIONAL
95 <   */
96 <  void ForceManager::setupCutoffs() {
97 <    
98 <    Globals* simParams_ = info_->getSimParams();
99 <    ForceFieldOptions& forceFieldOptions_ = forceField_->getForceFieldOptions();
100 <    
101 <    if (simParams_->haveCutoffRadius()) {
102 <      rCut_ = simParams_->getCutoffRadius();
103 <    } else {      
104 <      if (info_->usesElectrostaticAtoms()) {
105 <        sprintf(painCave.errMsg,
106 <                "ForceManager::setupCutoffs: No value was set for the cutoffRadius.\n"
107 <                "\tOpenMD will use a default value of 12.0 angstroms"
108 <                "\tfor the cutoffRadius.\n");
109 <        painCave.isFatal = 0;
110 <        painCave.severity = OPENMD_INFO;
111 <        simError();
112 <        rCut_ = 12.0;
113 <      } else {
114 <        RealType thisCut;
115 <        set<AtomType*>::iterator i;
116 <        set<AtomType*> atomTypes;
117 <        atomTypes = info_->getSimulatedAtomTypes();        
118 <        for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
119 <          thisCut = interactionMan_->getSuggestedCutoffRadius((*i));
120 <          rCut_ = max(thisCut, rCut_);
121 <        }
122 <        sprintf(painCave.errMsg,
123 <                "ForceManager::setupCutoffs: No value was set for the cutoffRadius.\n"
124 <                "\tOpenMD will use %lf angstroms.\n",
125 <                rCut_);
126 <        painCave.isFatal = 0;
127 <        painCave.severity = OPENMD_INFO;
128 <        simError();
129 <      }
130 <    }
72 > //long int elapsedTime = 0;
73  
74 <    fDecomp_->setUserCutoff(rCut_);
74 > ForceManager::ForceManager(SimInfo * info) :
75 >        info_(info) {
76 >        forceField_ = info_->getForceField();
77 >        interactionMan_ = new InteractionManager();
78 >        fDecomp_ = new ForceMatrixDecomposition(info_, interactionMan_);
79 > }
80  
81 <    map<string, CutoffMethod> stringToCutoffMethod;
82 <    stringToCutoffMethod["HARD"] = HARD;
83 <    stringToCutoffMethod["SWITCHED"] = SWITCHED;
84 <    stringToCutoffMethod["SHIFTED_POTENTIAL"] = SHIFTED_POTENTIAL;    
85 <    stringToCutoffMethod["SHIFTED_FORCE"] = SHIFTED_FORCE;
86 <  
87 <    if (simParams_->haveCutoffMethod()) {
88 <      string cutMeth = toUpperCopy(simParams_->getCutoffMethod());
89 <      map<string, CutoffMethod>::iterator i;
90 <      i = stringToCutoffMethod.find(cutMeth);
91 <      if (i == stringToCutoffMethod.end()) {
92 <        sprintf(painCave.errMsg,
93 <                "ForceManager::setupCutoffs: Could not find chosen cutoffMethod %s\n"
94 <                "\tShould be one of: "
95 <                "HARD, SWITCHED, SHIFTED_POTENTIAL, or SHIFTED_FORCE\n",
96 <                cutMeth.c_str());
97 <        painCave.isFatal = 1;
98 <        painCave.severity = OPENMD_ERROR;
99 <        simError();
100 <      } else {
101 <        cutoffMethod_ = i->second;
102 <      }
103 <    } else {
104 <      sprintf(painCave.errMsg,
105 <              "ForceManager::setupCutoffs: No value was set for the cutoffMethod.\n"
106 <              "\tOpenMD will use SHIFTED_FORCE.\n");
107 <      painCave.isFatal = 0;
108 <      painCave.severity = OPENMD_INFO;
109 <      simError();
110 <      cutoffMethod_ = SHIFTED_FORCE;        
111 <    }
81 > /**
82 > * setupCutoffs
83 > *
84 > * Sets the values of cutoffRadius, switchingRadius, cutoffMethod,
85 > * and cutoffPolicy
86 > *
87 > * cutoffRadius : realType
88 > *  If the cutoffRadius was explicitly set, use that value.
89 > *  If the cutoffRadius was not explicitly set:
90 > *      Are there electrostatic atoms?  Use 12.0 Angstroms.
91 > *      No electrostatic atoms?  Poll the atom types present in the
92 > *      simulation for suggested cutoff values (e.g. 2.5 * sigma).
93 > *      Use the maximum suggested value that was found.
94 > *
95 > * cutoffMethod : (one of HARD, SWITCHED, SHIFTED_FORCE,
96 > *                        or SHIFTED_POTENTIAL)
97 > *      If cutoffMethod was explicitly set, use that choice.
98 > *      If cutoffMethod was not explicitly set, use SHIFTED_FORCE
99 > *
100 > * cutoffPolicy : (one of MIX, MAX, TRADITIONAL)
101 > *      If cutoffPolicy was explicitly set, use that choice.
102 > *      If cutoffPolicy was not explicitly set, use TRADITIONAL
103 > *
104 > * switchingRadius : realType
105 > *  If the cutoffMethod was set to SWITCHED:
106 > *      If the switchingRadius was explicitly set, use that value
107 > *          (but do a sanity check first).
108 > *      If the switchingRadius was not explicitly set: use 0.85 *
109 > *      cutoffRadius_
110 > *  If the cutoffMethod was not set to SWITCHED:
111 > *      Set switchingRadius equal to cutoffRadius for safety.
112 > */
113 > void ForceManager::setupCutoffs() {
114  
115 <    map<string, CutoffPolicy> stringToCutoffPolicy;
116 <    stringToCutoffPolicy["MIX"] = MIX;
168 <    stringToCutoffPolicy["MAX"] = MAX;
169 <    stringToCutoffPolicy["TRADITIONAL"] = TRADITIONAL;    
115 >        Globals* simParams_ = info_->getSimParams();
116 >        ForceFieldOptions& forceFieldOptions_ = forceField_->getForceFieldOptions();
117  
118 <    std::string cutPolicy;
119 <    if (forceFieldOptions_.haveCutoffPolicy()){
120 <      cutPolicy = forceFieldOptions_.getCutoffPolicy();
121 <    }else if (simParams_->haveCutoffPolicy()) {
122 <      cutPolicy = simParams_->getCutoffPolicy();
123 <    }
118 >        if (simParams_->haveCutoffRadius())
119 >        {
120 >                rCut_ = simParams_->getCutoffRadius();
121 >        } else
122 >        {
123 >                if (info_->usesElectrostaticAtoms())
124 >                {
125 >                        sprintf(painCave.errMsg, "ForceManager::setupCutoffs: No value was set for the cutoffRadius.\n"
126 >                                "\tOpenMD will use a default value of 12.0 angstroms"
127 >                                "\tfor the cutoffRadius.\n");
128 >                        painCave.isFatal = 0;
129 >                        painCave.severity = OPENMD_INFO;
130 >                        simError();
131 >                        rCut_ = 12.0;
132 >                } else
133 >                {
134 >                        RealType thisCut;
135 >                        set<AtomType*>::iterator i;
136 >                        set<AtomType*> atomTypes;
137 >                        atomTypes = info_->getSimulatedAtomTypes();
138 >                        for (i = atomTypes.begin(); i != atomTypes.end(); ++i)
139 >                        {
140 >                                thisCut = interactionMan_->getSuggestedCutoffRadius((*i));
141 >                                rCut_ = max(thisCut, rCut_);
142 >                        }
143 >                        sprintf(painCave.errMsg, "ForceManager::setupCutoffs: No value was set for the cutoffRadius.\n"
144 >                                "\tOpenMD will use %lf angstroms.\n", rCut_);
145 >                        painCave.isFatal = 0;
146 >                        painCave.severity = OPENMD_INFO;
147 >                        simError();
148 >                }
149 >        }
150  
151 <    if (!cutPolicy.empty()){
152 <      toUpper(cutPolicy);
180 <      map<string, CutoffPolicy>::iterator i;
181 <      i = stringToCutoffPolicy.find(cutPolicy);
151 >        fDecomp_->setUserCutoff(rCut_);
152 >        interactionMan_->setCutoffRadius(rCut_);
153  
154 <      if (i == stringToCutoffPolicy.end()) {
155 <        sprintf(painCave.errMsg,
156 <                "ForceManager::setupCutoffs: Could not find chosen cutoffPolicy %s\n"
157 <                "\tShould be one of: "
158 <                "MIX, MAX, or TRADITIONAL\n",
188 <                cutPolicy.c_str());
189 <        painCave.isFatal = 1;
190 <        painCave.severity = OPENMD_ERROR;
191 <        simError();
192 <      } else {
193 <        cutoffPolicy_ = i->second;
194 <      }
195 <    } else {
196 <      sprintf(painCave.errMsg,
197 <              "ForceManager::setupCutoffs: No value was set for the cutoffPolicy.\n"
198 <              "\tOpenMD will use TRADITIONAL.\n");
199 <      painCave.isFatal = 0;
200 <      painCave.severity = OPENMD_INFO;
201 <      simError();
202 <      cutoffPolicy_ = TRADITIONAL;        
203 <    }
204 <    fDecomp_->setCutoffPolicy(cutoffPolicy_);
205 <  }
154 >        map<string, CutoffMethod> stringToCutoffMethod;
155 >        stringToCutoffMethod["HARD"] = HARD;
156 >        stringToCutoffMethod["SWITCHED"] = SWITCHED;
157 >        stringToCutoffMethod["SHIFTED_POTENTIAL"] = SHIFTED_POTENTIAL;
158 >        stringToCutoffMethod["SHIFTED_FORCE"] = SHIFTED_FORCE;
159  
160 <  /**
161 <   * setupSwitching
162 <   *
163 <   * Sets the values of switchingRadius and
164 <   *  If the switchingRadius was explicitly set, use that value (but check it)
165 <   *  If the switchingRadius was not explicitly set: use 0.85 * cutoffRadius_
166 <   */
167 <  void ForceManager::setupSwitching() {
168 <    Globals* simParams_ = info_->getSimParams();
160 >        if (simParams_->haveCutoffMethod())
161 >        {
162 >                string cutMeth = toUpperCopy(simParams_->getCutoffMethod());
163 >                map<string, CutoffMethod>::iterator i;
164 >                i = stringToCutoffMethod.find(cutMeth);
165 >                if (i == stringToCutoffMethod.end())
166 >                {
167 >                        sprintf(painCave.errMsg, "ForceManager::setupCutoffs: Could not find chosen cutoffMethod %s\n"
168 >                                "\tShould be one of: "
169 >                                "HARD, SWITCHED, SHIFTED_POTENTIAL, or SHIFTED_FORCE\n", cutMeth.c_str());
170 >                        painCave.isFatal = 1;
171 >                        painCave.severity = OPENMD_ERROR;
172 >                        simError();
173 >                } else
174 >                {
175 >                        cutoffMethod_ = i->second;
176 >                }
177 >        } else
178 >        {
179 >                sprintf(painCave.errMsg, "ForceManager::setupCutoffs: No value was set for the cutoffMethod.\n"
180 >                        "\tOpenMD will use SHIFTED_FORCE.\n");
181 >                painCave.isFatal = 0;
182 >                painCave.severity = OPENMD_INFO;
183 >                simError();
184 >                cutoffMethod_ = SHIFTED_FORCE;
185 >        }
186  
187 <    // create the switching function object:
188 <    switcher_ = new SwitchingFunction();
189 <    
190 <    if (simParams_->haveSwitchingRadius()) {
221 <      rSwitch_ = simParams_->getSwitchingRadius();
222 <      if (rSwitch_ > rCut_) {        
223 <        sprintf(painCave.errMsg,
224 <                "ForceManager::setupSwitching: switchingRadius (%f) is larger "
225 <                "than the cutoffRadius(%f)\n", rSwitch_, rCut_);
226 <        painCave.isFatal = 1;
227 <        painCave.severity = OPENMD_ERROR;
228 <        simError();
229 <      }
230 <    } else {      
231 <      rSwitch_ = 0.85 * rCut_;
232 <      sprintf(painCave.errMsg,
233 <              "ForceManager::setupSwitching: No value was set for the switchingRadius.\n"
234 <              "\tOpenMD will use a default value of 85 percent of the cutoffRadius.\n"
235 <              "\tswitchingRadius = %f. for this simulation\n", rSwitch_);
236 <      painCave.isFatal = 0;
237 <      painCave.severity = OPENMD_WARNING;
238 <      simError();
239 <    }          
240 <    
241 <    // Default to cubic switching function.
242 <    sft_ = cubic;
243 <    if (simParams_->haveSwitchingFunctionType()) {
244 <      string funcType = simParams_->getSwitchingFunctionType();
245 <      toUpper(funcType);
246 <      if (funcType == "CUBIC") {
247 <        sft_ = cubic;
248 <      } else {
249 <        if (funcType == "FIFTH_ORDER_POLYNOMIAL") {
250 <          sft_ = fifth_order_poly;
251 <        } else {
252 <          // throw error        
253 <          sprintf( painCave.errMsg,
254 <                   "ForceManager::setupSwitching : Unknown switchingFunctionType. (Input file specified %s .)\n"
255 <                   "\tswitchingFunctionType must be one of: "
256 <                   "\"cubic\" or \"fifth_order_polynomial\".",
257 <                   funcType.c_str() );
258 <          painCave.isFatal = 1;
259 <          painCave.severity = OPENMD_ERROR;
260 <          simError();
261 <        }          
262 <      }
263 <    }
264 <    switcher_->setSwitchType(sft_);
265 <    switcher_->setSwitch(rSwitch_, rCut_);
266 <  }
267 <  
268 <  void ForceManager::initialize() {
187 >        map<string, CutoffPolicy> stringToCutoffPolicy;
188 >        stringToCutoffPolicy["MIX"] = MIX;
189 >        stringToCutoffPolicy["MAX"] = MAX;
190 >        stringToCutoffPolicy["TRADITIONAL"] = TRADITIONAL;
191  
192 <    if (!info_->isTopologyDone()) {
193 <      info_->update();
194 <      interactionMan_->setSimInfo(info_);
195 <      interactionMan_->initialize();
192 >        std::string cutPolicy;
193 >        if (forceFieldOptions_.haveCutoffPolicy())
194 >        {
195 >                cutPolicy = forceFieldOptions_.getCutoffPolicy();
196 >        } else if (simParams_->haveCutoffPolicy())
197 >        {
198 >                cutPolicy = simParams_->getCutoffPolicy();
199 >        }
200  
201 <      // We want to delay the cutoffs until after the interaction
202 <      // manager has set up the atom-atom interactions so that we can
203 <      // query them for suggested cutoff values
201 >        if (!cutPolicy.empty())
202 >        {
203 >                toUpper(cutPolicy);
204 >                map<string, CutoffPolicy>::iterator i;
205 >                i = stringToCutoffPolicy.find(cutPolicy);
206  
207 <      setupCutoffs();
208 <      setupSwitching();
207 >                if (i == stringToCutoffPolicy.end())
208 >                {
209 >                        sprintf(painCave.errMsg, "ForceManager::setupCutoffs: Could not find chosen cutoffPolicy %s\n"
210 >                                "\tShould be one of: "
211 >                                "MIX, MAX, or TRADITIONAL\n", cutPolicy.c_str());
212 >                        painCave.isFatal = 1;
213 >                        painCave.severity = OPENMD_ERROR;
214 >                        simError();
215 >                } else
216 >                {
217 >                        cutoffPolicy_ = i->second;
218 >                }
219 >        } else
220 >        {
221 >                sprintf(painCave.errMsg, "ForceManager::setupCutoffs: No value was set for the cutoffPolicy.\n"
222 >                        "\tOpenMD will use TRADITIONAL.\n");
223 >                painCave.isFatal = 0;
224 >                painCave.severity = OPENMD_INFO;
225 >                simError();
226 >                cutoffPolicy_ = TRADITIONAL;
227 >        }
228  
229 <      info_->prepareTopology();      
283 <    }
229 >        fDecomp_->setCutoffPolicy(cutoffPolicy_);
230  
231 <    ForceFieldOptions& fopts = forceField_->getForceFieldOptions();
286 <    
287 <    // Force fields can set options on how to scale van der Waals and electrostatic
288 <    // interactions for atoms connected via bonds, bends and torsions
289 <    // in this case the topological distance between atoms is:
290 <    // 0 = topologically unconnected
291 <    // 1 = bonded together
292 <    // 2 = connected via a bend
293 <    // 3 = connected via a torsion
294 <    
295 <    vdwScale_.reserve(4);
296 <    fill(vdwScale_.begin(), vdwScale_.end(), 0.0);
231 >        // create the switching function object:
232  
233 <    electrostaticScale_.reserve(4);
299 <    fill(electrostaticScale_.begin(), electrostaticScale_.end(), 0.0);
233 >        switcher_ = new SwitchingFunction();
234  
235 <    vdwScale_[0] = 1.0;
236 <    vdwScale_[1] = fopts.getvdw12scale();
237 <    vdwScale_[2] = fopts.getvdw13scale();
238 <    vdwScale_[3] = fopts.getvdw14scale();
239 <    
240 <    electrostaticScale_[0] = 1.0;
241 <    electrostaticScale_[1] = fopts.getelectrostatic12scale();
242 <    electrostaticScale_[2] = fopts.getelectrostatic13scale();
243 <    electrostaticScale_[3] = fopts.getelectrostatic14scale();    
244 <    
245 <    fDecomp_->distributeInitialData();
246 <
247 <    initialized_ = true;
235 >        if (cutoffMethod_ == SWITCHED)
236 >        {
237 >                if (simParams_->haveSwitchingRadius())
238 >                {
239 >                        rSwitch_ = simParams_->getSwitchingRadius();
240 >                        if (rSwitch_ > rCut_)
241 >                        {
242 >                                sprintf(painCave.errMsg, "ForceManager::setupCutoffs: switchingRadius (%f) is larger "
243 >                                        "than the cutoffRadius(%f)\n", rSwitch_, rCut_);
244 >                                painCave.isFatal = 1;
245 >                                painCave.severity = OPENMD_ERROR;
246 >                                simError();
247 >                        }
248 >                } else
249 >                {
250 >                        rSwitch_ = 0.85 * rCut_;
251 >                        sprintf(painCave.errMsg, "ForceManager::setupCutoffs: No value was set for the switchingRadius.\n"
252 >                                "\tOpenMD will use a default value of 85 percent of the cutoffRadius.\n"
253 >                                "\tswitchingRadius = %f. for this simulation\n", rSwitch_);
254 >                        painCave.isFatal = 0;
255 >                        painCave.severity = OPENMD_WARNING;
256 >                        simError();
257 >                }
258 >        } else
259 >        {
260 >                if (simParams_->haveSwitchingRadius())
261 >                {
262 >                        map<string, CutoffMethod>::const_iterator it;
263 >                        string theMeth;
264 >                        for (it = stringToCutoffMethod.begin(); it != stringToCutoffMethod.end(); ++it)
265 >                        {
266 >                                if (it->second == cutoffMethod_)
267 >                                {
268 >                                        theMeth = it->first;
269 >                                        break;
270 >                                }
271 >                        }
272 >                        sprintf(painCave.errMsg, "ForceManager::setupCutoffs: the cutoffMethod (%s)\n"
273 >                                "\tis not set to SWITCHED, so switchingRadius value\n"
274 >                                "\twill be ignored for this simulation\n", theMeth.c_str());
275 >                        painCave.isFatal = 0;
276 >                        painCave.severity = OPENMD_WARNING;
277 >                        simError();
278 >                }
279  
280 <  }
280 >                rSwitch_ = rCut_;
281 >        }
282  
283 <  void ForceManager::calcForces() {
284 <    
285 <    if (!initialized_) initialize();
283 >        // Default to cubic switching function.
284 >        sft_ = cubic;
285 >        if (simParams_->haveSwitchingFunctionType())
286 >        {
287 >                string funcType = simParams_->getSwitchingFunctionType();
288 >                toUpper(funcType);
289 >                if (funcType == "CUBIC")
290 >                {
291 >                        sft_ = cubic;
292 >                } else
293 >                {
294 >                        if (funcType == "FIFTH_ORDER_POLYNOMIAL")
295 >                        {
296 >                                sft_ = fifth_order_poly;
297 >                        } else
298 >                        {
299 >                                // throw error
300 >                                sprintf(painCave.errMsg,
301 >                                                "ForceManager::setupSwitching : Unknown switchingFunctionType. (Input file specified %s .)\n"
302 >                                                        "\tswitchingFunctionType must be one of: "
303 >                                                        "\"cubic\" or \"fifth_order_polynomial\".", funcType.c_str());
304 >                                painCave.isFatal = 1;
305 >                                painCave.severity = OPENMD_ERROR;
306 >                                simError();
307 >                        }
308 >                }
309 >        }
310 >        switcher_->setSwitchType(sft_);
311 >        switcher_->setSwitch(rSwitch_, rCut_);
312 >        interactionMan_->setSwitchingRadius(rSwitch_);
313 > }
314  
315 <    preCalculation();  
322 <    shortRangeInteractions();
323 <    longRangeInteractions();
324 <    postCalculation();    
325 <  }
326 <  
327 <  void ForceManager::preCalculation() {
328 <    SimInfo::MoleculeIterator mi;
329 <    Molecule* mol;
330 <    Molecule::AtomIterator ai;
331 <    Atom* atom;
332 <    Molecule::RigidBodyIterator rbIter;
333 <    RigidBody* rb;
334 <    Molecule::CutoffGroupIterator ci;
335 <    CutoffGroup* cg;
336 <    
337 <    // forces are zeroed here, before any are accumulated.
338 <    
339 <    for (mol = info_->beginMolecule(mi); mol != NULL;
340 <         mol = info_->nextMolecule(mi)) {
341 <      for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
342 <        atom->zeroForcesAndTorques();
343 <      }
344 <          
345 <      //change the positions of atoms which belong to the rigidbodies
346 <      for (rb = mol->beginRigidBody(rbIter); rb != NULL;
347 <           rb = mol->nextRigidBody(rbIter)) {
348 <        rb->zeroForcesAndTorques();
349 <      }        
315 > void ForceManager::initialize() {
316  
317 <      if(info_->getNGlobalCutoffGroups() != info_->getNGlobalAtoms()){
318 <        for(cg = mol->beginCutoffGroup(ci); cg != NULL;
353 <            cg = mol->nextCutoffGroup(ci)) {
354 <          //calculate the center of mass of cutoff group
355 <          cg->updateCOM();
356 <        }
357 <      }      
358 <    }
359 <  
360 <    // Zero out the stress tensor
361 <    tau *= 0.0;
362 <    
363 <  }
364 <  
365 <  void ForceManager::shortRangeInteractions() {
366 <    Molecule* mol;
367 <    RigidBody* rb;
368 <    Bond* bond;
369 <    Bend* bend;
370 <    Torsion* torsion;
371 <    Inversion* inversion;
372 <    SimInfo::MoleculeIterator mi;
373 <    Molecule::RigidBodyIterator rbIter;
374 <    Molecule::BondIterator bondIter;;
375 <    Molecule::BendIterator  bendIter;
376 <    Molecule::TorsionIterator  torsionIter;
377 <    Molecule::InversionIterator  inversionIter;
378 <    RealType bondPotential = 0.0;
379 <    RealType bendPotential = 0.0;
380 <    RealType torsionPotential = 0.0;
381 <    RealType inversionPotential = 0.0;
317 >        if (!info_->isTopologyDone())
318 >        {
319  
320 <    //calculate short range interactions    
321 <    for (mol = info_->beginMolecule(mi); mol != NULL;
322 <         mol = info_->nextMolecule(mi)) {
320 >                info_->update();
321 >                interactionMan_->setSimInfo(info_);
322 >                interactionMan_->initialize();
323  
324 <      //change the positions of atoms which belong to the rigidbodies
325 <      for (rb = mol->beginRigidBody(rbIter); rb != NULL;
326 <           rb = mol->nextRigidBody(rbIter)) {
327 <        rb->updateAtoms();
391 <      }
324 >                // We want to delay the cutoffs until after the interaction
325 >                // manager has set up the atom-atom interactions so that we can
326 >                // query them for suggested cutoff values
327 >                setupCutoffs();
328  
329 <      for (bond = mol->beginBond(bondIter); bond != NULL;
330 <           bond = mol->nextBond(bondIter)) {
395 <        bond->calcForce();
396 <        bondPotential += bond->getPotential();
397 <      }
329 >                info_->prepareTopology();
330 >        }
331  
332 <      for (bend = mol->beginBend(bendIter); bend != NULL;
400 <           bend = mol->nextBend(bendIter)) {
401 <        
402 <        RealType angle;
403 <        bend->calcForce(angle);
404 <        RealType currBendPot = bend->getPotential();          
405 <        
406 <        bendPotential += bend->getPotential();
407 <        map<Bend*, BendDataSet>::iterator i = bendDataSets.find(bend);
408 <        if (i == bendDataSets.end()) {
409 <          BendDataSet dataSet;
410 <          dataSet.prev.angle = dataSet.curr.angle = angle;
411 <          dataSet.prev.potential = dataSet.curr.potential = currBendPot;
412 <          dataSet.deltaV = 0.0;
413 <          bendDataSets.insert(map<Bend*, BendDataSet>::value_type(bend, dataSet));
414 <        }else {
415 <          i->second.prev.angle = i->second.curr.angle;
416 <          i->second.prev.potential = i->second.curr.potential;
417 <          i->second.curr.angle = angle;
418 <          i->second.curr.potential = currBendPot;
419 <          i->second.deltaV =  fabs(i->second.curr.potential -  
420 <                                   i->second.prev.potential);
421 <        }
422 <      }
423 <      
424 <      for (torsion = mol->beginTorsion(torsionIter); torsion != NULL;
425 <           torsion = mol->nextTorsion(torsionIter)) {
426 <        RealType angle;
427 <        torsion->calcForce(angle);
428 <        RealType currTorsionPot = torsion->getPotential();
429 <        torsionPotential += torsion->getPotential();
430 <        map<Torsion*, TorsionDataSet>::iterator i = torsionDataSets.find(torsion);
431 <        if (i == torsionDataSets.end()) {
432 <          TorsionDataSet dataSet;
433 <          dataSet.prev.angle = dataSet.curr.angle = angle;
434 <          dataSet.prev.potential = dataSet.curr.potential = currTorsionPot;
435 <          dataSet.deltaV = 0.0;
436 <          torsionDataSets.insert(map<Torsion*, TorsionDataSet>::value_type(torsion, dataSet));
437 <        }else {
438 <          i->second.prev.angle = i->second.curr.angle;
439 <          i->second.prev.potential = i->second.curr.potential;
440 <          i->second.curr.angle = angle;
441 <          i->second.curr.potential = currTorsionPot;
442 <          i->second.deltaV =  fabs(i->second.curr.potential -  
443 <                                   i->second.prev.potential);
444 <        }      
445 <      }      
446 <      
447 <      for (inversion = mol->beginInversion(inversionIter);
448 <           inversion != NULL;
449 <           inversion = mol->nextInversion(inversionIter)) {
450 <        RealType angle;
451 <        inversion->calcForce(angle);
452 <        RealType currInversionPot = inversion->getPotential();
453 <        inversionPotential += inversion->getPotential();
454 <        map<Inversion*, InversionDataSet>::iterator i = inversionDataSets.find(inversion);
455 <        if (i == inversionDataSets.end()) {
456 <          InversionDataSet dataSet;
457 <          dataSet.prev.angle = dataSet.curr.angle = angle;
458 <          dataSet.prev.potential = dataSet.curr.potential = currInversionPot;
459 <          dataSet.deltaV = 0.0;
460 <          inversionDataSets.insert(map<Inversion*, InversionDataSet>::value_type(inversion, dataSet));
461 <        }else {
462 <          i->second.prev.angle = i->second.curr.angle;
463 <          i->second.prev.potential = i->second.curr.potential;
464 <          i->second.curr.angle = angle;
465 <          i->second.curr.potential = currInversionPot;
466 <          i->second.deltaV =  fabs(i->second.curr.potential -  
467 <                                   i->second.prev.potential);
468 <        }      
469 <      }      
470 <    }
471 <    
472 <    RealType  shortRangePotential = bondPotential + bendPotential +
473 <      torsionPotential +  inversionPotential;    
474 <    Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
475 <    curSnapshot->statData[Stats::SHORT_RANGE_POTENTIAL] = shortRangePotential;
476 <    curSnapshot->statData[Stats::BOND_POTENTIAL] = bondPotential;
477 <    curSnapshot->statData[Stats::BEND_POTENTIAL] = bendPotential;
478 <    curSnapshot->statData[Stats::DIHEDRAL_POTENTIAL] = torsionPotential;
479 <    curSnapshot->statData[Stats::INVERSION_POTENTIAL] = inversionPotential;    
480 <  }
481 <  
482 <  void ForceManager::longRangeInteractions() {
332 >        ForceFieldOptions& fopts = forceField_->getForceFieldOptions();
333  
334 <    Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
335 <    DataStorage* config = &(curSnapshot->atomData);
336 <    DataStorage* cgConfig = &(curSnapshot->cgData);
334 >        // Force fields can set options on how to scale van der Waals and
335 >        // electrostatic interactions for atoms connected via bonds, bends
336 >        // and torsions in this case the topological distance between
337 >        // atoms is:
338 >        // 0 = topologically unconnected
339 >        // 1 = bonded together
340 >        // 2 = connected via a bend
341 >        // 3 = connected via a torsion
342  
343 <    //calculate the center of mass of cutoff group
343 >        vdwScale_.reserve(4);
344 >        fill(vdwScale_.begin(), vdwScale_.end(), 0.0);
345  
346 <    SimInfo::MoleculeIterator mi;
347 <    Molecule* mol;
492 <    Molecule::CutoffGroupIterator ci;
493 <    CutoffGroup* cg;
346 >        electrostaticScale_.reserve(4);
347 >        fill(electrostaticScale_.begin(), electrostaticScale_.end(), 0.0);
348  
349 <    if(info_->getNCutoffGroups() > 0){      
350 <      for (mol = info_->beginMolecule(mi); mol != NULL;
351 <           mol = info_->nextMolecule(mi)) {
352 <        for(cg = mol->beginCutoffGroup(ci); cg != NULL;
499 <            cg = mol->nextCutoffGroup(ci)) {
500 <          cg->updateCOM();
501 <        }
502 <      }      
503 <    } else {
504 <      // center of mass of the group is the same as position of the atom  
505 <      // if cutoff group does not exist
506 <      cgConfig->position = config->position;
507 <    }
349 >        vdwScale_[0] = 1.0;
350 >        vdwScale_[1] = fopts.getvdw12scale();
351 >        vdwScale_[2] = fopts.getvdw13scale();
352 >        vdwScale_[3] = fopts.getvdw14scale();
353  
354 <    fDecomp_->zeroWorkArrays();
355 <    fDecomp_->distributeData();
356 <    
357 <    int cg1, cg2, atom1, atom2, topoDist;
513 <    Vector3d d_grp, dag, d;
514 <    RealType rgrpsq, rgrp, r2, r;
515 <    RealType electroMult, vdwMult;
516 <    RealType vij;
517 <    Vector3d fij, fg, f1;
518 <    tuple3<RealType, RealType, RealType> cuts;
519 <    RealType rCutSq;
520 <    bool in_switching_region;
521 <    RealType sw, dswdr, swderiv;
522 <    vector<int> atomListColumn, atomListRow, atomListLocal;
523 <    InteractionData idat;
524 <    SelfData sdat;
525 <    RealType mf;
526 <    RealType lrPot;
527 <    RealType vpair;
528 <    potVec longRangePotential(0.0);
529 <    potVec workPot(0.0);
354 >        electrostaticScale_[0] = 1.0;
355 >        electrostaticScale_[1] = fopts.getelectrostatic12scale();
356 >        electrostaticScale_[2] = fopts.getelectrostatic13scale();
357 >        electrostaticScale_[3] = fopts.getelectrostatic14scale();
358  
359 <    int loopStart, loopEnd;
359 >        fDecomp_->distributeInitialData();
360  
361 <    idat.vdwMult = &vdwMult;
534 <    idat.electroMult = &electroMult;
535 <    idat.pot = &workPot;
536 <    sdat.pot = fDecomp_->getEmbeddingPotential();
537 <    idat.vpair = &vpair;
538 <    idat.f1 = &f1;
539 <    idat.sw = &sw;
540 <    idat.shiftedPot = (cutoffMethod_ == SHIFTED_POTENTIAL) ? true : false;
541 <    idat.shiftedForce = (cutoffMethod_ == SHIFTED_FORCE) ? true : false;
542 <    
543 <    loopEnd = PAIR_LOOP;
544 <    if (info_->requiresPrepair() ) {
545 <      loopStart = PREPAIR_LOOP;
546 <    } else {
547 <      loopStart = PAIR_LOOP;
548 <    }
549 <  
550 <    for (int iLoop = loopStart; iLoop <= loopEnd; iLoop++) {
551 <    
552 <      if (iLoop == loopStart) {
553 <        bool update_nlist = fDecomp_->checkNeighborList();
554 <        if (update_nlist)
555 <          neighborList = fDecomp_->buildNeighborList();
556 <      }      
557 <        
558 <      for (vector<pair<int, int> >::iterator it = neighborList.begin();
559 <             it != neighborList.end(); ++it) {
560 <                
561 <        cg1 = (*it).first;
562 <        cg2 = (*it).second;
563 <        
564 <        cuts = fDecomp_->getGroupCutoffs(cg1, cg2);
361 >        initialized_ = true;
362  
363 <        d_grp  = fDecomp_->getIntergroupVector(cg1, cg2);
567 <        curSnapshot->wrapVector(d_grp);        
568 <        rgrpsq = d_grp.lengthSquare();
363 > }
364  
365 <        rCutSq = cuts.second;
365 > void ForceManager::calcForces() {
366  
367 <        if (rgrpsq < rCutSq) {
368 <          idat.rcut = &cuts.first;
574 <          if (iLoop == PAIR_LOOP) {
575 <            vij *= 0.0;
576 <            fij = V3Zero;
577 <          }
578 <          
579 <          in_switching_region = switcher_->getSwitch(rgrpsq, sw, dswdr,
580 <                                                     rgrp);
581 <              
582 <          atomListRow = fDecomp_->getAtomsInGroupRow(cg1);
583 <          atomListColumn = fDecomp_->getAtomsInGroupColumn(cg2);
367 >        if (!initialized_)
368 >                initialize();
369  
370 <          for (vector<int>::iterator ia = atomListRow.begin();
371 <               ia != atomListRow.end(); ++ia) {            
372 <            atom1 = (*ia);
373 <            
374 <            for (vector<int>::iterator jb = atomListColumn.begin();
375 <                 jb != atomListColumn.end(); ++jb) {              
376 <              atom2 = (*jb);
592 <            
593 <              if (!fDecomp_->skipAtomPair(atom1, atom2)) {
594 <                vpair = 0.0;
595 <                workPot = 0.0;
596 <                f1 = V3Zero;
370 >        preCalculation();
371 >        shortRangeInteractions();
372 >        //    longRangeInteractions();
373 >        //      longRangeInteractionsRapaport();
374 >        longRangeInteractionsParallel();
375 >        postCalculation();
376 > }
377  
378 <                fDecomp_->fillInteractionData(idat, atom1, atom2);
379 <                
380 <                topoDist = fDecomp_->getTopologicalDistance(atom1, atom2);
381 <                vdwMult = vdwScale_[topoDist];
382 <                electroMult = electrostaticScale_[topoDist];
378 > void ForceManager::preCalculation() {
379 >        SimInfo::MoleculeIterator mi;
380 >        Molecule* mol;
381 >        Molecule::AtomIterator ai;
382 >        Atom* atom;
383 >        Molecule::RigidBodyIterator rbIter;
384 >        RigidBody* rb;
385 >        Molecule::CutoffGroupIterator ci;
386 >        CutoffGroup* cg;
387  
388 <                if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
605 <                  idat.d = &d_grp;
606 <                  idat.r2 = &rgrpsq;
607 <                } else {
608 <                  d = fDecomp_->getInteratomicVector(atom1, atom2);
609 <                  curSnapshot->wrapVector( d );
610 <                  r2 = d.lengthSquare();
611 <                  idat.d = &d;
612 <                  idat.r2 = &r2;
613 <                }
614 <                
615 <                r = sqrt( *(idat.r2) );
616 <                idat.rij = &r;
617 <              
618 <                if (iLoop == PREPAIR_LOOP) {
619 <                  interactionMan_->doPrePair(idat);
620 <                } else {
621 <                  interactionMan_->doPair(idat);
622 <                  fDecomp_->unpackInteractionData(idat, atom1, atom2);
623 <                  vij += vpair;
624 <                  fij += f1;
625 <                  tau -= outProduct( *(idat.d), f1);
626 <                }
627 <              }
628 <            }
629 <          }
388 >        // forces are zeroed here, before any are accumulated.
389  
390 <          if (iLoop == PAIR_LOOP) {
391 <            if (in_switching_region) {
392 <              swderiv = vij * dswdr / rgrp;
393 <              fg = swderiv * d_grp;
390 >        for (mol = info_->beginMolecule(mi); mol != NULL; mol = info_->nextMolecule(mi))
391 >        {
392 >                for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai))
393 >                {
394 >                        atom->zeroForcesAndTorques();
395 >                }
396  
397 <              fij += fg;
397 >                //change the positions of atoms which belong to the rigidbodies
398 >                for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter))
399 >                {
400 >                        rb->zeroForcesAndTorques();
401 >                }
402  
403 <              if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
404 <                tau -= outProduct( *(idat.d), fg);
405 <              }
406 <          
407 <              for (vector<int>::iterator ia = atomListRow.begin();
408 <                   ia != atomListRow.end(); ++ia) {            
409 <                atom1 = (*ia);                
410 <                mf = fDecomp_->getMassFactorRow(atom1);
411 <                // fg is the force on atom ia due to cutoff group's
647 <                // presence in switching region
648 <                fg = swderiv * d_grp * mf;
649 <                fDecomp_->addForceToAtomRow(atom1, fg);
403 >                if (info_->getNGlobalCutoffGroups() != info_->getNGlobalAtoms())
404 >                {
405 >                        for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci))
406 >                        {
407 >                                //calculate the center of mass of cutoff group
408 >                                cg->updateCOM();
409 >                        }
410 >                }
411 >        }
412  
413 <                if (atomListRow.size() > 1) {
414 <                  if (info_->usesAtomicVirial()) {
653 <                    // find the distance between the atom
654 <                    // and the center of the cutoff group:
655 <                    dag = fDecomp_->getAtomToGroupVectorRow(atom1, cg1);
656 <                    tau -= outProduct(dag, fg);
657 <                  }
658 <                }
659 <              }
660 <              for (vector<int>::iterator jb = atomListColumn.begin();
661 <                   jb != atomListColumn.end(); ++jb) {              
662 <                atom2 = (*jb);
663 <                mf = fDecomp_->getMassFactorColumn(atom2);
664 <                // fg is the force on atom jb due to cutoff group's
665 <                // presence in switching region
666 <                fg = -swderiv * d_grp * mf;
667 <                fDecomp_->addForceToAtomColumn(atom2, fg);
413 >        // Zero out the stress tensor
414 >        tau *= 0.0;
415  
416 <                if (atomListColumn.size() > 1) {
670 <                  if (info_->usesAtomicVirial()) {
671 <                    // find the distance between the atom
672 <                    // and the center of the cutoff group:
673 <                    dag = fDecomp_->getAtomToGroupVectorColumn(atom2, cg2);
674 <                    tau -= outProduct(dag, fg);
675 <                  }
676 <                }
677 <              }
678 <            }
679 <            //if (!SIM_uses_AtomicVirial) {
680 <            //  tau -= outProduct(d_grp, fij);
681 <            //}
682 <          }
683 <        }
684 <      }
416 > }
417  
418 <      if (iLoop == PREPAIR_LOOP) {
419 <        if (info_->requiresPrepair()) {            
420 <          fDecomp_->collectIntermediateData();
418 > void ForceManager::shortRangeInteractions() {
419 >        Molecule* mol;
420 >        RigidBody* rb;
421 >        Bond* bond;
422 >        Bend* bend;
423 >        Torsion* torsion;
424 >        Inversion* inversion;
425 >        SimInfo::MoleculeIterator mi;
426 >        Molecule::RigidBodyIterator rbIter;
427 >        Molecule::BondIterator bondIter;
428 >        ;
429 >        Molecule::BendIterator bendIter;
430 >        Molecule::TorsionIterator torsionIter;
431 >        Molecule::InversionIterator inversionIter;
432 >        RealType bondPotential = 0.0;
433 >        RealType bendPotential = 0.0;
434 >        RealType torsionPotential = 0.0;
435 >        RealType inversionPotential = 0.0;
436  
437 <          for (int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) {
438 <            fDecomp_->fillSelfData(sdat, atom1);
439 <            interactionMan_->doPreForce(sdat);
693 <          }
694 <          
695 <          
696 <          fDecomp_->distributeIntermediateData();        
697 <        }
698 <      }
437 >        //calculate short range interactions
438 >        for (mol = info_->beginMolecule(mi); mol != NULL; mol = info_->nextMolecule(mi))
439 >        {
440  
441 <    }
442 <    
443 <    fDecomp_->collectData();
444 <    
445 <    if ( info_->requiresSkipCorrection() ) {
705 <      
706 <      for (int atom1 = 0; atom1 < fDecomp_->getNAtomsInRow(); atom1++) {
441 >                //change the positions of atoms which belong to the rigidbodies
442 >                for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter))
443 >                {
444 >                        rb->updateAtoms();
445 >                }
446  
447 <        vector<int> skipList = fDecomp_->getSkipsForAtom( atom1 );
448 <        
449 <        for (vector<int>::iterator jb = skipList.begin();
450 <             jb != skipList.end(); ++jb) {        
451 <    
713 <          atom2 = (*jb);
714 <          fDecomp_->fillSkipData(idat, atom1, atom2);
715 <          interactionMan_->doSkipCorrection(idat);
716 <          fDecomp_->unpackSkipData(idat, atom1, atom2);
447 >                for (bond = mol->beginBond(bondIter); bond != NULL; bond = mol->nextBond(bondIter))
448 >                {
449 >                        bond->calcForce();
450 >                        bondPotential += bond->getPotential();
451 >                }
452  
453 <        }
454 <      }
720 <    }
721 <    
722 <    if (info_->requiresSelfCorrection()) {
453 >                for (bend = mol->beginBend(bendIter); bend != NULL; bend = mol->nextBend(bendIter))
454 >                {
455  
456 <      for (int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) {          
457 <        fDecomp_->fillSelfData(sdat, atom1);
458 <        interactionMan_->doSelfCorrection(sdat);
727 <      }
456 >                        RealType angle;
457 >                        bend->calcForce(angle);
458 >                        RealType currBendPot = bend->getPotential();
459  
460 <    }
460 >                        bendPotential += bend->getPotential();
461 >                        map<Bend*, BendDataSet>::iterator i = bendDataSets.find(bend);
462 >                        if (i == bendDataSets.end())
463 >                        {
464 >                                BendDataSet dataSet;
465 >                                dataSet.prev.angle = dataSet.curr.angle = angle;
466 >                                dataSet.prev.potential = dataSet.curr.potential = currBendPot;
467 >                                dataSet.deltaV = 0.0;
468 >                                bendDataSets.insert(map<Bend*, BendDataSet>::value_type(bend, dataSet));
469 >                        } else
470 >                        {
471 >                                i->second.prev.angle = i->second.curr.angle;
472 >                                i->second.prev.potential = i->second.curr.potential;
473 >                                i->second.curr.angle = angle;
474 >                                i->second.curr.potential = currBendPot;
475 >                                i->second.deltaV = fabs(i->second.curr.potential - i->second.prev.potential);
476 >                        }
477 >                }
478  
479 <    longRangePotential = *(fDecomp_->getEmbeddingPotential()) +
480 <      *(fDecomp_->getPairwisePotential());
479 >                for (torsion = mol->beginTorsion(torsionIter); torsion != NULL; torsion = mol->nextTorsion(torsionIter))
480 >                {
481 >                        RealType angle;
482 >                        torsion->calcForce(angle);
483 >                        RealType currTorsionPot = torsion->getPotential();
484 >                        torsionPotential += torsion->getPotential();
485 >                        map<Torsion*, TorsionDataSet>::iterator i = torsionDataSets.find(torsion);
486 >                        if (i == torsionDataSets.end())
487 >                        {
488 >                                TorsionDataSet dataSet;
489 >                                dataSet.prev.angle = dataSet.curr.angle = angle;
490 >                                dataSet.prev.potential = dataSet.curr.potential = currTorsionPot;
491 >                                dataSet.deltaV = 0.0;
492 >                                torsionDataSets.insert(map<Torsion*, TorsionDataSet>::value_type(torsion, dataSet));
493 >                        } else
494 >                        {
495 >                                i->second.prev.angle = i->second.curr.angle;
496 >                                i->second.prev.potential = i->second.curr.potential;
497 >                                i->second.curr.angle = angle;
498 >                                i->second.curr.potential = currTorsionPot;
499 >                                i->second.deltaV = fabs(i->second.curr.potential - i->second.prev.potential);
500 >                        }
501 >                }
502  
503 <    lrPot = longRangePotential.sum();
503 >                for (inversion = mol->beginInversion(inversionIter); inversion != NULL; inversion = mol->nextInversion(
504 >                                inversionIter))
505 >                {
506 >                        RealType angle;
507 >                        inversion->calcForce(angle);
508 >                        RealType currInversionPot = inversion->getPotential();
509 >                        inversionPotential += inversion->getPotential();
510 >                        map<Inversion*, InversionDataSet>::iterator i = inversionDataSets.find(inversion);
511 >                        if (i == inversionDataSets.end())
512 >                        {
513 >                                InversionDataSet dataSet;
514 >                                dataSet.prev.angle = dataSet.curr.angle = angle;
515 >                                dataSet.prev.potential = dataSet.curr.potential = currInversionPot;
516 >                                dataSet.deltaV = 0.0;
517 >                                inversionDataSets.insert(map<Inversion*, InversionDataSet>::value_type(inversion, dataSet));
518 >                        } else
519 >                        {
520 >                                i->second.prev.angle = i->second.curr.angle;
521 >                                i->second.prev.potential = i->second.curr.potential;
522 >                                i->second.curr.angle = angle;
523 >                                i->second.curr.potential = currInversionPot;
524 >                                i->second.deltaV = fabs(i->second.curr.potential - i->second.prev.potential);
525 >                        }
526 >                }
527 >        }
528  
529 <    //store the tau and long range potential    
530 <    curSnapshot->statData[Stats::LONG_RANGE_POTENTIAL] = lrPot;
531 <    curSnapshot->statData[Stats::VANDERWAALS_POTENTIAL] = longRangePotential[VANDERWAALS_FAMILY];
532 <    curSnapshot->statData[Stats::ELECTROSTATIC_POTENTIAL] = longRangePotential[ELECTROSTATIC_FAMILY];
533 <  }
529 >        RealType shortRangePotential = bondPotential + bendPotential + torsionPotential + inversionPotential;
530 >        Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
531 >        curSnapshot->statData[Stats::SHORT_RANGE_POTENTIAL] = shortRangePotential;
532 >        curSnapshot->statData[Stats::BOND_POTENTIAL] = bondPotential;
533 >        curSnapshot->statData[Stats::BEND_POTENTIAL] = bendPotential;
534 >        curSnapshot->statData[Stats::DIHEDRAL_POTENTIAL] = torsionPotential;
535 >        curSnapshot->statData[Stats::INVERSION_POTENTIAL] = inversionPotential;
536 > }
537  
538 <  
539 <  void ForceManager::postCalculation() {
540 <    SimInfo::MoleculeIterator mi;
541 <    Molecule* mol;
542 <    Molecule::RigidBodyIterator rbIter;
543 <    RigidBody* rb;
544 <    Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
545 <    
546 <    // collect the atomic forces onto rigid bodies
547 <    
548 <    for (mol = info_->beginMolecule(mi); mol != NULL;
549 <         mol = info_->nextMolecule(mi)) {
550 <      for (rb = mol->beginRigidBody(rbIter); rb != NULL;
551 <           rb = mol->nextRigidBody(rbIter)) {
552 <        Mat3x3d rbTau = rb->calcForcesAndTorquesAndVirial();
553 <        tau += rbTau;
554 <      }
555 <    }
556 <    
557 < #ifdef IS_MPI
558 <    Mat3x3d tmpTau(tau);
559 <    MPI_Allreduce(tmpTau.getArrayPointer(), tau.getArrayPointer(),
560 <                  9, MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
538 > void ForceManager::longRangeInteractionsParallel() {
539 >
540 >        Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
541 >        DataStorage* config = &(curSnapshot->atomData);
542 >        DataStorage* cgConfig = &(curSnapshot->cgData);
543 >
544 >        //calculate the center of mass of cutoff group
545 >
546 >        SimInfo::MoleculeIterator mi;
547 >        Molecule* mol;
548 >        Molecule::CutoffGroupIterator ci;
549 >        CutoffGroup* cg;
550 >
551 >        if (info_->getNCutoffGroups() > 0)
552 >        {
553 >                for (mol = info_->beginMolecule(mi); mol != NULL; mol = info_->nextMolecule(mi))
554 >                {
555 >                        for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci))
556 >                        {
557 >                                //                              cerr << "branch1\n";
558 >                                //                              cerr << "globind = " << cg->getGlobalIndex() << ":" << __LINE__ << "\n";
559 >                                cg->updateCOM();
560 >
561 >                                //                              cerr << "gbI: " << cg->getGlobalIndex() << " locI: " << cg->getLocalIndex() << " x: "
562 >                                //                                              << cgConfig->position[cg->getLocalIndex()].x() << " y: " << cgConfig->position[cg->getLocalIndex()].y()
563 >                                //                                              << " z: " << cgConfig->position[cg->getLocalIndex()].z() << "\n";
564 >                        }
565 >                }
566 >        } else
567 >        {
568 >                // center of mass of the group is the same as position of the atom
569 >                // if cutoff group does not exist
570 >                //              cerr << ":" << __LINE__ << "branch2\n";
571 >                cgConfig->position = config->position;
572 >        }
573 >
574 >        fDecomp_->zeroWorkArrays();
575 >        fDecomp_->distributeData();
576 >
577 >        int atom1, atom2, topoDist;
578 >        Vector3d d_grp, dag, d;
579 >        RealType rgrpsq, rgrp, r2, r;
580 >        RealType electroMult, vdwMult;
581 >        RealType vij;
582 >        Vector3d fij, fg, f1;
583 >        tuple3<RealType, RealType, RealType> cuts;
584 >        RealType rCutSq;
585 >        bool in_switching_region;
586 >        RealType sw, dswdr, swderiv;
587 >        vector<int> atomListColumn, atomListRow, atomListLocal;
588 >
589 >        /* Defines local interaction data to each thread */
590 >        InteractionDataPrv idatPrv;
591 >
592 >        SelfData sdat;
593 >        RealType mf;
594 >        RealType lrPot;
595 >        RealType vpair;
596 >        potVec longRangePotential(0.0);
597 >        potVec workPot(0.0);
598 >
599 >        int loopStart, loopEnd;
600 >        sdat.pot = fDecomp_->getEmbeddingPotential();
601 >
602 >        vector<CutoffGroup *> cgs;
603 >
604 >        for (mol = info_->beginMolecule(mi); mol != NULL; mol = info_->nextMolecule(mi))
605 >        {
606 >                for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci))
607 >                {
608 >                        cgs.push_back(cg);
609 >                }
610 >        }
611 >
612 >        loopEnd = PAIR_LOOP;
613 >        if (info_->requiresPrepair())
614 >        {
615 >                loopStart = PREPAIR_LOOP;
616 >        } else
617 >        {
618 >                loopStart = PAIR_LOOP;
619 >        }
620 >
621 >        for (int iLoop = loopStart; iLoop <= loopEnd; iLoop++)
622 >        {
623 >
624 >                if (iLoop == loopStart)
625 >                {
626 >                        bool update_nlist = fDecomp_->checkNeighborList();
627 >                        if (update_nlist)
628 >                                neighborMatW = fDecomp_->buildLayerBasedNeighborList();
629 >                }
630 >
631 >                /* Eager initialization */
632 >                /* Initializes InteractionManager before force calculations */
633 >                interactionMan_->initializeOMP();
634 >                /* Initializes forces used in simulation before force calculations */
635 >                interactionMan_->initNonbondedForces();
636 >
637 >                vector<CutoffGroup *>::iterator cg1;
638 >                vector<CutoffGroup *>::iterator cg2;
639 >
640 >                /* Defines local accumulators for each thread */
641 >                vector<Vector3d> forceLcl;
642 >                Vector3d fatom1Lcl;
643 >                Mat3x3d tauLcl;
644 >                potVec potLcl;
645 >
646 >                /* Defines the size of chunks into which the loop iterations will be split */
647 >                int chunkSize = cgs.size() / (omp_get_max_threads() * 5);
648 >
649 >                /*struct timeval tv, tv2;
650 >
651 >                gettimeofday(&tv, NULL);*/
652 >
653 >                /* Defines the parallel region and the list of variables that should be shared and private to each thread */
654 >                #pragma omp parallel default(none) shared(curSnapshot, iLoop, cgs, chunkSize, config) \
655 >                        private(cg1, cg2, cuts, d_grp, rgrpsq, rCutSq, idatPrv, vij, fij, in_switching_region, \
656 >                        dswdr, rgrp, atomListRow, atomListColumn, atom1, atom2, topoDist, d, r2, swderiv, fg, mf, \
657 >                        dag, tauLcl, forceLcl, fatom1Lcl, potLcl)
658 >                {
659 >                        idatPrv.shiftedPot = (cutoffMethod_ == SHIFTED_POTENTIAL) ? true : false;
660 >                        idatPrv.shiftedForce = (cutoffMethod_ == SHIFTED_FORCE) ? true : false;
661 >                        forceLcl = vector<Vector3d>(config->force.size());
662 >                        tauLcl *= 0;
663 >
664 >                        /* Spreads force calculations between threads. Each thread receives chunkSize portion of the CutoffGroups. */
665 >                        #pragma omp for schedule(dynamic, chunkSize)
666 >                        for (cg1 = cgs.begin(); cg1 < cgs.end(); ++cg1)
667 >                        {
668 >                                /* Iterates between neighbors of the CutoffGroup */
669 >                                for (cg2 = neighborMatW[(*cg1)->getGlobalIndex()].begin(); cg2 < neighborMatW[(*cg1)->getGlobalIndex()].end(); ++cg2)
670 >                                {
671 >
672 >                                        cuts = fDecomp_->getGroupCutoffs((*cg1)->getGlobalIndex(), (*cg2)->getGlobalIndex());
673 >
674 >                                        d_grp = fDecomp_->getIntergroupVector((*cg1), (*cg2));
675 >                                        curSnapshot->wrapVector(d_grp);
676 >                                        rgrpsq = d_grp.lengthSquare();
677 >
678 >                                        rCutSq = cuts.second;
679 >
680 > //                                      printf("Thread %d\tcg1:%d\tcg2:%d d_grp\tx:%f\ty:%f\tz:%f\trgrpsq:%f\n", omp_get_thread_num(), (*cg1)->getGlobalIndex(), (*cg2)->getGlobalIndex(), d_grp.x(), d_grp.y(), d_grp.z(), rgrpsq);
681 >
682 >                                        if (rgrpsq < rCutSq)
683 >                                        {
684 >                                                idatPrv.rcut = cuts.first;
685 >                                                if (iLoop == PAIR_LOOP)
686 >                                                {
687 >                                                        vij = 0.0;
688 >                                                        fij = V3Zero;
689 >                                                }
690 >
691 >                                                in_switching_region = switcher_->getSwitch(rgrpsq, idatPrv.sw, dswdr, rgrp);
692 >
693 > //                                              printf("in_switching_region:%d\trgrpsq:%f\t*idatPrv.sw:%f\tdswdr:%f\trgrp:%f\n", (in_switching_region == false ? 0 : 1), rgrpsq, idatPrv.sw, dswdr, rgrp);
694 >
695 >                                                atomListRow = fDecomp_->getAtomsInGroupRow((*cg1)->getGlobalIndex());
696 >                                                atomListColumn = fDecomp_->getAtomsInGroupColumn((*cg2)->getGlobalIndex());
697 >
698 >                                                for (vector<int>::iterator ia = atomListRow.begin(); ia != atomListRow.end(); ++ia)
699 >                                                {
700 >                                                        atom1 = (*ia);
701 >                                                        fatom1Lcl = V3Zero;
702 >
703 >                                                        for (vector<int>::iterator jb = atomListColumn.begin(); jb != atomListColumn.end(); ++jb)
704 >                                                        {
705 >                                                                atom2 = (*jb);
706 >
707 >                                                                if (!fDecomp_->skipAtomPair(atom1, atom2))
708 >                                                                {
709 >                                                                        idatPrv.vpair = 0.0;
710 >                                                                        idatPrv.pot = 0.0;
711 >                                                                        idatPrv.f1 = V3Zero;
712 >
713 >                                                                        fDecomp_->fillInteractionDataOMP(idatPrv, atom1, atom2);
714 >
715 >                                                                        topoDist = fDecomp_->getTopologicalDistance(atom1, atom2);
716 >                                                                        idatPrv.vdwMult = vdwScale_[topoDist];
717 >                                                                        idatPrv.electroMult = electrostaticScale_[topoDist];
718 >
719 > //                                                                      printf("topoDist:%d\tidatPrv.vdwMult:%f\tidatPrv.electroMult:%f\n", topoDist, idatPrv.vdwMult, idatPrv.electroMult);
720 >
721 >                                                                        if (atomListRow.size() == 1 && atomListColumn.size() == 1)
722 >                                                                        {
723 >                                                                                idatPrv.d = d_grp;
724 >                                                                                idatPrv.r2 = rgrpsq;
725 >                                                                                //cerr << "dgrp = " << d_grp << ":" << __LINE__ << "\n";
726 >                                                                        } else
727 >                                                                        {
728 >                                                                                d = fDecomp_->getInteratomicVector(atom1, atom2);
729 >                                                                                curSnapshot->wrapVector(d);
730 >                                                                                r2 = d.lengthSquare();
731 >                                                                                //cerr << "datm = " << d << ":" << __LINE__ << "\n";
732 >                                                                                idatPrv.d = d;
733 >                                                                                idatPrv.r2 = r2;
734 >                                                                        }
735 >
736 >                                                                        //printf("idatPrv.d x:%f\ty:%f\tz:%f\tidatPrv.r2:%f\n", (idatPrv.d).x(), (idatPrv.d).y(), (idatPrv.d).z(), idatPrv.r2);
737 >                                                                        //cerr << "idat.d = " << *(idat.d) << ":" << __LINE__ << "\n";
738 >                                                                        idatPrv.rij = sqrt((idatPrv.r2));
739 >                                                                        //cerr << "idat.rij = " << *(idat.rij) << "\n";
740 >
741 >                                                                        if (iLoop == PREPAIR_LOOP)
742 >                                                                        {
743 >                                                                                interactionMan_->doPrePairOMP(idatPrv);
744 >                                                                        } else
745 >                                                                        {
746 >                                                                                interactionMan_->doPairOMP(idatPrv);
747 >
748 >                                                                                /* Accumulates potential and forces in local arrays */
749 >                                                                                potLcl += idatPrv.pot;
750 >                                                                                fatom1Lcl += idatPrv.f1;
751 >                                                                                forceLcl[atom2] -= idatPrv.f1;
752 >                                                                                //cerr << "d = " << *(idat.d) << "\tv=" << vpair << "\tf=" << f1 << ":" << __LINE__ << "\n";
753 >                                                                                //printf("d x:%f y:%f z:%f vpair:%f f1 x:%f y:%f z:%f\n", idatPrv.d.x(), idatPrv.d.y(), idatPrv.d.z(), idatPrv.vpair, idatPrv.f1.x(), idatPrv.f1.y(), idatPrv.f1.z());
754 >                                                                                vij += idatPrv.vpair;
755 >                                                                                fij += idatPrv.f1;
756 >                                                                                tauLcl -= outProduct(idatPrv.d, idatPrv.f1);
757 >                                                                                //printf("vij:%f fij x:%f y:%f z:%f\n", vij, fij.x(), fij.y(), fij.z());
758 >                                                                        }
759 >                                                                }
760 >                                                        }
761 >                                                        /* We can accumulate force for current CutoffGroup in shared memory without worring about read after write bugs*/
762 >                                                        config->force[atom1] += fatom1Lcl;
763 >                                                }
764 >
765 >                                                if (iLoop == PAIR_LOOP)
766 >                                                {
767 >                                                        if (in_switching_region)
768 >                                                        {
769 >                                                                swderiv = vij * dswdr / rgrp;
770 >                                                                fg = swderiv * d_grp;
771 >                                                                fij += fg;
772 >
773 >                                                                if (atomListRow.size() == 1 && atomListColumn.size() == 1)
774 >                                                                {
775 >                                                                                tauLcl -= outProduct(idatPrv.d, fg);
776 >                                                                }
777 >
778 >                                                                for (vector<int>::iterator ia = atomListRow.begin(); ia != atomListRow.end(); ++ia)
779 >                                                                {
780 >                                                                        atom1 = (*ia);
781 >                                                                        mf = fDecomp_->getMassFactorRow(atom1);
782 >                                                                        // fg is the force on atom ia due to cutoff group's
783 >                                                                        // presence in switching region
784 >                                                                        fg = swderiv * d_grp * mf;
785 >                                                                        #pragma omp critical (forceLck)
786 >                                                                        {
787 >                                                                                fDecomp_->addForceToAtomRow(atom1, fg);
788 >                                                                        }
789 >
790 >                                                                        if (atomListRow.size() > 1)
791 >                                                                        {
792 >                                                                                if (info_->usesAtomicVirial())
793 >                                                                                {
794 >                                                                                        // find the distance between the atom
795 >                                                                                        // and the center of the cutoff group:
796 >                                                                                        dag = fDecomp_->getAtomToGroupVectorRow(atom1, (*cg1)->getGlobalIndex());
797 >                                                                                        tauLcl -= outProduct(dag, fg);
798 >                                                                                }
799 >                                                                        }
800 >                                                                }
801 >                                                                for (vector<int>::iterator jb = atomListColumn.begin(); jb != atomListColumn.end(); ++jb)
802 >                                                                {
803 >                                                                        atom2 = (*jb);
804 >                                                                        mf = fDecomp_->getMassFactorColumn(atom2);
805 >                                                                        // fg is the force on atom jb due to cutoff group's
806 >                                                                        // presence in switching region
807 >                                                                        fg = -swderiv * d_grp * mf;
808 >                                                                        #pragma omp critical (forceLck)
809 >                                                                        {
810 >                                                                                fDecomp_->addForceToAtomColumn(atom2, fg);
811 >                                                                        }
812 >
813 >                                                                        if (atomListColumn.size() > 1)
814 >                                                                        {
815 >                                                                                if (info_->usesAtomicVirial())
816 >                                                                                {
817 >                                                                                        // find the distance between the atom
818 >                                                                                        // and the center of the cutoff group:
819 >                                                                                        dag = fDecomp_->getAtomToGroupVectorColumn(atom2, (*cg2)->getGlobalIndex());
820 >                                                                                        tauLcl -= outProduct(dag, fg);
821 >                                                                                }
822 >                                                                        }
823 >                                                                }
824 >                                                        }
825 >                                                        //if (!SIM_uses_AtomicVirial) {
826 >                                                        //  tau -= outProduct(d_grp, fij);
827 >                                                        //}
828 >                                                }
829 >                                        }
830 >                                }
831 >                        }// END: omp for loop
832 >                        /* Critical region which accumulates forces from local to shared arrays  */
833 >                        #pragma omp critical (forceAdd)
834 >                        {
835 >                                for (int currAtom = 0; currAtom < config->force.size(); ++currAtom)
836 >                                {
837 >                                        config->force[currAtom] += forceLcl[currAtom];
838 >                                }
839 >
840 >                                tau -= tauLcl;
841 >                                *(fDecomp_->getPairwisePotential()) += potLcl;
842 >                        }
843 >                }// END: omp parallel region
844 >
845 >                /*gettimeofday(&tv2, NULL);
846 >
847 >                elapsedTime += 1000000 * (tv2.tv_sec - tv.tv_sec)
848 >                                                + (tv2.tv_usec - tv.tv_usec);
849 >
850 >                Globals *simParams_ = info_->getSimParams();
851 >
852 >                if(curSnapshot->getTime() >= simParams_->getRunTime() - 1)
853 >                {
854 >                        printf("Force calculation time: %ld [us]\n", elapsedTime);
855 >                }*/
856 >
857 >                if (iLoop == PREPAIR_LOOP)
858 >                {
859 >                        if (info_->requiresPrepair())
860 >                        {
861 >
862 >                                fDecomp_->collectIntermediateData();
863 >
864 >                                for (int atom1 = 0; atom1 < info_->getNAtoms(); atom1++)
865 >                                {
866 >                                        fDecomp_->fillSelfData(sdat, atom1);
867 >                                        interactionMan_->doPreForce(sdat);
868 >                                }
869 >
870 >                                fDecomp_->distributeIntermediateData();
871 >
872 >                        }
873 >                }
874 >        }
875 >
876 >        fDecomp_->collectData();
877 >
878 >        if (info_->requiresSelfCorrection())
879 >        {
880 >
881 >                for (int atom1 = 0; atom1 < info_->getNAtoms(); atom1++)
882 >                {
883 >                        fDecomp_->fillSelfData(sdat, atom1);
884 >                        interactionMan_->doSelfCorrection(sdat);
885 >                }
886 >
887 >        }
888 >
889 >        longRangePotential = *(fDecomp_->getEmbeddingPotential()) + *(fDecomp_->getPairwisePotential());
890 >
891 >        lrPot = longRangePotential.sum();
892 >
893 >        //store the tau and long range potential
894 >        curSnapshot->statData[Stats::LONG_RANGE_POTENTIAL] = lrPot;
895 >        curSnapshot->statData[Stats::VANDERWAALS_POTENTIAL] = longRangePotential[VANDERWAALS_FAMILY];
896 >        curSnapshot->statData[Stats::ELECTROSTATIC_POTENTIAL] = longRangePotential[ELECTROSTATIC_FAMILY];
897 > }
898 >
899 > void ForceManager::longRangeInteractionsRapaport() {
900 >
901 >        Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
902 >        DataStorage* config = &(curSnapshot->atomData);
903 >        DataStorage* cgConfig = &(curSnapshot->cgData);
904 >
905 >        //calculate the center of mass of cutoff group
906 >
907 >        SimInfo::MoleculeIterator mi;
908 >        Molecule* mol;
909 >        Molecule::CutoffGroupIterator ci;
910 >        CutoffGroup* cg;
911 >
912 >        if (info_->getNCutoffGroups() > 0)
913 >        {
914 >                for (mol = info_->beginMolecule(mi); mol != NULL; mol = info_->nextMolecule(mi))
915 >                {
916 >                        for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci))
917 >                        {
918 >                                //                              cerr << "branch1\n";
919 >                                //                              cerr << "globind = " << cg->getGlobalIndex() << ":" << __LINE__ << "\n";
920 >                                cg->updateCOM();
921 >
922 >                                //                              cerr << "gbI: " << cg->getGlobalIndex() << " locI: " << cg->getLocalIndex() << " x: "
923 >                                //                                              << cgConfig->position[cg->getLocalIndex()].x() << " y: " << cgConfig->position[cg->getLocalIndex()].y()
924 >                                //                                              << " z: " << cgConfig->position[cg->getLocalIndex()].z() << "\n";
925 >                        }
926 >                }
927 >        } else
928 >        {
929 >                // center of mass of the group is the same as position of the atom
930 >                // if cutoff group does not exist
931 >                //              cerr << ":" << __LINE__ << "branch2\n";
932 >                cgConfig->position = config->position;
933 >        }
934 >
935 >        fDecomp_->zeroWorkArrays();
936 >        fDecomp_->distributeData();
937 >
938 >        int atom1, atom2, topoDist;
939 >        CutoffGroup *cg1;
940 >        Vector3d d_grp, dag, d;
941 >        RealType rgrpsq, rgrp, r2, r;
942 >        RealType electroMult, vdwMult;
943 >        RealType vij;
944 >        Vector3d fij, fg, f1;
945 >        tuple3<RealType, RealType, RealType> cuts;
946 >        RealType rCutSq;
947 >        bool in_switching_region;
948 >        RealType sw, dswdr, swderiv;
949 >        vector<int> atomListColumn, atomListRow, atomListLocal;
950 >        InteractionData idat;
951 >        SelfData sdat;
952 >        RealType mf;
953 >        RealType lrPot;
954 >        RealType vpair;
955 >        potVec longRangePotential(0.0);
956 >        potVec workPot(0.0);
957 >
958 >        int loopStart, loopEnd;
959 >
960 >        idat.vdwMult = &vdwMult;
961 >        idat.electroMult = &electroMult;
962 >        idat.pot = &workPot;
963 >        sdat.pot = fDecomp_->getEmbeddingPotential();
964 >        idat.vpair = &vpair;
965 >        idat.f1 = &f1;
966 >        idat.sw = &sw;
967 >        idat.shiftedPot = (cutoffMethod_ == SHIFTED_POTENTIAL) ? true : false;
968 >        idat.shiftedForce = (cutoffMethod_ == SHIFTED_FORCE) ? true : false;
969 >
970 >        loopEnd = PAIR_LOOP;
971 >        if (info_->requiresPrepair())
972 >        {
973 >                loopStart = PREPAIR_LOOP;
974 >        } else
975 >        {
976 >                loopStart = PAIR_LOOP;
977 >        }
978 >
979 >        for (int iLoop = loopStart; iLoop <= loopEnd; iLoop++)
980 >        {
981 >
982 >                if (iLoop == loopStart)
983 >                {
984 >                        bool update_nlist = fDecomp_->checkNeighborList();
985 >                        if (update_nlist)
986 >                                neighborMatW = fDecomp_->buildLayerBasedNeighborList();
987 >                }
988 >
989 >                for (mol = info_->beginMolecule(mi); mol != NULL; mol = info_->nextMolecule(mi))
990 >                {
991 >                        for (cg1 = mol->beginCutoffGroup(ci); cg1 != NULL; cg1 = mol->nextCutoffGroup(ci))
992 >                        {
993 >                                //                      printf("Thread %d executes loop iteration %d\n", omp_get_thread_num(), i);
994 >                                for (vector<CutoffGroup *>::iterator cg2 = neighborMatW[cg1->getGlobalIndex()].begin(); cg2
995 >                                                != neighborMatW[cg1->getGlobalIndex()].end(); ++cg2)
996 >                                {
997 >
998 >                                        cuts = fDecomp_->getGroupCutoffs(cg1->getGlobalIndex(), (*cg2)->getGlobalIndex());
999 >
1000 >                                        d_grp = fDecomp_->getIntergroupVector(cg1, (*cg2));
1001 >                                        curSnapshot->wrapVector(d_grp);
1002 >                                        rgrpsq = d_grp.lengthSquare();
1003 >
1004 >                                        rCutSq = cuts.second;
1005 >
1006 >                                        if (rgrpsq < rCutSq)
1007 >                                        {
1008 >                                                idat.rcut = &cuts.first;
1009 >                                                if (iLoop == PAIR_LOOP)
1010 >                                                {
1011 >                                                        vij = 0.0;
1012 >                                                        fij = V3Zero;
1013 >                                                }
1014 >
1015 >                                                in_switching_region = switcher_->getSwitch(rgrpsq, sw, dswdr, rgrp);
1016 >
1017 >                                                atomListRow = fDecomp_->getAtomsInGroupRow(cg1->getGlobalIndex());
1018 >                                                atomListColumn = fDecomp_->getAtomsInGroupColumn((*cg2)->getGlobalIndex());
1019 >
1020 >                                                for (vector<int>::iterator ia = atomListRow.begin(); ia != atomListRow.end(); ++ia)
1021 >                                                {
1022 >                                                        atom1 = (*ia);
1023 >
1024 >                                                        for (vector<int>::iterator jb = atomListColumn.begin(); jb != atomListColumn.end(); ++jb)
1025 >                                                        {
1026 >                                                                atom2 = (*jb);
1027 >
1028 >                                                                if (!fDecomp_->skipAtomPair(atom1, atom2))
1029 >                                                                {
1030 >                                                                        vpair = 0.0;
1031 >                                                                        workPot = 0.0;
1032 >                                                                        f1 = V3Zero;
1033 >
1034 >                                                                        fDecomp_->fillInteractionData(idat, atom1, atom2);
1035 >
1036 >                                                                        topoDist = fDecomp_->getTopologicalDistance(atom1, atom2);
1037 >                                                                        vdwMult = vdwScale_[topoDist];
1038 >                                                                        electroMult = electrostaticScale_[topoDist];
1039 >
1040 >                                                                        if (atomListRow.size() == 1 && atomListColumn.size() == 1)
1041 >                                                                        {
1042 >                                                                                idat.d = &d_grp;
1043 >                                                                                idat.r2 = &rgrpsq;
1044 >                                                                                //                                                                              cerr << "dgrp = " << d_grp << ":" << __LINE__ << "\n";
1045 >                                                                        } else
1046 >                                                                        {
1047 >                                                                                d = fDecomp_->getInteratomicVector(atom1, atom2);
1048 >                                                                                curSnapshot->wrapVector(d);
1049 >                                                                                r2 = d.lengthSquare();
1050 >                                                                                //                                                                              cerr << "datm = " << d << ":" << __LINE__ << "\n";
1051 >                                                                                idat.d = &d;
1052 >                                                                                idat.r2 = &r2;
1053 >                                                                        }
1054 >
1055 >                                                                        //                                                                      cerr << "idat.d = " << *(idat.d) << ":" << __LINE__ << "\n";
1056 >                                                                        r = sqrt(*(idat.r2));
1057 >                                                                        idat.rij = &r;
1058 >                                                                        //                                                                      cerr << "idat.rij = " << *(idat.rij) << "\n";
1059 >
1060 >                                                                        if (iLoop == PREPAIR_LOOP)
1061 >                                                                        {
1062 >                                                                                interactionMan_->doPrePair(idat);
1063 >                                                                        } else
1064 >                                                                        {
1065 >                                                                                interactionMan_->doPair(idat);
1066 >                                                                                fDecomp_->unpackInteractionData(idat, atom1, atom2);
1067 >
1068 >                                                                                //                                                                              cerr << "d = " << *(idat.d) << "\tv=" << vpair << "\tf=" << f1 << ":" << __LINE__ << "\n";
1069 >                                                                                vij += vpair;
1070 >                                                                                fij += f1;
1071 >                                                                                tau -= outProduct(*(idat.d), f1);
1072 >                                                                        }
1073 >                                                                }
1074 >                                                        }
1075 >                                                }
1076 >
1077 >                                                if (iLoop == PAIR_LOOP)
1078 >                                                {
1079 >                                                        if (in_switching_region)
1080 >                                                        {
1081 >                                                                swderiv = vij * dswdr / rgrp;
1082 >                                                                fg = swderiv * d_grp;
1083 >                                                                fij += fg;
1084 >
1085 >                                                                if (atomListRow.size() == 1 && atomListColumn.size() == 1)
1086 >                                                                {
1087 >                                                                        tau -= outProduct(*(idat.d), fg);
1088 >                                                                }
1089 >
1090 >                                                                for (vector<int>::iterator ia = atomListRow.begin(); ia != atomListRow.end(); ++ia)
1091 >                                                                {
1092 >                                                                        atom1 = (*ia);
1093 >                                                                        mf = fDecomp_->getMassFactorRow(atom1);
1094 >                                                                        // fg is the force on atom ia due to cutoff group's
1095 >                                                                        // presence in switching region
1096 >                                                                        fg = swderiv * d_grp * mf;
1097 >                                                                        fDecomp_->addForceToAtomRow(atom1, fg);
1098 >
1099 >                                                                        if (atomListRow.size() > 1)
1100 >                                                                        {
1101 >                                                                                if (info_->usesAtomicVirial())
1102 >                                                                                {
1103 >                                                                                        // find the distance between the atom
1104 >                                                                                        // and the center of the cutoff group:
1105 >                                                                                        dag = fDecomp_->getAtomToGroupVectorRow(atom1, cg1->getGlobalIndex());
1106 >                                                                                        tau -= outProduct(dag, fg);
1107 >                                                                                }
1108 >                                                                        }
1109 >                                                                }
1110 >                                                                for (vector<int>::iterator jb = atomListColumn.begin(); jb != atomListColumn.end(); ++jb)
1111 >                                                                {
1112 >                                                                        atom2 = (*jb);
1113 >                                                                        mf = fDecomp_->getMassFactorColumn(atom2);
1114 >                                                                        // fg is the force on atom jb due to cutoff group's
1115 >                                                                        // presence in switching region
1116 >                                                                        fg = -swderiv * d_grp * mf;
1117 >                                                                        fDecomp_->addForceToAtomColumn(atom2, fg);
1118 >
1119 >                                                                        if (atomListColumn.size() > 1)
1120 >                                                                        {
1121 >                                                                                if (info_->usesAtomicVirial())
1122 >                                                                                {
1123 >                                                                                        // find the distance between the atom
1124 >                                                                                        // and the center of the cutoff group:
1125 >                                                                                        dag = fDecomp_->getAtomToGroupVectorColumn(atom2, (*cg2)->getGlobalIndex());
1126 >                                                                                        tau -= outProduct(dag, fg);
1127 >                                                                                }
1128 >                                                                        }
1129 >                                                                }
1130 >                                                        }
1131 >                                                        //if (!SIM_uses_AtomicVirial) {
1132 >                                                        //  tau -= outProduct(d_grp, fij);
1133 >                                                        //}
1134 >                                                }
1135 >                                        }
1136 >                                }
1137 >                        }
1138 >                }
1139 >
1140 >                if (iLoop == PREPAIR_LOOP)
1141 >                {
1142 >                        if (info_->requiresPrepair())
1143 >                        {
1144 >
1145 >                                fDecomp_->collectIntermediateData();
1146 >
1147 >                                for (int atom1 = 0; atom1 < info_->getNAtoms(); atom1++)
1148 >                                {
1149 >                                        fDecomp_->fillSelfData(sdat, atom1);
1150 >                                        interactionMan_->doPreForce(sdat);
1151 >                                }
1152 >
1153 >                                fDecomp_->distributeIntermediateData();
1154 >
1155 >                        }
1156 >                }
1157 >        }
1158 >
1159 >        fDecomp_->collectData();
1160 >
1161 >        if (info_->requiresSelfCorrection())
1162 >        {
1163 >
1164 >                for (int atom1 = 0; atom1 < info_->getNAtoms(); atom1++)
1165 >                {
1166 >                        fDecomp_->fillSelfData(sdat, atom1);
1167 >                        interactionMan_->doSelfCorrection(sdat);
1168 >                }
1169 >
1170 >        }
1171 >
1172 >        longRangePotential = *(fDecomp_->getEmbeddingPotential()) + *(fDecomp_->getPairwisePotential());
1173 >
1174 >        lrPot = longRangePotential.sum();
1175 >
1176 >        //store the tau and long range potential
1177 >        curSnapshot->statData[Stats::LONG_RANGE_POTENTIAL] = lrPot;
1178 >        curSnapshot->statData[Stats::VANDERWAALS_POTENTIAL] = longRangePotential[VANDERWAALS_FAMILY];
1179 >        curSnapshot->statData[Stats::ELECTROSTATIC_POTENTIAL] = longRangePotential[ELECTROSTATIC_FAMILY];
1180 > }
1181 >
1182 > void ForceManager::longRangeInteractions() {
1183 >
1184 >        Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
1185 >        DataStorage* config = &(curSnapshot->atomData);
1186 >        DataStorage* cgConfig = &(curSnapshot->cgData);
1187 >
1188 >        //calculate the center of mass of cutoff group
1189 >
1190 >        SimInfo::MoleculeIterator mi;
1191 >        Molecule* mol;
1192 >        Molecule::CutoffGroupIterator ci;
1193 >        CutoffGroup* cg;
1194 >
1195 >        if (info_->getNCutoffGroups() > 0)
1196 >        {
1197 >                for (mol = info_->beginMolecule(mi); mol != NULL; mol = info_->nextMolecule(mi))
1198 >                {
1199 >                        for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci))
1200 >                        {
1201 >                                cerr << "branch1\n";
1202 >                                cerr << "globind = " << cg->getGlobalIndex() << "\n";
1203 >                                cg->updateCOM();
1204 >                        }
1205 >                }
1206 >        } else
1207 >        {
1208 >                // center of mass of the group is the same as position of the atom
1209 >                // if cutoff group does not exist
1210 >                cerr << "branch2\n";
1211 >                cgConfig->position = config->position;
1212 >        }
1213 >
1214 >        fDecomp_->zeroWorkArrays();
1215 >        fDecomp_->distributeData();
1216 >
1217 >        int cg1, cg2, atom1, atom2, topoDist;
1218 >        Vector3d d_grp, dag, d;
1219 >        RealType rgrpsq, rgrp, r2, r;
1220 >        RealType electroMult, vdwMult;
1221 >        RealType vij;
1222 >        Vector3d fij, fg, f1;
1223 >        tuple3<RealType, RealType, RealType> cuts;
1224 >        RealType rCutSq;
1225 >        bool in_switching_region;
1226 >        RealType sw, dswdr, swderiv;
1227 >        vector<int> atomListColumn, atomListRow, atomListLocal;
1228 >        InteractionData idat;
1229 >        SelfData sdat;
1230 >        RealType mf;
1231 >        RealType lrPot;
1232 >        RealType vpair;
1233 >        potVec longRangePotential(0.0);
1234 >        potVec workPot(0.0);
1235 >
1236 >        int loopStart, loopEnd;
1237 >
1238 >        idat.vdwMult = &vdwMult;
1239 >        idat.electroMult = &electroMult;
1240 >        idat.pot = &workPot;
1241 >        sdat.pot = fDecomp_->getEmbeddingPotential();
1242 >        idat.vpair = &vpair;
1243 >        idat.f1 = &f1;
1244 >        idat.sw = &sw;
1245 >        idat.shiftedPot = (cutoffMethod_ == SHIFTED_POTENTIAL) ? true : false;
1246 >        idat.shiftedForce = (cutoffMethod_ == SHIFTED_FORCE) ? true : false;
1247 >
1248 >        loopEnd = PAIR_LOOP;
1249 >        if (info_->requiresPrepair())
1250 >        {
1251 >                loopStart = PREPAIR_LOOP;
1252 >        } else
1253 >        {
1254 >                loopStart = PAIR_LOOP;
1255 >        }
1256 >
1257 >        for (int iLoop = loopStart; iLoop <= loopEnd; iLoop++)
1258 >        {
1259 >
1260 >                if (iLoop == loopStart)
1261 >                {
1262 >                        bool update_nlist = fDecomp_->checkNeighborList();
1263 >                        if (update_nlist)
1264 >                                neighborList = fDecomp_->buildNeighborList();
1265 >
1266 >                }
1267 >
1268 >                for (vector<pair<int, int> >::iterator it = neighborList.begin(); it != neighborList.end(); ++it)
1269 >                {
1270 >                        cg1 = (*it).first;
1271 >                        cg2 = (*it).second;
1272 >
1273 >                        cuts = fDecomp_->getGroupCutoffs(cg1, cg2);
1274 >
1275 >                        d_grp = fDecomp_->getIntergroupVector(cg1, cg2);
1276 >                        curSnapshot->wrapVector(d_grp);
1277 >                        rgrpsq = d_grp.lengthSquare();
1278 >
1279 >                        rCutSq = cuts.second;
1280 >
1281 >                        if (rgrpsq < rCutSq)
1282 >                        {
1283 >                                idat.rcut = &cuts.first;
1284 >                                if (iLoop == PAIR_LOOP)
1285 >                                {
1286 >                                        vij = 0.0;
1287 >                                        fij = V3Zero;
1288 >                                }
1289 >
1290 >                                in_switching_region = switcher_->getSwitch(rgrpsq, sw, dswdr, rgrp);
1291 >
1292 >                                atomListRow = fDecomp_->getAtomsInGroupRow(cg1);
1293 >                                atomListColumn = fDecomp_->getAtomsInGroupColumn(cg2);
1294 >
1295 >                                for (vector<int>::iterator ia = atomListRow.begin(); ia != atomListRow.end(); ++ia)
1296 >                                {
1297 >                                        atom1 = (*ia);
1298 >
1299 >                                        for (vector<int>::iterator jb = atomListColumn.begin(); jb != atomListColumn.end(); ++jb)
1300 >                                        {
1301 >                                                atom2 = (*jb);
1302 >
1303 >                                                if (!fDecomp_->skipAtomPair(atom1, atom2))
1304 >                                                {
1305 >                                                        vpair = 0.0;
1306 >                                                        workPot = 0.0;
1307 >                                                        f1 = V3Zero;
1308 >
1309 >                                                        fDecomp_->fillInteractionData(idat, atom1, atom2);
1310 >
1311 >                                                        topoDist = fDecomp_->getTopologicalDistance(atom1, atom2);
1312 >                                                        vdwMult = vdwScale_[topoDist];
1313 >                                                        electroMult = electrostaticScale_[topoDist];
1314 >
1315 >                                                        if (atomListRow.size() == 1 && atomListColumn.size() == 1)
1316 >                                                        {
1317 >                                                                idat.d = &d_grp;
1318 >                                                                idat.r2 = &rgrpsq;
1319 >                                                                cerr << "dgrp = " << d_grp << "\n";
1320 >                                                        } else
1321 >                                                        {
1322 >                                                                d = fDecomp_->getInteratomicVector(atom1, atom2);
1323 >                                                                curSnapshot->wrapVector(d);
1324 >                                                                r2 = d.lengthSquare();
1325 >                                                                cerr << "datm = " << d << "\n";
1326 >                                                                idat.d = &d;
1327 >                                                                idat.r2 = &r2;
1328 >                                                        }
1329 >
1330 >                                                        cerr << "idat.d = " << *(idat.d) << "\n";
1331 >                                                        r = sqrt(*(idat.r2));
1332 >                                                        idat.rij = &r;
1333 >
1334 >                                                        if (iLoop == PREPAIR_LOOP)
1335 >                                                        {
1336 >                                                                interactionMan_->doPrePair(idat);
1337 >                                                        } else
1338 >                                                        {
1339 >                                                                interactionMan_->doPair(idat);
1340 >                                                                fDecomp_->unpackInteractionData(idat, atom1, atom2);
1341 >
1342 >                                                                cerr << "d = " << *(idat.d) << "\tv=" << vpair << "\tf=" << f1 << "\n";
1343 >                                                                vij += vpair;
1344 >                                                                fij += f1;
1345 >                                                                tau -= outProduct(*(idat.d), f1);
1346 >                                                        }
1347 >                                                }
1348 >                                        }
1349 >                                }
1350 >
1351 >                                if (iLoop == PAIR_LOOP)
1352 >                                {
1353 >                                        if (in_switching_region)
1354 >                                        {
1355 >                                                swderiv = vij * dswdr / rgrp;
1356 >                                                fg = swderiv * d_grp;
1357 >                                                fij += fg;
1358 >
1359 >                                                if (atomListRow.size() == 1 && atomListColumn.size() == 1)
1360 >                                                {
1361 >                                                        tau -= outProduct(*(idat.d), fg);
1362 >                                                }
1363 >
1364 >                                                for (vector<int>::iterator ia = atomListRow.begin(); ia != atomListRow.end(); ++ia)
1365 >                                                {
1366 >                                                        atom1 = (*ia);
1367 >                                                        mf = fDecomp_->getMassFactorRow(atom1);
1368 >                                                        // fg is the force on atom ia due to cutoff group's
1369 >                                                        // presence in switching region
1370 >                                                        fg = swderiv * d_grp * mf;
1371 >                                                        fDecomp_->addForceToAtomRow(atom1, fg);
1372 >
1373 >                                                        if (atomListRow.size() > 1)
1374 >                                                        {
1375 >                                                                if (info_->usesAtomicVirial())
1376 >                                                                {
1377 >                                                                        // find the distance between the atom
1378 >                                                                        // and the center of the cutoff group:
1379 >                                                                        dag = fDecomp_->getAtomToGroupVectorRow(atom1, cg1);
1380 >                                                                        tau -= outProduct(dag, fg);
1381 >                                                                }
1382 >                                                        }
1383 >                                                }
1384 >                                                for (vector<int>::iterator jb = atomListColumn.begin(); jb != atomListColumn.end(); ++jb)
1385 >                                                {
1386 >                                                        atom2 = (*jb);
1387 >                                                        mf = fDecomp_->getMassFactorColumn(atom2);
1388 >                                                        // fg is the force on atom jb due to cutoff group's
1389 >                                                        // presence in switching region
1390 >                                                        fg = -swderiv * d_grp * mf;
1391 >                                                        fDecomp_->addForceToAtomColumn(atom2, fg);
1392 >
1393 >                                                        if (atomListColumn.size() > 1)
1394 >                                                        {
1395 >                                                                if (info_->usesAtomicVirial())
1396 >                                                                {
1397 >                                                                        // find the distance between the atom
1398 >                                                                        // and the center of the cutoff group:
1399 >                                                                        dag = fDecomp_->getAtomToGroupVectorColumn(atom2, cg2);
1400 >                                                                        tau -= outProduct(dag, fg);
1401 >                                                                }
1402 >                                                        }
1403 >                                                }
1404 >                                        }
1405 >                                        //if (!SIM_uses_AtomicVirial) {
1406 >                                        //  tau -= outProduct(d_grp, fij);
1407 >                                        //}
1408 >                                }
1409 >                        }
1410 >                }
1411 >
1412 >                if (iLoop == PREPAIR_LOOP)
1413 >                {
1414 >                        if (info_->requiresPrepair())
1415 >                        {
1416 >
1417 >                                fDecomp_->collectIntermediateData();
1418 >
1419 >                                for (int atom1 = 0; atom1 < info_->getNAtoms(); atom1++)
1420 >                                {
1421 >                                        fDecomp_->fillSelfData(sdat, atom1);
1422 >                                        interactionMan_->doPreForce(sdat);
1423 >                                }
1424 >
1425 >                                fDecomp_->distributeIntermediateData();
1426 >
1427 >                        }
1428 >                }
1429 >
1430 >        }
1431 >
1432 >        fDecomp_->collectData();
1433 >
1434 >        if (info_->requiresSelfCorrection())
1435 >        {
1436 >
1437 >                for (int atom1 = 0; atom1 < info_->getNAtoms(); atom1++)
1438 >                {
1439 >                        fDecomp_->fillSelfData(sdat, atom1);
1440 >                        interactionMan_->doSelfCorrection(sdat);
1441 >                }
1442 >
1443 >        }
1444 >
1445 >        longRangePotential = *(fDecomp_->getEmbeddingPotential()) + *(fDecomp_->getPairwisePotential());
1446 >
1447 >        lrPot = longRangePotential.sum();
1448 >
1449 >        //store the tau and long range potential
1450 >        curSnapshot->statData[Stats::LONG_RANGE_POTENTIAL] = lrPot;
1451 >        curSnapshot->statData[Stats::VANDERWAALS_POTENTIAL] = longRangePotential[VANDERWAALS_FAMILY];
1452 >        curSnapshot->statData[Stats::ELECTROSTATIC_POTENTIAL] = longRangePotential[ELECTROSTATIC_FAMILY];
1453 > }
1454 >
1455 > void ForceManager::postCalculation() {
1456 >        SimInfo::MoleculeIterator mi;
1457 >        Molecule* mol;
1458 >        Molecule::RigidBodyIterator rbIter;
1459 >        RigidBody* rb;
1460 >        Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
1461 >
1462 >        // collect the atomic forces onto rigid bodies
1463 >
1464 >        for (mol = info_->beginMolecule(mi); mol != NULL; mol = info_->nextMolecule(mi))
1465 >        {
1466 >                for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter))
1467 >                {
1468 >                        Mat3x3d rbTau = rb->calcForcesAndTorquesAndVirial();
1469 >                        tau += rbTau;
1470 >                }
1471 >        }
1472 >
1473 > #ifdef IS_MPI
1474 >        Mat3x3d tmpTau(tau);
1475 >        MPI_Allreduce(tmpTau.getArrayPointer(), tau.getArrayPointer(),
1476 >                        9, MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
1477   #endif
1478 <    curSnapshot->statData.setTau(tau);
1479 <  }
1478 >        curSnapshot->statData.setTau(tau);
1479 > }
1480  
1481   } //end namespace OpenMD

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines