ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/rnemd/RNEMD.cpp
Revision: 1769
Committed: Mon Jul 9 14:15:52 2012 UTC (12 years, 9 months ago) by gezelter
File size: 52767 byte(s)
Log Message:
Code readability updates.

File Contents

# User Rev Content
1 gezelter 1329 /*
2     * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3     *
4     * The University of Notre Dame grants you ("Licensee") a
5     * non-exclusive, royalty free, license to use, modify and
6     * redistribute this software in source and binary code form, provided
7     * that the following conditions are met:
8     *
9 gezelter 1390 * 1. Redistributions of source code must retain the above copyright
10 gezelter 1329 * notice, this list of conditions and the following disclaimer.
11     *
12 gezelter 1390 * 2. Redistributions in binary form must reproduce the above copyright
13 gezelter 1329 * notice, this list of conditions and the following disclaimer in the
14     * documentation and/or other materials provided with the
15     * distribution.
16     *
17     * This software is provided "AS IS," without a warranty of any
18     * kind. All express or implied conditions, representations and
19     * warranties, including any implied warranty of merchantability,
20     * fitness for a particular purpose or non-infringement, are hereby
21     * excluded. The University of Notre Dame and its licensors shall not
22     * be liable for any damages suffered by licensee as a result of
23     * using, modifying or distributing the software or its
24     * derivatives. In no event will the University of Notre Dame or its
25     * licensors be liable for any lost revenue, profit or data, or for
26     * direct, indirect, special, consequential, incidental or punitive
27     * damages, however caused and regardless of the theory of liability,
28     * arising out of the use of or inability to use software, even if the
29     * University of Notre Dame has been advised of the possibility of
30     * such damages.
31 gezelter 1390 *
32     * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
33     * research, please cite the appropriate papers when you publish your
34     * work. Good starting points are:
35     *
36     * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
37     * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
38     * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 24107 (2008).
39 gezelter 1722 * [4] Vardeman & Gezelter, in progress (2009).
40 gezelter 1329 */
41    
42 skuang 1368 #include <cmath>
43 gezelter 1731 #include "rnemd/RNEMD.hpp"
44 gezelter 1332 #include "math/Vector3.hpp"
45 gezelter 1722 #include "math/Vector.hpp"
46 gezelter 1329 #include "math/SquareMatrix3.hpp"
47 skuang 1368 #include "math/Polynomial.hpp"
48 gezelter 1329 #include "primitives/Molecule.hpp"
49     #include "primitives/StuntDouble.hpp"
50 gezelter 1390 #include "utils/PhysicalConstants.hpp"
51 gezelter 1332 #include "utils/Tuple.hpp"
52 gezelter 1329
53     #ifndef IS_MPI
54     #include "math/SeqRandNumGen.hpp"
55     #else
56     #include "math/ParallelRandNumGen.hpp"
57 gezelter 1723 #include <mpi.h>
58 gezelter 1329 #endif
59    
60 gezelter 1350 #define HONKING_LARGE_VALUE 1.0e10
61 gezelter 1329
62 gezelter 1629 using namespace std;
63 gezelter 1390 namespace OpenMD {
64 gezelter 1329
65 gezelter 1629 RNEMD::RNEMD(SimInfo* info) : info_(info), evaluator_(info), seleMan_(info),
66     usePeriodicBoundaryConditions_(info->getSimParams()->getUsePeriodicBoundaryConditions()) {
67 skuang 1368
68     failTrialCount_ = 0;
69     failRootCount_ = 0;
70    
71 gezelter 1329 int seedValue;
72     Globals * simParams = info->getSimParams();
73 gezelter 1731 RNEMDParameters* rnemdParams = simParams->getRNEMDParameters();
74 skuang 1330
75 skuang 1368 stringToEnumMap_["KineticSwap"] = rnemdKineticSwap;
76     stringToEnumMap_["KineticScale"] = rnemdKineticScale;
77 gezelter 1722 stringToEnumMap_["KineticScaleVAM"] = rnemdKineticScaleVAM;
78     stringToEnumMap_["KineticScaleAM"] = rnemdKineticScaleAM;
79 skuang 1368 stringToEnumMap_["PxScale"] = rnemdPxScale;
80     stringToEnumMap_["PyScale"] = rnemdPyScale;
81     stringToEnumMap_["PzScale"] = rnemdPzScale;
82 skuang 1330 stringToEnumMap_["Px"] = rnemdPx;
83     stringToEnumMap_["Py"] = rnemdPy;
84     stringToEnumMap_["Pz"] = rnemdPz;
85 gezelter 1722 stringToEnumMap_["ShiftScaleV"] = rnemdShiftScaleV;
86     stringToEnumMap_["ShiftScaleVAM"] = rnemdShiftScaleVAM;
87 skuang 1330 stringToEnumMap_["Unknown"] = rnemdUnknown;
88    
89 jmarr 1728 runTime_ = simParams->getRunTime();
90     statusTime_ = simParams->getStatusTime();
91    
92 gezelter 1731 rnemdObjectSelection_ = rnemdParams->getObjectSelection();
93 skuang 1341 evaluator_.loadScriptString(rnemdObjectSelection_);
94     seleMan_.setSelectionSet(evaluator_.evaluate());
95 gezelter 1331
96 skuang 1341 // do some sanity checking
97    
98     int selectionCount = seleMan_.getSelectionCount();
99     int nIntegrable = info->getNGlobalIntegrableObjects();
100    
101     if (selectionCount > nIntegrable) {
102     sprintf(painCave.errMsg,
103 gezelter 1629 "RNEMD: The current RNEMD_objectSelection,\n"
104 skuang 1341 "\t\t%s\n"
105     "\thas resulted in %d selected objects. However,\n"
106     "\tthe total number of integrable objects in the system\n"
107     "\tis only %d. This is almost certainly not what you want\n"
108     "\tto do. A likely cause of this is forgetting the _RB_0\n"
109     "\tselector in the selection script!\n",
110     rnemdObjectSelection_.c_str(),
111     selectionCount, nIntegrable);
112     painCave.isFatal = 0;
113 gezelter 1629 painCave.severity = OPENMD_WARNING;
114 skuang 1341 simError();
115     }
116 gezelter 1331
117 gezelter 1731 const string st = rnemdParams->getExchangeType();
118 skuang 1330
119 gezelter 1629 map<string, RNEMDTypeEnum>::iterator i;
120 skuang 1330 i = stringToEnumMap_.find(st);
121 skuang 1368 rnemdType_ = (i == stringToEnumMap_.end()) ? RNEMD::rnemdUnknown : i->second;
122     if (rnemdType_ == rnemdUnknown) {
123 gezelter 1629 sprintf(painCave.errMsg,
124     "RNEMD: The current RNEMD_exchangeType,\n"
125     "\t\t%s\n"
126     "\tis not one of the recognized exchange types.\n",
127     st.c_str());
128     painCave.isFatal = 1;
129     painCave.severity = OPENMD_ERROR;
130     simError();
131 skuang 1368 }
132 gezelter 1629
133 gezelter 1722 outputTemp_ = false;
134 gezelter 1731 if (rnemdParams->haveOutputTemperature()) {
135     outputTemp_ = rnemdParams->getOutputTemperature();
136 gezelter 1722 } else if ((rnemdType_ == rnemdKineticSwap) ||
137     (rnemdType_ == rnemdKineticScale) ||
138     (rnemdType_ == rnemdKineticScaleVAM) ||
139     (rnemdType_ == rnemdKineticScaleAM)) {
140     outputTemp_ = true;
141     }
142     outputVx_ = false;
143 gezelter 1731 if (rnemdParams->haveOutputVx()) {
144     outputVx_ = rnemdParams->getOutputVx();
145 gezelter 1722 } else if ((rnemdType_ == rnemdPx) || (rnemdType_ == rnemdPxScale)) {
146     outputVx_ = true;
147     }
148     outputVy_ = false;
149 gezelter 1731 if (rnemdParams->haveOutputVy()) {
150     outputVy_ = rnemdParams->getOutputVy();
151 gezelter 1722 } else if ((rnemdType_ == rnemdPy) || (rnemdType_ == rnemdPyScale)) {
152     outputVy_ = true;
153     }
154 gezelter 1629 output3DTemp_ = false;
155 gezelter 1731 if (rnemdParams->haveOutputXyzTemperature()) {
156     output3DTemp_ = rnemdParams->getOutputXyzTemperature();
157 gezelter 1629 }
158 gezelter 1722 outputRotTemp_ = false;
159 gezelter 1731 if (rnemdParams->haveOutputRotTemperature()) {
160     outputRotTemp_ = rnemdParams->getOutputRotTemperature();
161 gezelter 1722 }
162 jmarr 1728 // James put this in.
163     outputDen_ = false;
164 gezelter 1731 if (rnemdParams->haveOutputDen()) {
165     outputDen_ = rnemdParams->getOutputDen();
166 jmarr 1728 }
167     outputAh_ = false;
168 gezelter 1731 if (rnemdParams->haveOutputAh()) {
169     outputAh_ = rnemdParams->getOutputAh();
170 jmarr 1728 }
171     outputVz_ = false;
172 gezelter 1731 if (rnemdParams->haveOutputVz()) {
173     outputVz_ = rnemdParams->getOutputVz();
174 jmarr 1728 } else if ((rnemdType_ == rnemdPz) || (rnemdType_ == rnemdPzScale)) {
175     outputVz_ = true;
176     }
177    
178 skuang 1330
179 skuang 1368 #ifdef IS_MPI
180     if (worldRank == 0) {
181     #endif
182    
183 gezelter 1722 //may have rnemdWriter separately
184 gezelter 1629 string rnemdFileName;
185 gezelter 1722
186     if (outputTemp_) {
187 skuang 1368 rnemdFileName = "temperature.log";
188 gezelter 1722 tempLog_.open(rnemdFileName.c_str());
189 skuang 1368 }
190 gezelter 1722 if (outputVx_) {
191     rnemdFileName = "velocityX.log";
192     vxzLog_.open(rnemdFileName.c_str());
193     }
194     if (outputVy_) {
195     rnemdFileName = "velocityY.log";
196     vyzLog_.open(rnemdFileName.c_str());
197     }
198 skuang 1368
199 gezelter 1629 if (output3DTemp_) {
200 gezelter 1722 rnemdFileName = "temperatureX.log";
201     xTempLog_.open(rnemdFileName.c_str());
202     rnemdFileName = "temperatureY.log";
203     yTempLog_.open(rnemdFileName.c_str());
204     rnemdFileName = "temperatureZ.log";
205     zTempLog_.open(rnemdFileName.c_str());
206 gezelter 1629 }
207 gezelter 1722 if (outputRotTemp_) {
208     rnemdFileName = "temperatureR.log";
209     rotTempLog_.open(rnemdFileName.c_str());
210     }
211 jmarr 1728
212     //James put this in
213     if (outputDen_) {
214     rnemdFileName = "Density.log";
215     denLog_.open(rnemdFileName.c_str());
216     }
217     if (outputAh_) {
218     rnemdFileName = "Ah.log";
219     AhLog_.open(rnemdFileName.c_str());
220     }
221     if (outputVz_) {
222     rnemdFileName = "velocityZ.log";
223     vzzLog_.open(rnemdFileName.c_str());
224     }
225     logFrameCount_ = 0;
226 skuang 1368 #ifdef IS_MPI
227     }
228     #endif
229    
230 gezelter 1731 set_RNEMD_exchange_time(rnemdParams->getExchangeTime());
231     set_RNEMD_nBins(rnemdParams->getNbins());
232 skuang 1368 midBin_ = nBins_ / 2;
233 gezelter 1731 if (rnemdParams->haveBinShift()) {
234     if (rnemdParams->getBinShift()) {
235 gezelter 1629 zShift_ = 0.5 / (RealType)(nBins_);
236     } else {
237     zShift_ = 0.0;
238     }
239     } else {
240     zShift_ = 0.0;
241     }
242 gezelter 1722 //cerr << "I shift slabs by " << zShift_ << " Lz\n";
243     //shift slabs by half slab width, maybe useful in heterogeneous systems
244     //set to 0.0 if not using it; N/A in status output yet
245 gezelter 1731 if (rnemdParams->haveLogWidth()) {
246     set_RNEMD_logWidth(rnemdParams->getLogWidth());
247 gezelter 1722 /*arbitary rnemdLogWidth_, no checking;
248     if (rnemdLogWidth_ != nBins_ && rnemdLogWidth_ != midBin_ + 1) {
249 gezelter 1629 cerr << "WARNING! RNEMD_logWidth has abnormal value!\n";
250     cerr << "Automaically set back to default.\n";
251 skuang 1368 rnemdLogWidth_ = nBins_;
252 gezelter 1722 }*/
253 skuang 1368 } else {
254 gezelter 1629 set_RNEMD_logWidth(nBins_);
255 skuang 1368 }
256 gezelter 1722 tempHist_.resize(rnemdLogWidth_, 0.0);
257     tempCount_.resize(rnemdLogWidth_, 0);
258     pxzHist_.resize(rnemdLogWidth_, 0.0);
259     //vxzCount_.resize(rnemdLogWidth_, 0);
260     pyzHist_.resize(rnemdLogWidth_, 0.0);
261     //vyzCount_.resize(rnemdLogWidth_, 0);
262    
263     mHist_.resize(rnemdLogWidth_, 0.0);
264 skuang 1368 xTempHist_.resize(rnemdLogWidth_, 0.0);
265     yTempHist_.resize(rnemdLogWidth_, 0.0);
266     zTempHist_.resize(rnemdLogWidth_, 0.0);
267 gezelter 1629 xyzTempCount_.resize(rnemdLogWidth_, 0);
268 gezelter 1722 rotTempHist_.resize(rnemdLogWidth_, 0.0);
269     rotTempCount_.resize(rnemdLogWidth_, 0);
270 jmarr 1728 // James put this in
271     DenHist_.resize(rnemdLogWidth_, 0.0);
272     pzzHist_.resize(rnemdLogWidth_, 0.0);
273 skuang 1338
274 skuang 1368 set_RNEMD_exchange_total(0.0);
275 gezelter 1731 if (rnemdParams->haveTargetFlux()) {
276     set_RNEMD_target_flux(rnemdParams->getTargetFlux());
277 skuang 1368 } else {
278     set_RNEMD_target_flux(0.0);
279     }
280 gezelter 1731 if (rnemdParams->haveTargetJzKE()) {
281     set_RNEMD_target_JzKE(rnemdParams->getTargetJzKE());
282 gezelter 1722 } else {
283     set_RNEMD_target_JzKE(0.0);
284     }
285 gezelter 1731 if (rnemdParams->haveTargetJzpx()) {
286     set_RNEMD_target_jzpx(rnemdParams->getTargetJzpx());
287 gezelter 1722 } else {
288     set_RNEMD_target_jzpx(0.0);
289     }
290     jzp_.x() = targetJzpx_;
291     njzp_.x() = -targetJzpx_;
292 gezelter 1731 if (rnemdParams->haveTargetJzpy()) {
293     set_RNEMD_target_jzpy(rnemdParams->getTargetJzpy());
294 gezelter 1722 } else {
295     set_RNEMD_target_jzpy(0.0);
296     }
297     jzp_.y() = targetJzpy_;
298     njzp_.y() = -targetJzpy_;
299 gezelter 1731 if (rnemdParams->haveTargetJzpz()) {
300     set_RNEMD_target_jzpz(rnemdParams->getTargetJzpz());
301 gezelter 1722 } else {
302     set_RNEMD_target_jzpz(0.0);
303     }
304     jzp_.z() = targetJzpz_;
305     njzp_.z() = -targetJzpz_;
306 skuang 1368
307 gezelter 1329 #ifndef IS_MPI
308     if (simParams->haveSeed()) {
309     seedValue = simParams->getSeed();
310     randNumGen_ = new SeqRandNumGen(seedValue);
311     }else {
312     randNumGen_ = new SeqRandNumGen();
313     }
314     #else
315     if (simParams->haveSeed()) {
316     seedValue = simParams->getSeed();
317     randNumGen_ = new ParallelRandNumGen(seedValue);
318     }else {
319     randNumGen_ = new ParallelRandNumGen();
320     }
321     #endif
322     }
323    
324     RNEMD::~RNEMD() {
325     delete randNumGen_;
326 gezelter 1396
327 skuang 1368 #ifdef IS_MPI
328     if (worldRank == 0) {
329     #endif
330 gezelter 1629
331     sprintf(painCave.errMsg,
332     "RNEMD: total failed trials: %d\n",
333     failTrialCount_);
334     painCave.isFatal = 0;
335     painCave.severity = OPENMD_INFO;
336     simError();
337 jmarr 1728
338 gezelter 1722 if (outputTemp_) tempLog_.close();
339     if (outputVx_) vxzLog_.close();
340     if (outputVy_) vyzLog_.close();
341    
342     if (rnemdType_ == rnemdKineticScale || rnemdType_ == rnemdPxScale ||
343     rnemdType_ == rnemdPyScale) {
344 gezelter 1629 sprintf(painCave.errMsg,
345     "RNEMD: total root-checking warnings: %d\n",
346     failRootCount_);
347     painCave.isFatal = 0;
348     painCave.severity = OPENMD_INFO;
349     simError();
350     }
351     if (output3DTemp_) {
352 skuang 1368 xTempLog_.close();
353     yTempLog_.close();
354     zTempLog_.close();
355     }
356 gezelter 1722 if (outputRotTemp_) rotTempLog_.close();
357 jmarr 1728 // James put this in
358     if (outputDen_) denLog_.close();
359     if (outputAh_) AhLog_.close();
360     if (outputVz_) vzzLog_.close();
361    
362 skuang 1368 #ifdef IS_MPI
363     }
364     #endif
365 gezelter 1329 }
366 skuang 1330
367 gezelter 1329 void RNEMD::doSwap() {
368 gezelter 1331
369 gezelter 1332 Snapshot* currentSnap_ = info_->getSnapshotManager()->getCurrentSnapshot();
370     Mat3x3d hmat = currentSnap_->getHmat();
371    
372 gezelter 1331 seleMan_.setSelectionSet(evaluator_.evaluate());
373    
374 gezelter 1333 int selei;
375 gezelter 1331 StuntDouble* sd;
376 gezelter 1333 int idx;
377 gezelter 1331
378 skuang 1338 RealType min_val;
379     bool min_found = false;
380     StuntDouble* min_sd;
381    
382     RealType max_val;
383     bool max_found = false;
384     StuntDouble* max_sd;
385    
386 gezelter 1333 for (sd = seleMan_.beginSelected(selei); sd != NULL;
387     sd = seleMan_.nextSelected(selei)) {
388 gezelter 1332
389 gezelter 1333 idx = sd->getLocalIndex();
390    
391 gezelter 1331 Vector3d pos = sd->getPos();
392 gezelter 1332
393     // wrap the stuntdouble's position back into the box:
394    
395 gezelter 1331 if (usePeriodicBoundaryConditions_)
396 gezelter 1332 currentSnap_->wrapVector(pos);
397    
398     // which bin is this stuntdouble in?
399 gezelter 1334 // wrapped positions are in the range [-0.5*hmat(2,2), +0.5*hmat(2,2)]
400 gezelter 1332
401 gezelter 1629 int binNo = int(nBins_ * (pos.z() / hmat(2,2) + zShift_ + 0.5)) % nBins_;
402 gezelter 1332
403 gezelter 1333
404 gezelter 1332 // if we're in bin 0 or the middleBin
405 skuang 1368 if (binNo == 0 || binNo == midBin_) {
406 gezelter 1332
407     RealType mass = sd->getMass();
408     Vector3d vel = sd->getVel();
409     RealType value;
410    
411     switch(rnemdType_) {
412 skuang 1368 case rnemdKineticSwap :
413 gezelter 1332
414 gezelter 1722 value = mass * vel.lengthSquare();
415    
416     if (sd->isDirectional()) {
417 gezelter 1332 Vector3d angMom = sd->getJ();
418     Mat3x3d I = sd->getI();
419    
420     if (sd->isLinear()) {
421 gezelter 1722 int i = sd->linearAxis();
422     int j = (i + 1) % 3;
423     int k = (i + 2) % 3;
424     value += angMom[j] * angMom[j] / I(j, j) +
425     angMom[k] * angMom[k] / I(k, k);
426 gezelter 1332 } else {
427 gezelter 1722 value += angMom[0]*angMom[0]/I(0, 0)
428     + angMom[1]*angMom[1]/I(1, 1)
429     + angMom[2]*angMom[2]/I(2, 2);
430 gezelter 1332 }
431 gezelter 1722 } //angular momenta exchange enabled
432     //energyConvert temporarily disabled
433 skuang 1368 //make exchangeSum_ comparable between swap & scale
434 gezelter 1390 //value = value * 0.5 / PhysicalConstants::energyConvert;
435 skuang 1368 value *= 0.5;
436 gezelter 1332 break;
437     case rnemdPx :
438     value = mass * vel[0];
439     break;
440     case rnemdPy :
441     value = mass * vel[1];
442     break;
443     case rnemdPz :
444     value = mass * vel[2];
445     break;
446     default :
447     break;
448     }
449    
450 skuang 1338 if (binNo == 0) {
451     if (!min_found) {
452     min_val = value;
453     min_sd = sd;
454     min_found = true;
455     } else {
456     if (min_val > value) {
457     min_val = value;
458     min_sd = sd;
459     }
460     }
461 skuang 1368 } else { //midBin_
462 skuang 1338 if (!max_found) {
463     max_val = value;
464     max_sd = sd;
465     max_found = true;
466     } else {
467     if (max_val < value) {
468     max_val = value;
469     max_sd = sd;
470     }
471     }
472     }
473 gezelter 1332 }
474 gezelter 1331 }
475 skuang 1341
476 gezelter 1350 #ifdef IS_MPI
477     int nProc, worldRank;
478 skuang 1338
479 gezelter 1350 nProc = MPI::COMM_WORLD.Get_size();
480     worldRank = MPI::COMM_WORLD.Get_rank();
481    
482     bool my_min_found = min_found;
483     bool my_max_found = max_found;
484    
485     // Even if we didn't find a minimum, did someone else?
486 gezelter 1629 MPI::COMM_WORLD.Allreduce(&my_min_found, &min_found, 1, MPI::BOOL, MPI::LOR);
487 gezelter 1350 // Even if we didn't find a maximum, did someone else?
488 gezelter 1629 MPI::COMM_WORLD.Allreduce(&my_max_found, &max_found, 1, MPI::BOOL, MPI::LOR);
489 gezelter 1722 #endif
490    
491     if (max_found && min_found) {
492    
493     #ifdef IS_MPI
494     struct {
495     RealType val;
496     int rank;
497     } max_vals, min_vals;
498 jmarr 1728
499 gezelter 1722 if (my_min_found) {
500 gezelter 1350 min_vals.val = min_val;
501 gezelter 1722 } else {
502 gezelter 1350 min_vals.val = HONKING_LARGE_VALUE;
503 gezelter 1722 }
504 gezelter 1350 min_vals.rank = worldRank;
505    
506     // Who had the minimum?
507     MPI::COMM_WORLD.Allreduce(&min_vals, &min_vals,
508     1, MPI::REALTYPE_INT, MPI::MINLOC);
509     min_val = min_vals.val;
510    
511 gezelter 1722 if (my_max_found) {
512 gezelter 1350 max_vals.val = max_val;
513 gezelter 1722 } else {
514 gezelter 1350 max_vals.val = -HONKING_LARGE_VALUE;
515 gezelter 1722 }
516 gezelter 1350 max_vals.rank = worldRank;
517    
518     // Who had the maximum?
519     MPI::COMM_WORLD.Allreduce(&max_vals, &max_vals,
520     1, MPI::REALTYPE_INT, MPI::MAXLOC);
521     max_val = max_vals.val;
522     #endif
523 gezelter 1722
524 gezelter 1629 if (min_val < max_val) {
525 gezelter 1722
526 gezelter 1350 #ifdef IS_MPI
527     if (max_vals.rank == worldRank && min_vals.rank == worldRank) {
528     // I have both maximum and minimum, so proceed like a single
529     // processor version:
530     #endif
531 gezelter 1722
532 gezelter 1350 Vector3d min_vel = min_sd->getVel();
533     Vector3d max_vel = max_sd->getVel();
534     RealType temp_vel;
535    
536     switch(rnemdType_) {
537 skuang 1368 case rnemdKineticSwap :
538 gezelter 1350 min_sd->setVel(max_vel);
539     max_sd->setVel(min_vel);
540 gezelter 1722 if (min_sd->isDirectional() && max_sd->isDirectional()) {
541 gezelter 1350 Vector3d min_angMom = min_sd->getJ();
542     Vector3d max_angMom = max_sd->getJ();
543     min_sd->setJ(max_angMom);
544     max_sd->setJ(min_angMom);
545 gezelter 1722 }//angular momenta exchange enabled
546     //assumes same rigid body identity
547 gezelter 1350 break;
548     case rnemdPx :
549     temp_vel = min_vel.x();
550     min_vel.x() = max_vel.x();
551     max_vel.x() = temp_vel;
552     min_sd->setVel(min_vel);
553     max_sd->setVel(max_vel);
554     break;
555     case rnemdPy :
556     temp_vel = min_vel.y();
557     min_vel.y() = max_vel.y();
558     max_vel.y() = temp_vel;
559     min_sd->setVel(min_vel);
560     max_sd->setVel(max_vel);
561     break;
562     case rnemdPz :
563     temp_vel = min_vel.z();
564     min_vel.z() = max_vel.z();
565     max_vel.z() = temp_vel;
566     min_sd->setVel(min_vel);
567     max_sd->setVel(max_vel);
568     break;
569     default :
570     break;
571     }
572 gezelter 1722
573 gezelter 1350 #ifdef IS_MPI
574     // the rest of the cases only apply in parallel simulations:
575     } else if (max_vals.rank == worldRank) {
576     // I had the max, but not the minimum
577    
578     Vector3d min_vel;
579     Vector3d max_vel = max_sd->getVel();
580     MPI::Status status;
581 skuang 1341
582 gezelter 1350 // point-to-point swap of the velocity vector
583     MPI::COMM_WORLD.Sendrecv(max_vel.getArrayPointer(), 3, MPI::REALTYPE,
584     min_vals.rank, 0,
585     min_vel.getArrayPointer(), 3, MPI::REALTYPE,
586     min_vals.rank, 0, status);
587    
588     switch(rnemdType_) {
589 skuang 1368 case rnemdKineticSwap :
590 gezelter 1350 max_sd->setVel(min_vel);
591 gezelter 1722 //angular momenta exchange enabled
592 gezelter 1350 if (max_sd->isDirectional()) {
593     Vector3d min_angMom;
594     Vector3d max_angMom = max_sd->getJ();
595 gezelter 1629
596 gezelter 1350 // point-to-point swap of the angular momentum vector
597     MPI::COMM_WORLD.Sendrecv(max_angMom.getArrayPointer(), 3,
598     MPI::REALTYPE, min_vals.rank, 1,
599     min_angMom.getArrayPointer(), 3,
600     MPI::REALTYPE, min_vals.rank, 1,
601     status);
602 gezelter 1629
603 gezelter 1350 max_sd->setJ(min_angMom);
604 gezelter 1722 }
605 gezelter 1350 break;
606     case rnemdPx :
607     max_vel.x() = min_vel.x();
608     max_sd->setVel(max_vel);
609     break;
610     case rnemdPy :
611     max_vel.y() = min_vel.y();
612     max_sd->setVel(max_vel);
613     break;
614     case rnemdPz :
615     max_vel.z() = min_vel.z();
616     max_sd->setVel(max_vel);
617     break;
618     default :
619     break;
620 skuang 1341 }
621 gezelter 1350 } else if (min_vals.rank == worldRank) {
622     // I had the minimum but not the maximum:
623    
624     Vector3d max_vel;
625     Vector3d min_vel = min_sd->getVel();
626     MPI::Status status;
627    
628     // point-to-point swap of the velocity vector
629     MPI::COMM_WORLD.Sendrecv(min_vel.getArrayPointer(), 3, MPI::REALTYPE,
630     max_vals.rank, 0,
631     max_vel.getArrayPointer(), 3, MPI::REALTYPE,
632     max_vals.rank, 0, status);
633    
634     switch(rnemdType_) {
635 skuang 1368 case rnemdKineticSwap :
636 gezelter 1350 min_sd->setVel(max_vel);
637 gezelter 1722 //angular momenta exchange enabled
638 gezelter 1350 if (min_sd->isDirectional()) {
639     Vector3d min_angMom = min_sd->getJ();
640     Vector3d max_angMom;
641 gezelter 1629
642 gezelter 1350 // point-to-point swap of the angular momentum vector
643     MPI::COMM_WORLD.Sendrecv(min_angMom.getArrayPointer(), 3,
644     MPI::REALTYPE, max_vals.rank, 1,
645     max_angMom.getArrayPointer(), 3,
646     MPI::REALTYPE, max_vals.rank, 1,
647     status);
648 gezelter 1629
649 gezelter 1350 min_sd->setJ(max_angMom);
650     }
651     break;
652     case rnemdPx :
653     min_vel.x() = max_vel.x();
654     min_sd->setVel(min_vel);
655     break;
656     case rnemdPy :
657     min_vel.y() = max_vel.y();
658     min_sd->setVel(min_vel);
659     break;
660     case rnemdPz :
661     min_vel.z() = max_vel.z();
662     min_sd->setVel(min_vel);
663     break;
664     default :
665     break;
666     }
667     }
668     #endif
669     exchangeSum_ += max_val - min_val;
670 gezelter 1629 } else {
671     sprintf(painCave.errMsg,
672     "RNEMD: exchange NOT performed because min_val > max_val\n");
673     painCave.isFatal = 0;
674     painCave.severity = OPENMD_INFO;
675     simError();
676 skuang 1368 failTrialCount_++;
677 skuang 1338 }
678     } else {
679 gezelter 1629 sprintf(painCave.errMsg,
680 gezelter 1722 "RNEMD: exchange NOT performed because selected object\n"
681     "\tnot present in at least one of the two slabs.\n");
682 gezelter 1629 painCave.isFatal = 0;
683     painCave.severity = OPENMD_INFO;
684     simError();
685 skuang 1368 failTrialCount_++;
686 skuang 1338 }
687 gezelter 1350
688 skuang 1338 }
689 gezelter 1350
690 skuang 1368 void RNEMD::doScale() {
691 skuang 1338
692     Snapshot* currentSnap_ = info_->getSnapshotManager()->getCurrentSnapshot();
693     Mat3x3d hmat = currentSnap_->getHmat();
694    
695     seleMan_.setSelectionSet(evaluator_.evaluate());
696    
697     int selei;
698     StuntDouble* sd;
699     int idx;
700    
701 gezelter 1629 vector<StuntDouble*> hotBin, coldBin;
702 gezelter 1350
703 skuang 1368 RealType Phx = 0.0;
704     RealType Phy = 0.0;
705     RealType Phz = 0.0;
706     RealType Khx = 0.0;
707     RealType Khy = 0.0;
708     RealType Khz = 0.0;
709 gezelter 1722 RealType Khw = 0.0;
710 skuang 1368 RealType Pcx = 0.0;
711     RealType Pcy = 0.0;
712     RealType Pcz = 0.0;
713     RealType Kcx = 0.0;
714     RealType Kcy = 0.0;
715     RealType Kcz = 0.0;
716 gezelter 1722 RealType Kcw = 0.0;
717 skuang 1368
718 skuang 1338 for (sd = seleMan_.beginSelected(selei); sd != NULL;
719     sd = seleMan_.nextSelected(selei)) {
720 skuang 1368
721     idx = sd->getLocalIndex();
722    
723     Vector3d pos = sd->getPos();
724    
725     // wrap the stuntdouble's position back into the box:
726    
727     if (usePeriodicBoundaryConditions_)
728     currentSnap_->wrapVector(pos);
729    
730     // which bin is this stuntdouble in?
731     // wrapped positions are in the range [-0.5*hmat(2,2), +0.5*hmat(2,2)]
732    
733 gezelter 1629 int binNo = int(nBins_ * (pos.z() / hmat(2,2) + zShift_ + 0.5)) % nBins_;
734 skuang 1368
735     // if we're in bin 0 or the middleBin
736     if (binNo == 0 || binNo == midBin_) {
737    
738     RealType mass = sd->getMass();
739     Vector3d vel = sd->getVel();
740    
741     if (binNo == 0) {
742     hotBin.push_back(sd);
743     Phx += mass * vel.x();
744     Phy += mass * vel.y();
745     Phz += mass * vel.z();
746     Khx += mass * vel.x() * vel.x();
747     Khy += mass * vel.y() * vel.y();
748     Khz += mass * vel.z() * vel.z();
749 gezelter 1722 //if (rnemdType_ == rnemdKineticScaleVAM) {
750     if (sd->isDirectional()) {
751     Vector3d angMom = sd->getJ();
752     Mat3x3d I = sd->getI();
753     if (sd->isLinear()) {
754     int i = sd->linearAxis();
755     int j = (i + 1) % 3;
756     int k = (i + 2) % 3;
757     Khw += angMom[j] * angMom[j] / I(j, j) +
758     angMom[k] * angMom[k] / I(k, k);
759     } else {
760     Khw += angMom[0]*angMom[0]/I(0, 0)
761     + angMom[1]*angMom[1]/I(1, 1)
762     + angMom[2]*angMom[2]/I(2, 2);
763     }
764     }
765     //}
766 skuang 1368 } else { //midBin_
767     coldBin.push_back(sd);
768     Pcx += mass * vel.x();
769     Pcy += mass * vel.y();
770     Pcz += mass * vel.z();
771     Kcx += mass * vel.x() * vel.x();
772     Kcy += mass * vel.y() * vel.y();
773     Kcz += mass * vel.z() * vel.z();
774 gezelter 1722 //if (rnemdType_ == rnemdKineticScaleVAM) {
775     if (sd->isDirectional()) {
776     Vector3d angMom = sd->getJ();
777     Mat3x3d I = sd->getI();
778     if (sd->isLinear()) {
779     int i = sd->linearAxis();
780     int j = (i + 1) % 3;
781     int k = (i + 2) % 3;
782     Kcw += angMom[j] * angMom[j] / I(j, j) +
783     angMom[k] * angMom[k] / I(k, k);
784     } else {
785     Kcw += angMom[0]*angMom[0]/I(0, 0)
786     + angMom[1]*angMom[1]/I(1, 1)
787     + angMom[2]*angMom[2]/I(2, 2);
788     }
789     }
790     //}
791 skuang 1368 }
792     }
793     }
794 gezelter 1722
795 skuang 1368 Khx *= 0.5;
796     Khy *= 0.5;
797     Khz *= 0.5;
798 gezelter 1722 Khw *= 0.5;
799 skuang 1368 Kcx *= 0.5;
800     Kcy *= 0.5;
801     Kcz *= 0.5;
802 gezelter 1722 Kcw *= 0.5;
803 skuang 1368
804 jmarr 1728 // std::cerr << "Khx= " << Khx << "\tKhy= " << Khy << "\tKhz= " << Khz
805     // << "\tKhw= " << Khw << "\tKcx= " << Kcx << "\tKcy= " << Kcy
806     // << "\tKcz= " << Kcz << "\tKcw= " << Kcw << "\n";
807     // std::cerr << "Phx= " << Phx << "\tPhy= " << Phy << "\tPhz= " << Phz
808     // << "\tPcx= " << Pcx << "\tPcy= " << Pcy << "\tPcz= " <<Pcz<<"\n";
809 gezelter 1722
810 skuang 1368 #ifdef IS_MPI
811     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &Phx, 1, MPI::REALTYPE, MPI::SUM);
812     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &Phy, 1, MPI::REALTYPE, MPI::SUM);
813     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &Phz, 1, MPI::REALTYPE, MPI::SUM);
814     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &Pcx, 1, MPI::REALTYPE, MPI::SUM);
815     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &Pcy, 1, MPI::REALTYPE, MPI::SUM);
816     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &Pcz, 1, MPI::REALTYPE, MPI::SUM);
817    
818     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &Khx, 1, MPI::REALTYPE, MPI::SUM);
819     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &Khy, 1, MPI::REALTYPE, MPI::SUM);
820     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &Khz, 1, MPI::REALTYPE, MPI::SUM);
821 gezelter 1722 MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &Khw, 1, MPI::REALTYPE, MPI::SUM);
822    
823 skuang 1368 MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &Kcx, 1, MPI::REALTYPE, MPI::SUM);
824     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &Kcy, 1, MPI::REALTYPE, MPI::SUM);
825     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &Kcz, 1, MPI::REALTYPE, MPI::SUM);
826 gezelter 1722 MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &Kcw, 1, MPI::REALTYPE, MPI::SUM);
827 skuang 1368 #endif
828    
829 gezelter 1722 //solve coldBin coeff's first
830 skuang 1368 RealType px = Pcx / Phx;
831     RealType py = Pcy / Phy;
832     RealType pz = Pcz / Phz;
833 gezelter 1722 RealType c, x, y, z;
834     bool successfulScale = false;
835     if ((rnemdType_ == rnemdKineticScaleVAM) ||
836     (rnemdType_ == rnemdKineticScaleAM)) {
837     //may need sanity check Khw & Kcw > 0
838 skuang 1368
839 gezelter 1722 if (rnemdType_ == rnemdKineticScaleVAM) {
840     c = 1.0 - targetFlux_ / (Kcx + Kcy + Kcz + Kcw);
841     } else {
842     c = 1.0 - targetFlux_ / Kcw;
843     }
844 skuang 1368
845 gezelter 1722 if ((c > 0.81) && (c < 1.21)) {//restrict scaling coefficients
846     c = sqrt(c);
847     std::cerr << "cold slab scaling coefficient: " << c << endl;
848     //now convert to hotBin coefficient
849     RealType w = 0.0;
850     if (rnemdType_ == rnemdKineticScaleVAM) {
851     x = 1.0 + px * (1.0 - c);
852     y = 1.0 + py * (1.0 - c);
853     z = 1.0 + pz * (1.0 - c);
854     /* more complicated way
855     w = 1.0 + (Kcw - Kcw * c * c - (c * c * (Kcx + Kcy + Kcz
856     + Khx * px * px + Khy * py * py + Khz * pz * pz)
857     - 2.0 * c * (Khx * px * (1.0 + px) + Khy * py * (1.0 + py)
858     + Khz * pz * (1.0 + pz)) + Khx * px * (2.0 + px)
859     + Khy * py * (2.0 + py) + Khz * pz * (2.0 + pz)
860     - Kcx - Kcy - Kcz)) / Khw; the following is simpler
861     */
862     if ((fabs(x - 1.0) < 0.1) && (fabs(y - 1.0) < 0.1) &&
863     (fabs(z - 1.0) < 0.1)) {
864     w = 1.0 + (targetFlux_ + Khx * (1.0 - x * x) + Khy * (1.0 - y * y)
865     + Khz * (1.0 - z * z)) / Khw;
866     }//no need to calculate w if x, y or z is out of range
867     } else {
868     w = 1.0 + targetFlux_ / Khw;
869     }
870     if ((w > 0.81) && (w < 1.21)) {//restrict scaling coefficients
871     //if w is in the right range, so should be x, y, z.
872     vector<StuntDouble*>::iterator sdi;
873     Vector3d vel;
874     for (sdi = coldBin.begin(); sdi != coldBin.end(); sdi++) {
875     if (rnemdType_ == rnemdKineticScaleVAM) {
876     vel = (*sdi)->getVel() * c;
877     //vel.x() *= c;
878     //vel.y() *= c;
879     //vel.z() *= c;
880     (*sdi)->setVel(vel);
881     }
882     if ((*sdi)->isDirectional()) {
883     Vector3d angMom = (*sdi)->getJ() * c;
884     //angMom[0] *= c;
885     //angMom[1] *= c;
886     //angMom[2] *= c;
887     (*sdi)->setJ(angMom);
888     }
889     }
890     w = sqrt(w);
891     std::cerr << "xh= " << x << "\tyh= " << y << "\tzh= " << z
892     << "\twh= " << w << endl;
893     for (sdi = hotBin.begin(); sdi != hotBin.end(); sdi++) {
894     if (rnemdType_ == rnemdKineticScaleVAM) {
895     vel = (*sdi)->getVel();
896     vel.x() *= x;
897     vel.y() *= y;
898     vel.z() *= z;
899     (*sdi)->setVel(vel);
900     }
901     if ((*sdi)->isDirectional()) {
902     Vector3d angMom = (*sdi)->getJ() * w;
903     //angMom[0] *= w;
904     //angMom[1] *= w;
905     //angMom[2] *= w;
906     (*sdi)->setJ(angMom);
907     }
908     }
909     successfulScale = true;
910     exchangeSum_ += targetFlux_;
911     }
912 skuang 1368 }
913 gezelter 1722 } else {
914     RealType a000, a110, c0, a001, a111, b01, b11, c1;
915     switch(rnemdType_) {
916     case rnemdKineticScale :
917     /* used hotBin coeff's & only scale x & y dimensions
918     RealType px = Phx / Pcx;
919     RealType py = Phy / Pcy;
920     a110 = Khy;
921     c0 = - Khx - Khy - targetFlux_;
922     a000 = Khx;
923     a111 = Kcy * py * py;
924     b11 = -2.0 * Kcy * py * (1.0 + py);
925     c1 = Kcy * py * (2.0 + py) + Kcx * px * ( 2.0 + px) + targetFlux_;
926     b01 = -2.0 * Kcx * px * (1.0 + px);
927     a001 = Kcx * px * px;
928     */
929     //scale all three dimensions, let c_x = c_y
930     a000 = Kcx + Kcy;
931     a110 = Kcz;
932     c0 = targetFlux_ - Kcx - Kcy - Kcz;
933     a001 = Khx * px * px + Khy * py * py;
934     a111 = Khz * pz * pz;
935     b01 = -2.0 * (Khx * px * (1.0 + px) + Khy * py * (1.0 + py));
936     b11 = -2.0 * Khz * pz * (1.0 + pz);
937     c1 = Khx * px * (2.0 + px) + Khy * py * (2.0 + py)
938     + Khz * pz * (2.0 + pz) - targetFlux_;
939     break;
940     case rnemdPxScale :
941     c = 1 - targetFlux_ / Pcx;
942     a000 = Kcy;
943     a110 = Kcz;
944     c0 = Kcx * c * c - Kcx - Kcy - Kcz;
945     a001 = py * py * Khy;
946     a111 = pz * pz * Khz;
947     b01 = -2.0 * Khy * py * (1.0 + py);
948     b11 = -2.0 * Khz * pz * (1.0 + pz);
949     c1 = Khy * py * (2.0 + py) + Khz * pz * (2.0 + pz)
950     + Khx * (fastpow(c * px - px - 1.0, 2) - 1.0);
951     break;
952     case rnemdPyScale :
953     c = 1 - targetFlux_ / Pcy;
954     a000 = Kcx;
955     a110 = Kcz;
956     c0 = Kcy * c * c - Kcx - Kcy - Kcz;
957     a001 = px * px * Khx;
958     a111 = pz * pz * Khz;
959     b01 = -2.0 * Khx * px * (1.0 + px);
960     b11 = -2.0 * Khz * pz * (1.0 + pz);
961     c1 = Khx * px * (2.0 + px) + Khz * pz * (2.0 + pz)
962     + Khy * (fastpow(c * py - py - 1.0, 2) - 1.0);
963     break;
964     case rnemdPzScale ://we don't really do this, do we?
965     c = 1 - targetFlux_ / Pcz;
966     a000 = Kcx;
967     a110 = Kcy;
968     c0 = Kcz * c * c - Kcx - Kcy - Kcz;
969     a001 = px * px * Khx;
970     a111 = py * py * Khy;
971     b01 = -2.0 * Khx * px * (1.0 + px);
972     b11 = -2.0 * Khy * py * (1.0 + py);
973     c1 = Khx * px * (2.0 + px) + Khy * py * (2.0 + py)
974     + Khz * (fastpow(c * pz - pz - 1.0, 2) - 1.0);
975     break;
976     default :
977     break;
978 skuang 1368 }
979 gezelter 1722
980     RealType v1 = a000 * a111 - a001 * a110;
981     RealType v2 = a000 * b01;
982     RealType v3 = a000 * b11;
983     RealType v4 = a000 * c1 - a001 * c0;
984     RealType v8 = a110 * b01;
985     RealType v10 = - b01 * c0;
986    
987     RealType u0 = v2 * v10 - v4 * v4;
988     RealType u1 = -2.0 * v3 * v4;
989     RealType u2 = -v2 * v8 - v3 * v3 - 2.0 * v1 * v4;
990     RealType u3 = -2.0 * v1 * v3;
991     RealType u4 = - v1 * v1;
992     //rescale coefficients
993     RealType maxAbs = fabs(u0);
994     if (maxAbs < fabs(u1)) maxAbs = fabs(u1);
995     if (maxAbs < fabs(u2)) maxAbs = fabs(u2);
996     if (maxAbs < fabs(u3)) maxAbs = fabs(u3);
997     if (maxAbs < fabs(u4)) maxAbs = fabs(u4);
998     u0 /= maxAbs;
999     u1 /= maxAbs;
1000     u2 /= maxAbs;
1001     u3 /= maxAbs;
1002     u4 /= maxAbs;
1003     //max_element(start, end) is also available.
1004     Polynomial<RealType> poly; //same as DoublePolynomial poly;
1005     poly.setCoefficient(4, u4);
1006     poly.setCoefficient(3, u3);
1007     poly.setCoefficient(2, u2);
1008     poly.setCoefficient(1, u1);
1009     poly.setCoefficient(0, u0);
1010     vector<RealType> realRoots = poly.FindRealRoots();
1011    
1012     vector<RealType>::iterator ri;
1013     RealType r1, r2, alpha0;
1014     vector<pair<RealType,RealType> > rps;
1015     for (ri = realRoots.begin(); ri !=realRoots.end(); ri++) {
1016     r2 = *ri;
1017     //check if FindRealRoots() give the right answer
1018     if ( fabs(u0 + r2 * (u1 + r2 * (u2 + r2 * (u3 + r2 * u4)))) > 1e-6 ) {
1019     sprintf(painCave.errMsg,
1020     "RNEMD Warning: polynomial solve seems to have an error!");
1021     painCave.isFatal = 0;
1022     simError();
1023     failRootCount_++;
1024     }
1025     //might not be useful w/o rescaling coefficients
1026     alpha0 = -c0 - a110 * r2 * r2;
1027     if (alpha0 >= 0.0) {
1028     r1 = sqrt(alpha0 / a000);
1029     if (fabs(c1 + r1 * (b01 + r1 * a001) + r2 * (b11 + r2 * a111))
1030     < 1e-6)
1031     { rps.push_back(make_pair(r1, r2)); }
1032     if (r1 > 1e-6) { //r1 non-negative
1033     r1 = -r1;
1034     if (fabs(c1 + r1 * (b01 + r1 * a001) + r2 * (b11 + r2 * a111))
1035     < 1e-6)
1036     { rps.push_back(make_pair(r1, r2)); }
1037     }
1038     }
1039 skuang 1368 }
1040 gezelter 1722 // Consider combining together the solving pair part w/ the searching
1041     // best solution part so that we don't need the pairs vector
1042     if (!rps.empty()) {
1043     RealType smallestDiff = HONKING_LARGE_VALUE;
1044     RealType diff;
1045     pair<RealType,RealType> bestPair = make_pair(1.0, 1.0);
1046     vector<pair<RealType,RealType> >::iterator rpi;
1047     for (rpi = rps.begin(); rpi != rps.end(); rpi++) {
1048     r1 = (*rpi).first;
1049     r2 = (*rpi).second;
1050     switch(rnemdType_) {
1051     case rnemdKineticScale :
1052     diff = fastpow(1.0 - r1, 2) + fastpow(1.0 - r2, 2)
1053     + fastpow(r1 * r1 / r2 / r2 - Kcz/Kcx, 2)
1054     + fastpow(r1 * r1 / r2 / r2 - Kcz/Kcy, 2);
1055     break;
1056     case rnemdPxScale :
1057     diff = fastpow(1.0 - r1, 2) + fastpow(1.0 - r2, 2)
1058     + fastpow(r1 * r1 / r2 / r2 - Kcz/Kcy, 2);
1059     break;
1060     case rnemdPyScale :
1061     diff = fastpow(1.0 - r1, 2) + fastpow(1.0 - r2, 2)
1062     + fastpow(r1 * r1 / r2 / r2 - Kcz/Kcx, 2);
1063     break;
1064     case rnemdPzScale :
1065     diff = fastpow(1.0 - r1, 2) + fastpow(1.0 - r2, 2)
1066     + fastpow(r1 * r1 / r2 / r2 - Kcy/Kcx, 2);
1067     default :
1068     break;
1069     }
1070     if (diff < smallestDiff) {
1071     smallestDiff = diff;
1072     bestPair = *rpi;
1073     }
1074     }
1075 skuang 1368 #ifdef IS_MPI
1076 gezelter 1722 if (worldRank == 0) {
1077 skuang 1368 #endif
1078 gezelter 1722 sprintf(painCave.errMsg,
1079     "RNEMD: roots r1= %lf\tr2 = %lf\n",
1080     bestPair.first, bestPair.second);
1081     painCave.isFatal = 0;
1082     painCave.severity = OPENMD_INFO;
1083     simError();
1084 skuang 1368 #ifdef IS_MPI
1085 gezelter 1722 }
1086 skuang 1368 #endif
1087 gezelter 1722
1088     switch(rnemdType_) {
1089     case rnemdKineticScale :
1090     x = bestPair.first;
1091     y = bestPair.first;
1092     z = bestPair.second;
1093     break;
1094     case rnemdPxScale :
1095     x = c;
1096     y = bestPair.first;
1097     z = bestPair.second;
1098     break;
1099     case rnemdPyScale :
1100     x = bestPair.first;
1101     y = c;
1102     z = bestPair.second;
1103     break;
1104     case rnemdPzScale :
1105     x = bestPair.first;
1106     y = bestPair.second;
1107     z = c;
1108     break;
1109     default :
1110     break;
1111     }
1112     vector<StuntDouble*>::iterator sdi;
1113     Vector3d vel;
1114     for (sdi = coldBin.begin(); sdi != coldBin.end(); sdi++) {
1115     vel = (*sdi)->getVel();
1116     vel.x() *= x;
1117     vel.y() *= y;
1118     vel.z() *= z;
1119     (*sdi)->setVel(vel);
1120     }
1121     //convert to hotBin coefficient
1122     x = 1.0 + px * (1.0 - x);
1123     y = 1.0 + py * (1.0 - y);
1124     z = 1.0 + pz * (1.0 - z);
1125     for (sdi = hotBin.begin(); sdi != hotBin.end(); sdi++) {
1126     vel = (*sdi)->getVel();
1127     vel.x() *= x;
1128     vel.y() *= y;
1129     vel.z() *= z;
1130     (*sdi)->setVel(vel);
1131     }
1132     successfulScale = true;
1133     exchangeSum_ += targetFlux_;
1134 gezelter 1629 }
1135 gezelter 1722 }
1136     if (successfulScale != true) {
1137     sprintf(painCave.errMsg,
1138     "RNEMD: exchange NOT performed!\n");
1139     painCave.isFatal = 0;
1140     painCave.severity = OPENMD_INFO;
1141     simError();
1142     failTrialCount_++;
1143     }
1144     }
1145    
1146     void RNEMD::doShiftScale() {
1147    
1148     Snapshot* currentSnap_ = info_->getSnapshotManager()->getCurrentSnapshot();
1149 jmarr 1728 RealType time = currentSnap_->getTime();
1150 gezelter 1722 Mat3x3d hmat = currentSnap_->getHmat();
1151    
1152     seleMan_.setSelectionSet(evaluator_.evaluate());
1153    
1154     int selei;
1155     StuntDouble* sd;
1156     int idx;
1157    
1158     vector<StuntDouble*> hotBin, coldBin;
1159    
1160     Vector3d Ph(V3Zero);
1161     RealType Mh = 0.0;
1162     RealType Kh = 0.0;
1163     Vector3d Pc(V3Zero);
1164     RealType Mc = 0.0;
1165     RealType Kc = 0.0;
1166 jmarr 1728
1167 gezelter 1722
1168     for (sd = seleMan_.beginSelected(selei); sd != NULL;
1169     sd = seleMan_.nextSelected(selei)) {
1170    
1171     idx = sd->getLocalIndex();
1172    
1173     Vector3d pos = sd->getPos();
1174    
1175     // wrap the stuntdouble's position back into the box:
1176    
1177     if (usePeriodicBoundaryConditions_)
1178     currentSnap_->wrapVector(pos);
1179    
1180     // which bin is this stuntdouble in?
1181     // wrapped positions are in the range [-0.5*hmat(2,2), +0.5*hmat(2,2)]
1182    
1183     int binNo = int(nBins_ * (pos.z() / hmat(2,2) + zShift_ + 0.5)) % nBins_;
1184    
1185     // if we're in bin 0 or the middleBin
1186     if (binNo == 0 || binNo == midBin_) {
1187    
1188     RealType mass = sd->getMass();
1189     Vector3d vel = sd->getVel();
1190    
1191     if (binNo == 0) {
1192     hotBin.push_back(sd);
1193     //std::cerr << "before, velocity = " << vel << endl;
1194     Ph += mass * vel;
1195     //std::cerr << "after, velocity = " << vel << endl;
1196     Mh += mass;
1197     Kh += mass * vel.lengthSquare();
1198     if (rnemdType_ == rnemdShiftScaleVAM) {
1199     if (sd->isDirectional()) {
1200     Vector3d angMom = sd->getJ();
1201     Mat3x3d I = sd->getI();
1202     if (sd->isLinear()) {
1203     int i = sd->linearAxis();
1204     int j = (i + 1) % 3;
1205     int k = (i + 2) % 3;
1206     Kh += angMom[j] * angMom[j] / I(j, j) +
1207     angMom[k] * angMom[k] / I(k, k);
1208     } else {
1209     Kh += angMom[0] * angMom[0] / I(0, 0) +
1210     angMom[1] * angMom[1] / I(1, 1) +
1211     angMom[2] * angMom[2] / I(2, 2);
1212     }
1213     }
1214     }
1215     } else { //midBin_
1216     coldBin.push_back(sd);
1217     Pc += mass * vel;
1218     Mc += mass;
1219     Kc += mass * vel.lengthSquare();
1220     if (rnemdType_ == rnemdShiftScaleVAM) {
1221     if (sd->isDirectional()) {
1222     Vector3d angMom = sd->getJ();
1223     Mat3x3d I = sd->getI();
1224     if (sd->isLinear()) {
1225     int i = sd->linearAxis();
1226     int j = (i + 1) % 3;
1227     int k = (i + 2) % 3;
1228     Kc += angMom[j] * angMom[j] / I(j, j) +
1229     angMom[k] * angMom[k] / I(k, k);
1230     } else {
1231     Kc += angMom[0] * angMom[0] / I(0, 0) +
1232     angMom[1] * angMom[1] / I(1, 1) +
1233     angMom[2] * angMom[2] / I(2, 2);
1234     }
1235     }
1236     }
1237     }
1238 skuang 1368 }
1239 gezelter 1722 }
1240    
1241     Kh *= 0.5;
1242     Kc *= 0.5;
1243    
1244 jmarr 1728 // std::cerr << "Mh= " << Mh << "\tKh= " << Kh << "\tMc= " << Mc
1245     // << "\tKc= " << Kc << endl;
1246     // std::cerr << "Ph= " << Ph << "\tPc= " << Pc << endl;
1247    
1248 gezelter 1722 #ifdef IS_MPI
1249     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &Ph[0], 3, MPI::REALTYPE, MPI::SUM);
1250     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &Pc[0], 3, MPI::REALTYPE, MPI::SUM);
1251     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &Mh, 1, MPI::REALTYPE, MPI::SUM);
1252     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &Kh, 1, MPI::REALTYPE, MPI::SUM);
1253     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &Mc, 1, MPI::REALTYPE, MPI::SUM);
1254     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &Kc, 1, MPI::REALTYPE, MPI::SUM);
1255     #endif
1256    
1257     bool successfulExchange = false;
1258     if ((Mh > 0.0) && (Mc > 0.0)) {//both slabs are not empty
1259     Vector3d vc = Pc / Mc;
1260     Vector3d ac = njzp_ / Mc + vc;
1261 jmarr 1728 Vector3d acrec = njzp_ / Mc;
1262 gezelter 1722 RealType cNumerator = Kc - targetJzKE_ - 0.5 * Mc * ac.lengthSquare();
1263     if (cNumerator > 0.0) {
1264     RealType cDenominator = Kc - 0.5 * Mc * vc.lengthSquare();
1265     if (cDenominator > 0.0) {
1266     RealType c = sqrt(cNumerator / cDenominator);
1267     if ((c > 0.9) && (c < 1.1)) {//restrict scaling coefficients
1268     Vector3d vh = Ph / Mh;
1269     Vector3d ah = jzp_ / Mh + vh;
1270 jmarr 1728 Vector3d ahrec = jzp_ / Mh;
1271 gezelter 1722 RealType hNumerator = Kh + targetJzKE_
1272     - 0.5 * Mh * ah.lengthSquare();
1273     if (hNumerator > 0.0) {
1274     RealType hDenominator = Kh - 0.5 * Mh * vh.lengthSquare();
1275     if (hDenominator > 0.0) {
1276     RealType h = sqrt(hNumerator / hDenominator);
1277     if ((h > 0.9) && (h < 1.1)) {
1278 jmarr 1728 // std::cerr << "cold slab scaling coefficient: " << c << "\n";
1279     // std::cerr << "hot slab scaling coefficient: " << h << "\n";
1280 gezelter 1722 vector<StuntDouble*>::iterator sdi;
1281     Vector3d vel;
1282     for (sdi = coldBin.begin(); sdi != coldBin.end(); sdi++) {
1283     //vel = (*sdi)->getVel();
1284     vel = ((*sdi)->getVel() - vc) * c + ac;
1285     (*sdi)->setVel(vel);
1286     if (rnemdType_ == rnemdShiftScaleVAM) {
1287     if ((*sdi)->isDirectional()) {
1288     Vector3d angMom = (*sdi)->getJ() * c;
1289     (*sdi)->setJ(angMom);
1290     }
1291     }
1292     }
1293     for (sdi = hotBin.begin(); sdi != hotBin.end(); sdi++) {
1294     //vel = (*sdi)->getVel();
1295     vel = ((*sdi)->getVel() - vh) * h + ah;
1296     (*sdi)->setVel(vel);
1297     if (rnemdType_ == rnemdShiftScaleVAM) {
1298     if ((*sdi)->isDirectional()) {
1299     Vector3d angMom = (*sdi)->getJ() * h;
1300     (*sdi)->setJ(angMom);
1301     }
1302     }
1303     }
1304     successfulExchange = true;
1305     exchangeSum_ += targetFlux_;
1306     // this is a redundant variable for doShiftScale() so that
1307     // RNEMD can output one exchange quantity needed in a job.
1308     // need a better way to do this.
1309 jmarr 1728 //cerr << "acx =" << ac.x() << "ahx =" << ah.x() << '\n';
1310     //cerr << "acy =" << ac.y() << "ahy =" << ah.y() << '\n';
1311     //cerr << "acz =" << ac.z() << "ahz =" << ah.z() << '\n';
1312     Asum_ += (ahrec.z() - acrec.z());
1313     Jsum_ += (jzp_.z()*((1/Mh)+(1/Mc)));
1314     AhCount_ = ahrec.z();
1315     if (outputAh_) {
1316     AhLog_ << time << " ";
1317     AhLog_ << AhCount_;
1318     AhLog_ << endl;
1319     }
1320 gezelter 1722 }
1321     }
1322     }
1323     }
1324     }
1325 skuang 1368 }
1326 gezelter 1722 }
1327     if (successfulExchange != true) {
1328 jmarr 1728 // sprintf(painCave.errMsg,
1329     // "RNEMD: exchange NOT performed!\n");
1330     // painCave.isFatal = 0;
1331     // painCave.severity = OPENMD_INFO;
1332     // simError();
1333 skuang 1368 failTrialCount_++;
1334     }
1335     }
1336    
1337     void RNEMD::doRNEMD() {
1338    
1339     switch(rnemdType_) {
1340     case rnemdKineticScale :
1341 gezelter 1722 case rnemdKineticScaleVAM :
1342     case rnemdKineticScaleAM :
1343 skuang 1368 case rnemdPxScale :
1344     case rnemdPyScale :
1345     case rnemdPzScale :
1346     doScale();
1347     break;
1348     case rnemdKineticSwap :
1349     case rnemdPx :
1350     case rnemdPy :
1351     case rnemdPz :
1352     doSwap();
1353     break;
1354 gezelter 1722 case rnemdShiftScaleV :
1355     case rnemdShiftScaleVAM :
1356     doShiftScale();
1357     break;
1358 skuang 1368 case rnemdUnknown :
1359     default :
1360     break;
1361     }
1362     }
1363    
1364     void RNEMD::collectData() {
1365    
1366     Snapshot* currentSnap_ = info_->getSnapshotManager()->getCurrentSnapshot();
1367     Mat3x3d hmat = currentSnap_->getHmat();
1368    
1369     seleMan_.setSelectionSet(evaluator_.evaluate());
1370    
1371     int selei;
1372     StuntDouble* sd;
1373     int idx;
1374    
1375 jmarr 1728 logFrameCount_++;
1376    
1377 gezelter 1629 // alternative approach, track all molecules instead of only those
1378     // selected for scaling/swapping:
1379     /*
1380     SimInfo::MoleculeIterator miter;
1381     vector<StuntDouble*>::iterator iiter;
1382     Molecule* mol;
1383 gezelter 1769 StuntDouble* sd;
1384 gezelter 1629 for (mol = info_->beginMolecule(miter); mol != NULL;
1385 jmarr 1728 mol = info_->nextMolecule(miter))
1386 gezelter 1769 sd is essentially sd
1387     for (sd = mol->beginIntegrableObject(iiter);
1388     sd != NULL;
1389     sd = mol->nextIntegrableObject(iiter))
1390 gezelter 1629 */
1391 skuang 1368 for (sd = seleMan_.beginSelected(selei); sd != NULL;
1392     sd = seleMan_.nextSelected(selei)) {
1393 skuang 1338
1394     idx = sd->getLocalIndex();
1395    
1396     Vector3d pos = sd->getPos();
1397    
1398     // wrap the stuntdouble's position back into the box:
1399    
1400     if (usePeriodicBoundaryConditions_)
1401     currentSnap_->wrapVector(pos);
1402    
1403     // which bin is this stuntdouble in?
1404     // wrapped positions are in the range [-0.5*hmat(2,2), +0.5*hmat(2,2)]
1405    
1406 gezelter 1629 int binNo = int(rnemdLogWidth_ * (pos.z() / hmat(2,2) + 0.5)) %
1407     rnemdLogWidth_;
1408 gezelter 1722 // no symmetrization allowed due to arbitary rnemdLogWidth_
1409 gezelter 1629 /*
1410 skuang 1368 if (rnemdLogWidth_ == midBin_ + 1)
1411     if (binNo > midBin_)
1412     binNo = nBins_ - binNo;
1413 gezelter 1629 */
1414 skuang 1338 RealType mass = sd->getMass();
1415 gezelter 1722 mHist_[binNo] += mass;
1416 skuang 1338 Vector3d vel = sd->getVel();
1417     RealType value;
1418 gezelter 1722 //RealType xVal, yVal, zVal;
1419 skuang 1338
1420 gezelter 1722 if (outputTemp_) {
1421     value = mass * vel.lengthSquare();
1422     tempCount_[binNo] += 3;
1423 skuang 1338 if (sd->isDirectional()) {
1424     Vector3d angMom = sd->getJ();
1425     Mat3x3d I = sd->getI();
1426     if (sd->isLinear()) {
1427     int i = sd->linearAxis();
1428     int j = (i + 1) % 3;
1429     int k = (i + 2) % 3;
1430     value += angMom[j] * angMom[j] / I(j, j) +
1431     angMom[k] * angMom[k] / I(k, k);
1432 gezelter 1722 tempCount_[binNo] +=2;
1433 skuang 1341 } else {
1434 gezelter 1722 value += angMom[0] * angMom[0] / I(0, 0) +
1435     angMom[1]*angMom[1]/I(1, 1) +
1436     angMom[2]*angMom[2]/I(2, 2);
1437     tempCount_[binNo] +=3;
1438 skuang 1338 }
1439     }
1440 gezelter 1722 value = value / PhysicalConstants::energyConvert
1441     / PhysicalConstants::kb;//may move to getStatus()
1442     tempHist_[binNo] += value;
1443     }
1444     if (outputVx_) {
1445 skuang 1338 value = mass * vel[0];
1446 gezelter 1722 //vxzCount_[binNo]++;
1447     pxzHist_[binNo] += value;
1448     }
1449     if (outputVy_) {
1450 skuang 1338 value = mass * vel[1];
1451 gezelter 1722 //vyzCount_[binNo]++;
1452     pyzHist_[binNo] += value;
1453 skuang 1338 }
1454 gezelter 1629
1455     if (output3DTemp_) {
1456 gezelter 1722 value = mass * vel.x() * vel.x();
1457     xTempHist_[binNo] += value;
1458     value = mass * vel.y() * vel.y() / PhysicalConstants::energyConvert
1459 gezelter 1629 / PhysicalConstants::kb;
1460 gezelter 1722 yTempHist_[binNo] += value;
1461     value = mass * vel.z() * vel.z() / PhysicalConstants::energyConvert
1462 gezelter 1629 / PhysicalConstants::kb;
1463 gezelter 1722 zTempHist_[binNo] += value;
1464 gezelter 1629 xyzTempCount_[binNo]++;
1465     }
1466 gezelter 1722 if (outputRotTemp_) {
1467     if (sd->isDirectional()) {
1468     Vector3d angMom = sd->getJ();
1469     Mat3x3d I = sd->getI();
1470     if (sd->isLinear()) {
1471     int i = sd->linearAxis();
1472     int j = (i + 1) % 3;
1473     int k = (i + 2) % 3;
1474     value = angMom[j] * angMom[j] / I(j, j) +
1475     angMom[k] * angMom[k] / I(k, k);
1476     rotTempCount_[binNo] +=2;
1477     } else {
1478     value = angMom[0] * angMom[0] / I(0, 0) +
1479     angMom[1] * angMom[1] / I(1, 1) +
1480     angMom[2] * angMom[2] / I(2, 2);
1481     rotTempCount_[binNo] +=3;
1482     }
1483     }
1484     value = value / PhysicalConstants::energyConvert
1485     / PhysicalConstants::kb;//may move to getStatus()
1486     rotTempHist_[binNo] += value;
1487     }
1488 jmarr 1728 // James put this in.
1489     if (outputDen_) {
1490     //value = 1.0;
1491     DenHist_[binNo] += 1;
1492     }
1493     if (outputVz_) {
1494     value = mass * vel[2];
1495     //vyzCount_[binNo]++;
1496     pzzHist_[binNo] += value;
1497     }
1498 skuang 1338 }
1499 skuang 1368 }
1500    
1501     void RNEMD::getStarted() {
1502 gezelter 1629 collectData();
1503 gezelter 1722 /*now can output profile in step 0, but might not be useful;
1504     Snapshot* currentSnap_ = info_->getSnapshotManager()->getCurrentSnapshot();
1505     Stats& stat = currentSnap_->statData;
1506     stat[Stats::RNEMD_EXCHANGE_TOTAL] = exchangeSum_;
1507 gezelter 1629 */
1508 gezelter 1722 //may output a header for the log file here
1509 gezelter 1629 getStatus();
1510 skuang 1368 }
1511    
1512     void RNEMD::getStatus() {
1513    
1514     Snapshot* currentSnap_ = info_->getSnapshotManager()->getCurrentSnapshot();
1515     RealType time = currentSnap_->getTime();
1516     //or to be more meaningful, define another item as exchangeSum_ / time
1517 gezelter 1396 int j;
1518 skuang 1368
1519 gezelter 1350 #ifdef IS_MPI
1520    
1521     // all processors have the same number of bins, and STL vectors pack their
1522     // arrays, so in theory, this should be safe:
1523    
1524 gezelter 1722 MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &mHist_[0],
1525     rnemdLogWidth_, MPI::REALTYPE, MPI::SUM);
1526     if (outputTemp_) {
1527     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &tempHist_[0],
1528     rnemdLogWidth_, MPI::REALTYPE, MPI::SUM);
1529     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &tempCount_[0],
1530     rnemdLogWidth_, MPI::INT, MPI::SUM);
1531     }
1532     if (outputVx_) {
1533     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &pxzHist_[0],
1534     rnemdLogWidth_, MPI::REALTYPE, MPI::SUM);
1535     //MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &vxzCount_[0],
1536     // rnemdLogWidth_, MPI::INT, MPI::SUM);
1537     }
1538     if (outputVy_) {
1539     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &pyzHist_[0],
1540     rnemdLogWidth_, MPI::REALTYPE, MPI::SUM);
1541     //MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &vyzCount_[0],
1542     // rnemdLogWidth_, MPI::INT, MPI::SUM);
1543     }
1544 gezelter 1629 if (output3DTemp_) {
1545 gezelter 1396 MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &xTempHist_[0],
1546     rnemdLogWidth_, MPI::REALTYPE, MPI::SUM);
1547     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &yTempHist_[0],
1548     rnemdLogWidth_, MPI::REALTYPE, MPI::SUM);
1549     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &zTempHist_[0],
1550     rnemdLogWidth_, MPI::REALTYPE, MPI::SUM);
1551 gezelter 1629 MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &xyzTempCount_[0],
1552     rnemdLogWidth_, MPI::INT, MPI::SUM);
1553 gezelter 1396 }
1554 gezelter 1722 if (outputRotTemp_) {
1555     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &rotTempHist_[0],
1556     rnemdLogWidth_, MPI::REALTYPE, MPI::SUM);
1557     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &rotTempCount_[0],
1558     rnemdLogWidth_, MPI::INT, MPI::SUM);
1559     }
1560 jmarr 1728 // James put this in
1561     if (outputDen_) {
1562     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &DenHist_[0],
1563     rnemdLogWidth_, MPI::REALTYPE, MPI::SUM);
1564     }
1565     if (outputAh_) {
1566     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &AhCount_,
1567     1, MPI::REALTYPE, MPI::SUM);
1568     }
1569     if (outputVz_) {
1570     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &pzzHist_[0],
1571     rnemdLogWidth_, MPI::REALTYPE, MPI::SUM);
1572     }
1573    
1574 gezelter 1350 // If we're the root node, should we print out the results
1575     int worldRank = MPI::COMM_WORLD.Get_rank();
1576     if (worldRank == 0) {
1577     #endif
1578 gezelter 1722
1579     if (outputTemp_) {
1580     tempLog_ << time;
1581     for (j = 0; j < rnemdLogWidth_; j++) {
1582     tempLog_ << "\t" << tempHist_[j] / (RealType)tempCount_[j];
1583     }
1584     tempLog_ << endl;
1585 skuang 1368 }
1586 gezelter 1722 if (outputVx_) {
1587     vxzLog_ << time;
1588     for (j = 0; j < rnemdLogWidth_; j++) {
1589     vxzLog_ << "\t" << pxzHist_[j] / mHist_[j];
1590     }
1591     vxzLog_ << endl;
1592     }
1593     if (outputVy_) {
1594     vyzLog_ << time;
1595     for (j = 0; j < rnemdLogWidth_; j++) {
1596     vyzLog_ << "\t" << pyzHist_[j] / mHist_[j];
1597     }
1598     vyzLog_ << endl;
1599     }
1600    
1601 gezelter 1629 if (output3DTemp_) {
1602 gezelter 1722 RealType temp;
1603     xTempLog_ << time;
1604 skuang 1368 for (j = 0; j < rnemdLogWidth_; j++) {
1605 gezelter 1722 if (outputVx_)
1606     xTempHist_[j] -= pxzHist_[j] * pxzHist_[j] / mHist_[j];
1607     temp = xTempHist_[j] / (RealType)xyzTempCount_[j]
1608     / PhysicalConstants::energyConvert / PhysicalConstants::kb;
1609     xTempLog_ << "\t" << temp;
1610 skuang 1368 }
1611 gezelter 1722 xTempLog_ << endl;
1612 skuang 1368 yTempLog_ << time;
1613     for (j = 0; j < rnemdLogWidth_; j++) {
1614 gezelter 1629 yTempLog_ << "\t" << yTempHist_[j] / (RealType)xyzTempCount_[j];
1615 skuang 1368 }
1616 gezelter 1722 yTempLog_ << endl;
1617 skuang 1368 zTempLog_ << time;
1618     for (j = 0; j < rnemdLogWidth_; j++) {
1619 gezelter 1629 zTempLog_ << "\t" << zTempHist_[j] / (RealType)xyzTempCount_[j];
1620 skuang 1368 }
1621 gezelter 1722 zTempLog_ << endl;
1622 skuang 1368 }
1623 gezelter 1722 if (outputRotTemp_) {
1624     rotTempLog_ << time;
1625     for (j = 0; j < rnemdLogWidth_; j++) {
1626     rotTempLog_ << "\t" << rotTempHist_[j] / (RealType)rotTempCount_[j];
1627     }
1628     rotTempLog_ << endl;
1629     }
1630 jmarr 1728 // James put this in.
1631     Mat3x3d hmat = currentSnap_->getHmat();
1632     if (outputDen_) {
1633     denLog_ << time;
1634     for (j = 0; j < rnemdLogWidth_; j++) {
1635    
1636     RealType binVol = hmat(0,0) * hmat(1,1) * (hmat(2,2) / float(nBins_));
1637     denLog_ << "\t" << DenHist_[j] / (float(logFrameCount_) * binVol);
1638     }
1639     denLog_ << endl;
1640     }
1641     if (outputVz_) {
1642     vzzLog_ << time;
1643     for (j = 0; j < rnemdLogWidth_; j++) {
1644     vzzLog_ << "\t" << pzzHist_[j] / mHist_[j];
1645     }
1646     vzzLog_ << endl;
1647     }
1648 gezelter 1350 #ifdef IS_MPI
1649 gezelter 1396 }
1650 gezelter 1350 #endif
1651 gezelter 1722
1652 gezelter 1396 for (j = 0; j < rnemdLogWidth_; j++) {
1653 gezelter 1722 mHist_[j] = 0.0;
1654 gezelter 1396 }
1655 gezelter 1722 if (outputTemp_)
1656     for (j = 0; j < rnemdLogWidth_; j++) {
1657     tempCount_[j] = 0;
1658     tempHist_[j] = 0.0;
1659     }
1660     if (outputVx_)
1661     for (j = 0; j < rnemdLogWidth_; j++) {
1662     //pxzCount_[j] = 0;
1663     pxzHist_[j] = 0.0;
1664     }
1665     if (outputVy_)
1666     for (j = 0; j < rnemdLogWidth_; j++) {
1667     //pyzCount_[j] = 0;
1668     pyzHist_[j] = 0.0;
1669     }
1670    
1671 gezelter 1629 if (output3DTemp_)
1672 gezelter 1396 for (j = 0; j < rnemdLogWidth_; j++) {
1673     xTempHist_[j] = 0.0;
1674     yTempHist_[j] = 0.0;
1675     zTempHist_[j] = 0.0;
1676 gezelter 1629 xyzTempCount_[j] = 0;
1677 gezelter 1396 }
1678 gezelter 1722 if (outputRotTemp_)
1679     for (j = 0; j < rnemdLogWidth_; j++) {
1680     rotTempCount_[j] = 0;
1681     rotTempHist_[j] = 0.0;
1682     }
1683 jmarr 1728 // James put this in
1684     if (outputDen_)
1685     for (j = 0; j < rnemdLogWidth_; j++) {
1686     //pyzCount_[j] = 0;
1687     DenHist_[j] = 0.0;
1688     }
1689     if (outputVz_)
1690     for (j = 0; j < rnemdLogWidth_; j++) {
1691     //pyzCount_[j] = 0;
1692     pzzHist_[j] = 0.0;
1693     }
1694     // reset the counter
1695    
1696     Numcount_++;
1697     if (Numcount_ > int(runTime_/statusTime_))
1698     cerr << "time =" << time << " Asum =" << Asum_ << '\n';
1699     if (Numcount_ > int(runTime_/statusTime_))
1700     cerr << "time =" << time << " Jsum =" << Jsum_ << '\n';
1701    
1702     logFrameCount_ = 0;
1703 gezelter 1334 }
1704 skuang 1338 }
1705 gezelter 1722

Properties

Name Value
svn:keywords Author Id Revision Date