source: src/atom.cpp@ ba4170

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since ba4170 was 2cc75c3, checked in by Frederik Heber <heber@…>, 16 years ago

Shifted molecuke::InitComponentNumbers() to atom::InitComponentNr.

Note that this is still only possible due to ListOfBondsPerAtom() -> atom::ListOfBonds() switch.

  • Property mode set to 100644
File size: 22.8 KB
Line 
1/** \file atom.cpp
2 *
3 * Function implementations for the class atom.
4 *
5 */
6
7#include "atom.hpp"
8#include "bond.hpp"
9#include "config.hpp"
10#include "element.hpp"
11#include "lists.hpp"
12#include "memoryallocator.hpp"
13#include "parser.hpp"
14#include "vector.hpp"
15
16/************************************* Functions for class atom *************************************/
17
18/** Constructor of class atom.
19 */
20atom::atom()
21{
22 father = this; // generally, father is itself
23 previous = NULL;
24 next = NULL;
25 Ancestor = NULL;
26 type = NULL;
27 sort = NULL;
28 FixedIon = 0;
29 GraphNr = -1;
30 ComponentNr = NULL;
31 IsCyclic = false;
32 SeparationVertex = false;
33 LowpointNr = -1;
34 AdaptiveOrder = 0;
35 MaxOrder = false;
36 // set LCNode::Vector to our Vector
37 node = &x;
38};
39
40/** Constructor of class atom.
41 */
42atom::atom(atom *pointer)
43{
44 Name = NULL;
45 previous = NULL;
46 next = NULL;
47 father = pointer; // generally, father is itself
48 Ancestor = NULL;
49 GraphNr = -1;
50 ComponentNr = NULL;
51 IsCyclic = false;
52 SeparationVertex = false;
53 LowpointNr = -1;
54 AdaptiveOrder = 0;
55 MaxOrder = false;
56 type = pointer->type; // copy element of atom
57 x.CopyVector(&pointer->x); // copy coordination
58 v.CopyVector(&pointer->v); // copy velocity
59 FixedIon = pointer->FixedIon;
60 nr = -1;
61 sort = &nr;
62 node = &x;
63}
64
65
66/** Destructor of class atom.
67 */
68atom::~atom()
69{
70 BondList::const_iterator Runner;
71 while (!ListOfBonds.empty()) {
72 Runner = ListOfBonds.begin();
73 removewithoutcheck(*Runner);
74 }
75 unlink(this);
76 Free<int>(&ComponentNr, "atom::~atom: *ComponentNr");
77 Free<char>(&Name, "atom::~atom: *Name");
78 Trajectory.R.clear();
79 Trajectory.U.clear();
80 Trajectory.F.clear();
81};
82
83
84/** Climbs up the father list until NULL, last is returned.
85 * \return true father, i.e. whose father points to itself, NULL if it could not be found or has none (added hydrogen)
86 */
87atom *atom::GetTrueFather()
88{
89 atom *walker = this;
90 do {
91 if (walker == walker->father) // top most father is the one that points on itself
92 break;
93 walker = walker->father;
94 } while (walker != NULL);
95 return walker;
96};
97
98/** Sets father to itself or its father in case of copying a molecule.
99 */
100void atom::CorrectFather()
101{
102 if (father->father == father) // same atom in copy's father points to itself
103 father = this; // set father to itself (copy of a whole molecule)
104 else
105 father = father->father; // set father to original's father
106
107};
108
109/** Check whether father is equal to given atom.
110 * \param *ptr atom to compare father to
111 * \param **res return value (only set if atom::father is equal to \a *ptr)
112 */
113void atom::EqualsFather ( atom *ptr, atom **res )
114{
115 if ( ptr == father )
116 *res = this;
117};
118
119/** Checks whether atom is within the given box.
120 * \param offset offset to box origin
121 * \param *parallelepiped box matrix
122 * \return true - is inside, false - is not
123 */
124bool atom::IsInParallelepiped(Vector offset, double *parallelepiped)
125{
126 return (node->IsInParallelepiped(offset, parallelepiped));
127};
128
129/** Counts the number of bonds weighted by bond::BondDegree.
130 * \param bonds times bond::BondDegree
131 */
132int atom::CountBonds() const
133{
134 int NoBonds = 0;
135 for (BondList::const_iterator Runner = ListOfBonds.begin(); Runner != ListOfBonds.end(); (++Runner))
136 NoBonds += (*Runner)->BondDegree;
137 return NoBonds;
138};
139
140/** Output of a single atom.
141 * \param ElementNo cardinal number of the element
142 * \param AtomNo cardinal number among these atoms of the same element
143 * \param *out stream to output to
144 * \param *comment commentary after '#' sign
145 * \return true - \a *out present, false - \a *out is NULL
146 */
147bool atom::Output(ofstream *out, int ElementNo, int AtomNo, const char *comment) const
148{
149 if (out != NULL) {
150 *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t" << fixed << setprecision(9) << showpoint;
151 *out << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2];
152 *out << "\t" << FixedIon;
153 if (v.Norm() > MYEPSILON)
154 *out << "\t" << scientific << setprecision(6) << v.x[0] << "\t" << v.x[1] << "\t" << v.x[2] << "\t";
155 if (comment != NULL)
156 *out << " # " << comment << endl;
157 else
158 *out << " # molecule nr " << nr << endl;
159 return true;
160 } else
161 return false;
162};
163bool atom::Output(ofstream *out, int *ElementNo, int *AtomNo, const char *comment)
164{
165 AtomNo[type->Z]++; // increment number
166 if (out != NULL) {
167 *out << "Ion_Type" << ElementNo[type->Z] << "_" << AtomNo[type->Z] << "\t" << fixed << setprecision(9) << showpoint;
168 *out << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2];
169 *out << "\t" << FixedIon;
170 if (v.Norm() > MYEPSILON)
171 *out << "\t" << scientific << setprecision(6) << v.x[0] << "\t" << v.x[1] << "\t" << v.x[2] << "\t";
172 if (comment != NULL)
173 *out << " # " << comment << endl;
174 else
175 *out << " # molecule nr " << nr << endl;
176 return true;
177 } else
178 return false;
179};
180
181/** Output of a single atom as one lin in xyz file.
182 * \param *out stream to output to
183 * \return true - \a *out present, false - \a *out is NULL
184 */
185bool atom::OutputXYZLine(ofstream *out) const
186{
187 if (out != NULL) {
188 *out << type->symbol << "\t" << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2] << "\t" << endl;
189 return true;
190 } else
191 return false;
192};
193
194/** Output of a single atom as one lin in xyz file.
195 * \param *out stream to output to
196 * \param *ElementNo array with ion type number in the config file this atom's element shall have
197 * \param *AtomNo array with atom number in the config file this atom shall have, is increase by one automatically
198 * \param step Trajectory time step to output
199 * \return true - \a *out present, false - \a *out is NULL
200 */
201bool atom::OutputTrajectory(ofstream *out, int *ElementNo, int *AtomNo, int step) const
202{
203 AtomNo[type->Z]++;
204 if (out != NULL) {
205 *out << "Ion_Type" << ElementNo[type->Z] << "_" << AtomNo[type->Z] << "\t" << fixed << setprecision(9) << showpoint;
206 *out << Trajectory.R.at(step).x[0] << "\t" << Trajectory.R.at(step).x[1] << "\t" << Trajectory.R.at(step).x[2];
207 *out << "\t" << FixedIon;
208 if (Trajectory.U.at(step).Norm() > MYEPSILON)
209 *out << "\t" << scientific << setprecision(6) << Trajectory.U.at(step).x[0] << "\t" << Trajectory.U.at(step).x[1] << "\t" << Trajectory.U.at(step).x[2] << "\t";
210 if (Trajectory.F.at(step).Norm() > MYEPSILON)
211 *out << "\t" << scientific << setprecision(6) << Trajectory.F.at(step).x[0] << "\t" << Trajectory.F.at(step).x[1] << "\t" << Trajectory.F.at(step).x[2] << "\t";
212 *out << "\t# Number in molecule " << nr << endl;
213 return true;
214 } else
215 return false;
216};
217
218/** Output of a single atom as one lin in xyz file.
219 * \param *out stream to output to
220 * \param step Trajectory time step to output
221 * \return true - \a *out present, false - \a *out is NULL
222 */
223bool atom::OutputTrajectoryXYZ(ofstream *out, int step) const
224{
225 if (out != NULL) {
226 *out << type->symbol << "\t";
227 *out << Trajectory.R.at(step).x[0] << "\t";
228 *out << Trajectory.R.at(step).x[1] << "\t";
229 *out << Trajectory.R.at(step).x[2] << endl;
230 return true;
231 } else
232 return false;
233};
234
235/** Output graph info of this atom.
236 * \param *out output stream
237 */
238void atom::OutputGraphInfo(ofstream *out) const
239{
240 *out << Verbose(2) << "Atom " << Name << " is " << ((SeparationVertex) ? "a" : "not a") << " separation vertex, components are ";
241 OutputComponentNumber(out);
242 *out << " with Lowpoint " << LowpointNr << " and Graph Nr. " << GraphNr << "." << endl;
243};
244
245/** Output a list of flags, stating whether the bond was visited or not.
246 * Note, we make use of the last entry of the ComponentNr always being -1 if allocated.
247 * \param *out output stream for debugging
248 */
249void atom::OutputComponentNumber(ofstream *out) const
250{
251 if (ComponentNr != NULL) {
252 for (int i=0; ComponentNr[i] != -1; i++)
253 *out << ComponentNr[i] << " ";
254 }
255};
256
257
258/** Prints all bonds of this atom with total degree.
259 * \param *out stream to output to
260 * \return true - \a *out present, false - \a *out is NULL
261 */
262bool atom::OutputBondOfAtom(ofstream *out) const
263{
264 if (out != NULL) {
265#ifdef ADDHYDROGEN
266 if (type->Z != 1) { // regard only non-hydrogen
267#endif
268 *out << Verbose(4) << "Atom " << Name << "/" << nr << " with " << ListOfBonds.size() << " bonds: ";
269 int TotalDegree = 0;
270 for (BondList::const_iterator Runner = ListOfBonds.begin(); Runner != ListOfBonds.end(); ++Runner) {
271 *out << **Runner << "\t";
272 TotalDegree += (*Runner)->BondDegree;
273 }
274 *out << " -- TotalDegree: " << TotalDegree << endl;
275#ifdef ADDHYDROGEN
276 }
277#endif
278 return true;
279 } else
280 return false;
281};
282
283/** Output of atom::nr along with all bond partners.
284 * \param *AdjacencyFile output stream
285 */
286void atom::OutputAdjacency(ofstream *AdjacencyFile) const
287{
288 *AdjacencyFile << nr << "\t";
289 for (BondList::const_iterator Runner = ListOfBonds.begin(); Runner != ListOfBonds.end(); (++Runner))
290 *AdjacencyFile << (*Runner)->GetOtherAtom(this)->nr << "\t";
291 *AdjacencyFile << endl;
292};
293
294/** Outputs the current atom::AdaptiveOrder and atom::MaxOrder to \a *file.
295 * \param *file output stream
296 */
297void atom::OutputOrder(ofstream *file)
298{
299 *file << nr << "\t" << (int)AdaptiveOrder << "\t" << (int)MaxOrder << endl;
300 //cout << Verbose(2) << "Storing: " << nr << "\t" << (int)AdaptiveOrder << "\t" << (int)MaxOrder << "." << endl;
301};
302
303/** Initialises the component number array.
304 * Size is set to atom::ListOfBonds.size()+1 (last is th encode end by -1)
305 */
306void atom::InitComponentNr()
307{
308 if (ComponentNr != NULL)
309 Free(&ComponentNr);
310 ComponentNr = Malloc<int>(ListOfBonds.size()+1, "atom::InitComponentNumbers: *ComponentNr");
311 for (int i=ListOfBonds.size()+1;i--;)
312 ComponentNr[i] = -1;
313};
314
315/** Puts a given bond into atom::ListOfBonds.
316 * \param *Binder bond to insert
317 */
318bool atom::RegisterBond(bond *Binder)
319{
320 bool status = false;
321 if (Binder != NULL) {
322 if (Binder->Contains(this)) {
323 ListOfBonds.push_back(Binder);
324 status = true;
325 } else {
326 cout << Verbose(1) << "ERROR: " << *Binder << " does not contain " << *this << "." << endl;
327 }
328 } else {
329 cout << Verbose(1) << "ERROR: Binder is " << Binder << "." << endl;
330 }
331 return status;
332};
333
334/** Removes a given bond from atom::ListOfBonds.
335 * \param *Binder bond to remove
336 */
337bool atom::UnregisterBond(bond *Binder)
338{
339 bool status = false;
340 if (Binder != NULL) {
341 if (Binder->Contains(this)) {
342 ListOfBonds.remove(Binder);
343 status = true;
344 } else {
345 cout << Verbose(1) << "ERROR: " << *Binder << " does not contain " << *this << "." << endl;
346 }
347 } else {
348 cout << Verbose(1) << "ERROR: Binder is " << Binder << "." << endl;
349 }
350 return status;
351};
352
353/** Removes all bonds from atom::ListOfBonds.
354 * \note Does not do any memory de-allocation.
355 */
356void atom::UnregisterAllBond()
357{
358 ListOfBonds.clear();
359};
360
361/** Corrects the bond degree by one at most if necessary.
362 * \param *out output stream for debugging
363 */
364int atom::CorrectBondDegree(ofstream *out)
365{
366 int NoBonds = 0;
367 int OtherNoBonds = 0;
368 int FalseBondDegree = 0;
369 atom *OtherWalker = NULL;
370 bond *CandidateBond = NULL;
371
372 *out << Verbose(3) << "Walker " << *this << ": " << (int)this->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;
373 NoBonds = CountBonds();
374 if ((int)(type->NoValenceOrbitals) > NoBonds) { // we have a mismatch, check all bonding partners for mismatch
375 for (BondList::const_iterator Runner = ListOfBonds.begin(); Runner != ListOfBonds.end(); (++Runner)) {
376 OtherWalker = (*Runner)->GetOtherAtom(this);
377 OtherNoBonds = OtherWalker->CountBonds();
378 *out << Verbose(3) << "OtherWalker " << *OtherWalker << ": " << (int)OtherWalker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;
379 if ((int)(OtherWalker->type->NoValenceOrbitals) > NoBonds) { // check if possible candidate
380 if ((CandidateBond == NULL) || (ListOfBonds.size() > OtherWalker->ListOfBonds.size())) { // pick the one with fewer number of bonds first
381 CandidateBond = (*Runner);
382 *out << Verbose(3) << "New candidate is " << *CandidateBond << "." << endl;
383 }
384 }
385 }
386 if ((CandidateBond != NULL)) {
387 CandidateBond->BondDegree++;
388 *out << Verbose(2) << "Increased bond degree for bond " << *CandidateBond << "." << endl;
389 } else {
390 *out << Verbose(2) << "Could not find correct degree for atom " << *this << "." << endl;
391 FalseBondDegree++;
392 }
393 }
394 return FalseBondDegree;
395};
396
397ostream & operator << (ostream &ost, const atom &a)
398{
399 ost << "[" << a.Name << "|" << &a << "]";
400 return ost;
401};
402
403ostream & atom::operator << (ostream &ost)
404{
405 ost << "[" << Name << "|" << this << "]";
406 return ost;
407};
408
409/** Compares the indices of \a this atom with a given \a ptr.
410 * \param ptr atom to compare index against
411 * \return true - this one's is smaller, false - not
412 */
413bool atom::Compare(const atom &ptr)
414{
415 if (nr < ptr.nr)
416 return true;
417 else
418 return false;
419};
420
421/** Extends the trajectory STL vector to the new size.
422 * Does nothing if \a MaxSteps is smaller than current size.
423 * \param MaxSteps
424 */
425void atom::ResizeTrajectory(int MaxSteps)
426{
427 if (Trajectory.R.size() <= (unsigned int)(MaxSteps)) {
428 //cout << "Increasing size for trajectory array of " << keyword << " to " << (MaxSteps+1) << "." << endl;
429 Trajectory.R.resize(MaxSteps+1);
430 Trajectory.U.resize(MaxSteps+1);
431 Trajectory.F.resize(MaxSteps+1);
432 }
433};
434
435/** Copies a given trajectory step \a src onto another \a dest
436 * \param dest index of destination step
437 * \param src index of source step
438 */
439void atom::CopyStepOnStep(int dest, int src)
440{
441 if (dest == src) // self assignment check
442 return;
443
444 for (int n=NDIM;n--;) {
445 Trajectory.R.at(dest).x[n] = Trajectory.R.at(src).x[n];
446 Trajectory.U.at(dest).x[n] = Trajectory.U.at(src).x[n];
447 Trajectory.F.at(dest).x[n] = Trajectory.F.at(src).x[n];
448 }
449};
450
451/** Performs a velocity verlet update of the trajectory.
452 * Parameters are according to those in configuration class.
453 * \param NextStep index of sequential step to set
454 * \param *configuration pointer to configuration with parameters
455 * \param *Force matrix with forces
456 */
457void atom::VelocityVerletUpdate(int NextStep, config *configuration, ForceMatrix *Force)
458{
459 //a = configuration.Deltat*0.5/walker->type->mass; // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a
460 for (int d=0; d<NDIM; d++) {
461 Trajectory.F.at(NextStep).x[d] = -Force->Matrix[0][nr][d+5]*(configuration->GetIsAngstroem() ? AtomicLengthToAngstroem : 1.);
462 Trajectory.R.at(NextStep).x[d] = Trajectory.R.at(NextStep-1).x[d];
463 Trajectory.R.at(NextStep).x[d] += configuration->Deltat*(Trajectory.U.at(NextStep-1).x[d]); // s(t) = s(0) + v * deltat + 1/2 a * deltat^2
464 Trajectory.R.at(NextStep).x[d] += 0.5*configuration->Deltat*configuration->Deltat*(Trajectory.F.at(NextStep).x[d]/type->mass); // F = m * a and s = 0.5 * F/m * t^2 = F * a * t
465 }
466 // Update U
467 for (int d=0; d<NDIM; d++) {
468 Trajectory.U.at(NextStep).x[d] = Trajectory.U.at(NextStep-1).x[d];
469 Trajectory.U.at(NextStep).x[d] += configuration->Deltat * (Trajectory.F.at(NextStep).x[d]+Trajectory.F.at(NextStep-1).x[d]/type->mass); // v = F/m * t
470 }
471 // Update R (and F)
472// out << "Integrated position&velocity of step " << (NextStep) << ": (";
473// for (int d=0;d<NDIM;d++)
474// out << Trajectory.R.at(NextStep).x[d] << " "; // next step
475// out << ")\t(";
476// for (int d=0;d<NDIM;d++)
477// cout << Trajectory.U.at(NextStep).x[d] << " "; // next step
478// out << ")" << endl;
479};
480
481/** Sums up mass and kinetics.
482 * \param Step step to sum for
483 * \param *TotalMass pointer to total mass sum
484 * \param *TotalVelocity pointer to tota velocity sum
485 */
486void atom::SumUpKineticEnergy( int Step, double *TotalMass, Vector *TotalVelocity )
487{
488 *TotalMass += type->mass; // sum up total mass
489 for(int d=0;d<NDIM;d++) {
490 TotalVelocity->x[d] += Trajectory.U.at(Step).x[d]*type->mass;
491 }
492};
493
494/** Returns squared distance to a given vector.
495 * \param origin vector to calculate distance to
496 * \return distance squared
497 */
498double atom::DistanceSquaredToVector(Vector &origin)
499{
500 return origin.DistanceSquared(&x);
501};
502
503/** Adds kinetic energy of this atom to given temperature value.
504 * \param *temperature add on this value
505 * \param step given step of trajectory to add
506 */
507void atom::AddKineticToTemperature(double *temperature, int step) const
508{
509 for (int i=NDIM;i--;)
510 *temperature += type->mass * Trajectory.U.at(step).x[i]* Trajectory.U.at(step).x[i];
511};
512
513/** Returns distance to a given vector.
514 * \param origin vector to calculate distance to
515 * \return distance
516 */
517double atom::DistanceToVector(Vector &origin)
518{
519 return origin.Distance(&x);
520};
521
522bool operator < (atom &a, atom &b)
523{
524 return a.Compare(b);
525};
526
527/** Evaluates some constraint potential if atom moves from \a startstep at once to \endstep in trajectory.
528 * \param startstep trajectory begins at
529 * \param endstep trajectory ends at
530 * \param **PermutationMap if atom switches places with some other atom, there is no translation but a permutaton noted here (not in the trajectories of each).
531 * \param *Force Force matrix to store result in
532 */
533void atom::EvaluateConstrainedForce(int startstep, int endstep, atom **PermutationMap, ForceMatrix *Force)
534{
535 double constant = 10.;
536 atom *Sprinter = PermutationMap[nr];
537 // set forces
538 for (int i=NDIM;i++;)
539 Force->Matrix[0][nr][5+i] += 2.*constant*sqrt(Trajectory.R.at(startstep).Distance(&Sprinter->Trajectory.R.at(endstep)));
540};
541
542/** Correct velocity against the summed \a CoGVelocity for \a step.
543 * \param *ActualTemp sum up actual temperature meanwhile
544 * \param Step MD step in atom::Tracjetory
545 * \param *CoGVelocity remnant velocity (i.e. vector sum of all atom velocities)
546 */
547void atom::CorrectVelocity(double *ActualTemp, int Step, Vector *CoGVelocity)
548{
549 for(int d=0;d<NDIM;d++) {
550 Trajectory.U.at(Step).x[d] -= CoGVelocity->x[d];
551 *ActualTemp += 0.5 * type->mass * Trajectory.U.at(Step).x[d] * Trajectory.U.at(Step).x[d];
552 }
553};
554
555/** Scales velocity of atom according to Woodcock thermostat.
556 * \param ScaleTempFactor factor to scale the velocities with (i.e. sqrt of energy scale factor)
557 * \param Step MD step to scale
558 * \param *ekin sum of kinetic energy
559 */
560void atom::Thermostat_Woodcock(double ScaleTempFactor, int Step, double *ekin)
561{
562 double *U = Trajectory.U.at(Step).x;
563 if (FixedIon == 0) // even FixedIon moves, only not by other's forces
564 for (int d=0; d<NDIM; d++) {
565 U[d] *= ScaleTempFactor;
566 *ekin += 0.5*type->mass * U[d]*U[d];
567 }
568};
569
570/** Scales velocity of atom according to Gaussian thermostat.
571 * \param Step MD step to scale
572 * \param *G
573 * \param *E
574 */
575void atom::Thermostat_Gaussian_init(int Step, double *G, double *E)
576{
577 double *U = Trajectory.U.at(Step).x;
578 double *F = Trajectory.F.at(Step).x;
579 if (FixedIon == 0) // even FixedIon moves, only not by other's forces
580 for (int d=0; d<NDIM; d++) {
581 *G += U[d] * F[d];
582 *E += U[d]*U[d]*type->mass;
583 }
584};
585
586/** Determines scale factors according to Gaussian thermostat.
587 * \param Step MD step to scale
588 * \param GE G over E ratio
589 * \param *ekin sum of kinetic energy
590 * \param *configuration configuration class with TempFrequency and TargetTemp
591 */
592void atom::Thermostat_Gaussian_least_constraint(int Step, double G_over_E, double *ekin, config *configuration)
593{
594 double *U = Trajectory.U.at(Step).x;
595 if (FixedIon == 0) // even FixedIon moves, only not by other's forces
596 for (int d=0; d<NDIM; d++) {
597 U[d] += configuration->Deltat/type->mass * ( (G_over_E) * (U[d]*type->mass) );
598 *ekin += type->mass * U[d]*U[d];
599 }
600};
601
602/** Scales velocity of atom according to Langevin thermostat.
603 * \param Step MD step to scale
604 * \param *r random number generator
605 * \param *ekin sum of kinetic energy
606 * \param *configuration configuration class with TempFrequency and TargetTemp
607 */
608void atom::Thermostat_Langevin(int Step, gsl_rng * r, double *ekin, config *configuration)
609{
610 double sigma = sqrt(configuration->TargetTemp/type->mass); // sigma = (k_b T)/m (Hartree/atomicmass = atomiclength/atomictime)
611 double *U = Trajectory.U.at(Step).x;
612 if (FixedIon == 0) { // even FixedIon moves, only not by other's forces
613 // throw a dice to determine whether it gets hit by a heat bath particle
614 if (((((rand()/(double)RAND_MAX))*configuration->TempFrequency) < 1.)) {
615 cout << Verbose(3) << "Particle " << *this << " was hit (sigma " << sigma << "): " << sqrt(U[0]*U[0]+U[1]*U[1]+U[2]*U[2]) << " -> ";
616 // pick three random numbers from a Boltzmann distribution around the desired temperature T for each momenta axis
617 for (int d=0; d<NDIM; d++) {
618 U[d] = gsl_ran_gaussian (r, sigma);
619 }
620 cout << sqrt(U[0]*U[0]+U[1]*U[1]+U[2]*U[2]) << endl;
621 }
622 for (int d=0; d<NDIM; d++)
623 *ekin += 0.5*type->mass * U[d]*U[d];
624 }
625};
626
627/** Scales velocity of atom according to Berendsen thermostat.
628 * \param Step MD step to scale
629 * \param ScaleTempFactor factor to scale energy (not velocity!) with
630 * \param *ekin sum of kinetic energy
631 * \param *configuration configuration class with TempFrequency and Deltat
632 */
633void atom::Thermostat_Berendsen(int Step, double ScaleTempFactor, double *ekin, config *configuration)
634{
635 double *U = Trajectory.U.at(Step).x;
636 if (FixedIon == 0) { // even FixedIon moves, only not by other's forces
637 for (int d=0; d<NDIM; d++) {
638 U[d] *= sqrt(1+(configuration->Deltat/configuration->TempFrequency)*(ScaleTempFactor-1));
639 *ekin += 0.5*type->mass * U[d]*U[d];
640 }
641 }
642};
643
644/** Initializes current run of NoseHoover thermostat.
645 * \param Step MD step to scale
646 * \param *delta_alpha additional sum of kinetic energy on return
647 */
648void atom::Thermostat_NoseHoover_init(int Step, double *delta_alpha)
649{
650 double *U = Trajectory.U.at(Step).x;
651 if (FixedIon == 0) { // even FixedIon moves, only not by other's forces
652 for (int d=0; d<NDIM; d++) {
653 *delta_alpha += U[d]*U[d]*type->mass;
654 }
655 }
656};
657
658/** Initializes current run of NoseHoover thermostat.
659 * \param Step MD step to scale
660 * \param *ekin sum of kinetic energy
661 * \param *configuration configuration class with TempFrequency and Deltat
662 */
663void atom::Thermostat_NoseHoover_scale(int Step, double *ekin, config *configuration)
664{
665 double *U = Trajectory.U.at(Step).x;
666 if (FixedIon == 0) { // even FixedIon moves, only not by other's forces
667 for (int d=0; d<NDIM; d++) {
668 U[d] += configuration->Deltat/type->mass * (configuration->alpha * (U[d] * type->mass));
669 *ekin += (0.5*type->mass) * U[d]*U[d];
670 }
671 }
672};
Note: See TracBrowser for help on using the repository browser.