[bcf653] | 1 | /*
|
---|
| 2 | * Project: MoleCuilder
|
---|
| 3 | * Description: creates and alters molecular systems
|
---|
| 4 | * Copyright (C) 2010 University of Bonn. All rights reserved.
|
---|
| 5 | * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
|
---|
| 6 | */
|
---|
| 7 |
|
---|
[cee0b57] | 8 | /*
|
---|
| 9 | * molecule_dynamics.cpp
|
---|
| 10 | *
|
---|
| 11 | * Created on: Oct 5, 2009
|
---|
| 12 | * Author: heber
|
---|
| 13 | */
|
---|
| 14 |
|
---|
[bf3817] | 15 | // include config.h
|
---|
| 16 | #ifdef HAVE_CONFIG_H
|
---|
| 17 | #include <config.h>
|
---|
| 18 | #endif
|
---|
| 19 |
|
---|
[ad011c] | 20 | #include "CodePatterns/MemDebug.hpp"
|
---|
[112b09] | 21 |
|
---|
[cbc5fb] | 22 | #include "World.hpp"
|
---|
[f66195] | 23 | #include "atom.hpp"
|
---|
[cee0b57] | 24 | #include "config.hpp"
|
---|
[9e23a3] | 25 | #include "Dynamics/MinimiseConstrainedPotential.hpp"
|
---|
| 26 | //#include "element.hpp"
|
---|
[ad011c] | 27 | #include "CodePatterns/Info.hpp"
|
---|
[9e23a3] | 28 | //#include "CodePatterns/Verbose.hpp"
|
---|
| 29 | //#include "CodePatterns/Log.hpp"
|
---|
[cee0b57] | 30 | #include "molecule.hpp"
|
---|
[f66195] | 31 | #include "parser.hpp"
|
---|
[9e23a3] | 32 | //#include "LinearAlgebra/Plane.hpp"
|
---|
[a3fded] | 33 | #include "ThermoStatContainer.hpp"
|
---|
[14c57a] | 34 | #include "Thermostats/Berendsen.hpp"
|
---|
[cee0b57] | 35 |
|
---|
[ad011c] | 36 | #include "CodePatterns/enumeration.hpp"
|
---|
[a0064e] | 37 |
|
---|
[cee0b57] | 38 | /************************************* Functions for class molecule *********************************/
|
---|
| 39 |
|
---|
| 40 |
|
---|
| 41 | /** Performs a linear interpolation between two desired atomic configurations with a given number of steps.
|
---|
| 42 | * Note, step number is config::MaxOuterStep
|
---|
| 43 | * \param *out output stream for debugging
|
---|
| 44 | * \param startstep stating initial configuration in molecule::Trajectories
|
---|
| 45 | * \param endstep stating final configuration in molecule::Trajectories
|
---|
[35b698] | 46 | * \param &prefix path and prefix
|
---|
[cee0b57] | 47 | * \param &config configuration structure
|
---|
| 48 | * \param MapByIdentity if true we just use the identity to map atoms in start config to end config, if not we find mapping by \sa MinimiseConstrainedPotential()
|
---|
| 49 | * \return true - success in writing step files, false - error writing files or only one step in molecule::Trajectories
|
---|
| 50 | */
|
---|
[e4afb4] | 51 | bool molecule::LinearInterpolationBetweenConfiguration(int startstep, int endstep, std::string prefix, config &configuration, bool MapByIdentity)
|
---|
[cee0b57] | 52 | {
|
---|
[32ea56] | 53 | // TODO: rewrite permutationMaps using enumeration objects
|
---|
[cee0b57] | 54 | molecule *mol = NULL;
|
---|
| 55 | bool status = true;
|
---|
| 56 | int MaxSteps = configuration.MaxOuterStep;
|
---|
[23b547] | 57 | MoleculeListClass *MoleculePerStep = new MoleculeListClass(World::getPointer());
|
---|
[cee0b57] | 58 | // Get the Permutation Map by MinimiseConstrainedPotential
|
---|
| 59 | atom **PermutationMap = NULL;
|
---|
[9879f6] | 60 | atom *Sprinter = NULL;
|
---|
[9e23a3] | 61 | if (!MapByIdentity) {
|
---|
| 62 | MinimiseConstrainedPotential Minimiser(atoms);
|
---|
| 63 | Minimiser(PermutationMap, startstep, endstep, configuration.GetIsAngstroem());
|
---|
| 64 | } else {
|
---|
[32ea56] | 65 | // TODO: construction of enumeration goes here
|
---|
[1024cb] | 66 | PermutationMap = new atom *[getAtomCount()];
|
---|
[32ea56] | 67 | for(internal_iterator iter = atoms.begin(); iter != atoms.end();++iter){
|
---|
[735b1c] | 68 | PermutationMap[(*iter)->getNr()] = (*iter);
|
---|
[32ea56] | 69 | }
|
---|
[cee0b57] | 70 | }
|
---|
| 71 |
|
---|
| 72 | // check whether we have sufficient space in Trajectories for each atom
|
---|
[6625c3] | 73 | LOG(1, "STATUS: Extending each trajectory size to " << MaxSteps+1 << ".");
|
---|
| 74 | for_each(atoms.begin(),atoms.end(),bind2nd(mem_fun(&atom::ResizeTrajectory),MaxSteps+1));
|
---|
[cee0b57] | 75 | // push endstep to last one
|
---|
[c743f8] | 76 | for_each(atoms.begin(),atoms.end(),boost::bind(&atom::CopyStepOnStep,_1,MaxSteps,endstep));
|
---|
[cee0b57] | 77 | endstep = MaxSteps;
|
---|
| 78 |
|
---|
| 79 | // go through all steps and add the molecular configuration to the list and to the Trajectories of \a this molecule
|
---|
[a67d19] | 80 | DoLog(1) && (Log() << Verbose(1) << "Filling intermediate " << MaxSteps << " steps with MDSteps of " << MDSteps << "." << endl);
|
---|
[cee0b57] | 81 | for (int step = 0; step <= MaxSteps; step++) {
|
---|
[23b547] | 82 | mol = World::getInstance().createMolecule();
|
---|
[cee0b57] | 83 | MoleculePerStep->insert(mol);
|
---|
[9879f6] | 84 | for (molecule::const_iterator iter = begin(); iter != end(); ++iter) {
|
---|
[cee0b57] | 85 | // add to molecule list
|
---|
[9879f6] | 86 | Sprinter = mol->AddCopyAtom((*iter));
|
---|
[6625c3] | 87 | // add to Trajectories
|
---|
[735b1c] | 88 | Vector temp = (*iter)->getPositionAtStep(startstep) + (PermutationMap[(*iter)->getNr()]->getPositionAtStep(endstep) - (*iter)->getPositionAtStep(startstep))*((double)step/(double)MaxSteps);
|
---|
[6625c3] | 89 | Sprinter->setPosition(temp);
|
---|
[056e70] | 90 | (*iter)->setAtomicVelocityAtStep(step, zeroVec);
|
---|
| 91 | (*iter)->setAtomicForceAtStep(step, zeroVec);
|
---|
[6625c3] | 92 | //Log() << Verbose(3) << step << ">=" << MDSteps-1 << endl;
|
---|
[cee0b57] | 93 | }
|
---|
| 94 | }
|
---|
| 95 | MDSteps = MaxSteps+1; // otherwise new Trajectories' points aren't stored on save&exit
|
---|
| 96 |
|
---|
| 97 | // store the list to single step files
|
---|
[1024cb] | 98 | int *SortIndex = new int[getAtomCount()];
|
---|
[ea7176] | 99 | for (int i=getAtomCount(); i--; )
|
---|
[cee0b57] | 100 | SortIndex[i] = i;
|
---|
[35b698] | 101 |
|
---|
| 102 | status = MoleculePerStep->OutputConfigForListOfFragments(prefix, SortIndex);
|
---|
[920c70] | 103 | delete[](SortIndex);
|
---|
[cee0b57] | 104 |
|
---|
| 105 | // free and return
|
---|
[920c70] | 106 | delete[](PermutationMap);
|
---|
[cee0b57] | 107 | delete(MoleculePerStep);
|
---|
| 108 | return status;
|
---|
| 109 | };
|
---|
| 110 |
|
---|
| 111 | /** Parses nuclear forces from file and performs Verlet integration.
|
---|
| 112 | * Note that we assume the parsed forces to be in atomic units (hence, if coordinates are in angstroem, we
|
---|
| 113 | * have to transform them).
|
---|
| 114 | * This adds a new MD step to the config file.
|
---|
| 115 | * \param *file filename
|
---|
| 116 | * \param config structure with config::Deltat, config::IsAngstroem, config::DoConstrained
|
---|
[ef7d30] | 117 | * \param offset offset in matrix file to the first force component
|
---|
[cee0b57] | 118 | * \return true - file found and parsed, false - file not found or imparsable
|
---|
| 119 | * \todo This is not yet checked if it is correctly working with DoConstrained set to true.
|
---|
| 120 | */
|
---|
[ef7d30] | 121 | bool molecule::VerletForceIntegration(char *file, config &configuration, const size_t offset)
|
---|
[cee0b57] | 122 | {
|
---|
[c7a473] | 123 | Info FunctionInfo(__func__);
|
---|
[cee0b57] | 124 | string token;
|
---|
| 125 | stringstream item;
|
---|
[4a7776a] | 126 | double IonMass, ConstrainedPotentialEnergy, ActualTemp;
|
---|
| 127 | Vector Velocity;
|
---|
[cee0b57] | 128 | ForceMatrix Force;
|
---|
| 129 |
|
---|
[ef7d30] | 130 | const int AtomCount = getAtomCount();
|
---|
[4e855e] | 131 | // parse file into ForceMatrix
|
---|
| 132 | std::ifstream input(file);
|
---|
| 133 | if ((input.good()) && (!Force.ParseMatrix(input, 0,0,0))) {
|
---|
| 134 | DoeLog(0) && (eLog()<< Verbose(0) << "Could not parse Force Matrix file " << file << "." << endl);
|
---|
| 135 | performCriticalExit();
|
---|
[cee0b57] | 136 | return false;
|
---|
[4e855e] | 137 | }
|
---|
| 138 | input.close();
|
---|
| 139 | if (Force.RowCounter[0] != AtomCount) {
|
---|
| 140 | DoeLog(0) && (eLog()<< Verbose(0) << "Mismatch between number of atoms in file " << Force.RowCounter[0] << " and in molecule " << getAtomCount() << "." << endl);
|
---|
| 141 | performCriticalExit();
|
---|
| 142 | return false;
|
---|
| 143 | }
|
---|
| 144 | // correct Forces
|
---|
| 145 | Velocity.Zero();
|
---|
| 146 | for(int i=0;i<AtomCount;i++)
|
---|
| 147 | for(int d=0;d<NDIM;d++) {
|
---|
| 148 | Velocity[d] += Force.Matrix[0][i][d+offset];
|
---|
[cee0b57] | 149 | }
|
---|
[4e855e] | 150 | for(int i=0;i<AtomCount;i++)
|
---|
| 151 | for(int d=0;d<NDIM;d++) {
|
---|
| 152 | Force.Matrix[0][i][d+offset] -= Velocity[d]/static_cast<double>(AtomCount);
|
---|
[cee0b57] | 153 | }
|
---|
[4e855e] | 154 | // solve a constrained potential if we are meant to
|
---|
| 155 | if (configuration.DoConstrainedMD) {
|
---|
| 156 | // calculate forces and potential
|
---|
| 157 | atom **PermutationMap = NULL;
|
---|
[9e23a3] | 158 | MinimiseConstrainedPotential Minimiser(atoms);
|
---|
| 159 | //double ConstrainedPotentialEnergy =
|
---|
| 160 | Minimiser(PermutationMap, configuration.DoConstrainedMD, 0, configuration.GetIsAngstroem());
|
---|
| 161 | Minimiser.EvaluateConstrainedForces(&Force);
|
---|
[4e855e] | 162 | delete[](PermutationMap);
|
---|
[cee0b57] | 163 | }
|
---|
[4e855e] | 164 |
|
---|
| 165 | // and perform Verlet integration for each atom with position, velocity and force vector
|
---|
| 166 | // check size of vectors
|
---|
[6625c3] | 167 | BOOST_FOREACH(atom *_atom, atoms) {
|
---|
[735b1c] | 168 | _atom->VelocityVerletUpdate(_atom->getNr(), MDSteps+1, &configuration, &Force, (const size_t) 0);
|
---|
[6625c3] | 169 | }
|
---|
[4e855e] | 170 |
|
---|
[cee0b57] | 171 | // correct velocities (rather momenta) so that center of mass remains motionless
|
---|
[259b2b] | 172 | Velocity = atoms.totalMomentumAtStep(MDSteps+1);
|
---|
| 173 | IonMass = atoms.totalMass();
|
---|
[4a7776a] | 174 |
|
---|
[cee0b57] | 175 | // correct velocities (rather momenta) so that center of mass remains motionless
|
---|
[5cd333c] | 176 | Velocity *= 1./IonMass;
|
---|
[259b2b] | 177 |
|
---|
| 178 | atoms.addVelocityAtStep(-1*Velocity,MDSteps+1);
|
---|
| 179 | ActualTemp = atoms.totalTemperatureAtStep(MDSteps+1);
|
---|
[14c57a] | 180 | Berendsen berendsen = Berendsen();
|
---|
[1bfc8e] | 181 | berendsen.addToContainer(World::getInstance().getThermostats());
|
---|
[14c57a] | 182 | double ekin = berendsen.scaleAtoms(MDSteps,ActualTemp,atoms);
|
---|
| 183 | DoLog(1) && (Log() << Verbose(1) << "Kinetic energy is " << ekin << "." << endl);
|
---|
[cee0b57] | 184 | MDSteps++;
|
---|
| 185 |
|
---|
| 186 | // exit
|
---|
| 187 | return true;
|
---|
| 188 | };
|
---|