Changeset 9e23a3
- Timestamp:
- Mar 1, 2011, 1:17:09 PM (14 years ago)
- Branches:
- 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
- Children:
- 20943b
- Parents:
- 632508
- git-author:
- Frederik Heber <heber@…> (02/24/11 23:49:26)
- git-committer:
- Frederik Heber <heber@…> (03/01/11 13:17:09)
- Location:
- src
- Files:
-
- 2 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Makefile.am
r632508 r9e23a3 119 119 Descriptors/MoleculeSelectionDescriptor_impl.hpp 120 120 121 DYNAMICSSOURCE = \ 122 Dynamics/MinimiseConstrainedPotential.cpp 123 124 DYNAMICSHEADER = \ 125 Dynamics/MinimiseConstrainedPotential.hpp 126 121 127 GRAPHSOURCE = \ 122 128 Graph/BondGraph.cpp … … 170 176 ${ATOMSOURCE} \ 171 177 ${DESCRIPTORSOURCE} \ 178 ${DYNAMICSSOURCE} \ 172 179 ${GRAPHSOURCE} \ 173 180 ${RANDOMSOURCE} \ … … 207 214 ${DESCRIPTORHEADER} \ 208 215 ${DESCRIPTORIMPLHEADER} \ 216 ${DYNAMICSHEADER} \ 209 217 ${GRAPHHEADER} \ 210 218 ${RANDOMSOURCE} \ -
src/molecule.hpp
r632508 r9e23a3 55 55 #define MoleculeListTest pair <MoleculeList::iterator, bool> 56 56 57 #define DistancePair pair < double, atom* >58 #define DistanceMap multimap < double, atom* >59 #define DistanceTestPair pair < DistanceMap::iterator, bool>60 61 62 57 /************************************* Class definitions ****************************************/ 63 64 /** Structure to contain parameters needed for evaluation of constraint potential.65 */66 struct EvaluatePotential67 {68 int startstep; //!< start configuration (MDStep in atom::trajectory)69 int endstep; //!< end configuration (MDStep in atom::trajectory)70 atom **PermutationMap; //!< gives target ptr for each atom, array of size molecule::AtomCount (this is "x" in \f$ V^{con}(x) \f$ )71 DistanceMap **DistanceList; //!< distance list of each atom to each atom72 DistanceMap::iterator *StepList; //!< iterator to ascend through NearestNeighbours \a **DistanceList73 int *DoubleList; //!< count of which sources want to move to this target, basically the injective measure (>1 -> not injective)74 DistanceMap::iterator *DistanceIterators; //!< marks which was the last picked target as injective candidate with smallest distance75 bool IsAngstroem; //!< whether coordinates are in angstroem (true) or bohrradius (false)76 double *PenaltyConstants; //!< penalty constant in front of each term77 };78 58 79 59 /** The complete molecule. … … 201 181 void RotateToPrincipalAxisSystem(Vector &Axis); 202 182 203 double ConstrainedPotential(struct EvaluatePotential &Params);204 double MinimiseConstrainedPotential(atom **&permutation, int startstep, int endstep, bool IsAngstroem);205 void EvaluateConstrainedForces(int startstep, int endstep, atom **PermutationMap, ForceMatrix *Force);206 183 bool LinearInterpolationBetweenConfiguration(int startstep, int endstep, std::string prefix, config &configuration, bool MapByIdentity); 207 184 -
src/molecule_dynamics.cpp
r632508 r9e23a3 23 23 #include "atom.hpp" 24 24 #include "config.hpp" 25 #include "element.hpp" 25 #include "Dynamics/MinimiseConstrainedPotential.hpp" 26 //#include "element.hpp" 26 27 #include "CodePatterns/Info.hpp" 27 #include "CodePatterns/Verbose.hpp"28 #include "CodePatterns/Log.hpp"28 //#include "CodePatterns/Verbose.hpp" 29 //#include "CodePatterns/Log.hpp" 29 30 #include "molecule.hpp" 30 31 #include "parser.hpp" 31 #include "LinearAlgebra/Plane.hpp"32 //#include "LinearAlgebra/Plane.hpp" 32 33 #include "ThermoStatContainer.hpp" 33 34 #include "Thermostats/Berendsen.hpp" … … 35 36 #include "CodePatterns/enumeration.hpp" 36 37 37 #include <gsl/gsl_matrix.h>38 #include <gsl/gsl_vector.h>39 #include <gsl/gsl_linalg.h>40 41 38 /************************************* Functions for class molecule *********************************/ 42 39 43 /** Penalizes long trajectories.44 * \param *Walker atom to check against others45 * \param *mol molecule with other atoms46 * \param &Params constraint potential parameters47 * \return penalty times each distance48 */49 double SumDistanceOfTrajectories(atom *Walker, molecule *mol, struct EvaluatePotential &Params)50 {51 gsl_matrix *A = gsl_matrix_alloc(NDIM,NDIM);52 gsl_vector *x = gsl_vector_alloc(NDIM);53 atom *Sprinter = NULL;54 Vector trajectory1, trajectory2, normal, TestVector;55 double Norm1, Norm2, tmp, result = 0.;56 57 for (molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) {58 if ((*iter) == Walker) // hence, we only go up to the Walker, not beyond (similar to i=0; i<j; i++)59 break;60 // determine normalized trajectories direction vector (n1, n2)61 Sprinter = Params.PermutationMap[Walker->getNr()]; // find first target point62 trajectory1 = Sprinter->getPositionAtStep(Params.endstep) - Walker->getPositionAtStep(Params.startstep);63 trajectory1.Normalize();64 Norm1 = trajectory1.Norm();65 Sprinter = Params.PermutationMap[(*iter)->getNr()]; // find second target point66 trajectory2 = Sprinter->getPositionAtStep(Params.endstep) - (*iter)->getPositionAtStep(Params.startstep);67 trajectory2.Normalize();68 Norm2 = trajectory1.Norm();69 // check whether either is zero()70 if ((Norm1 < MYEPSILON) && (Norm2 < MYEPSILON)) {71 tmp = Walker->getPositionAtStep(Params.startstep).distance((*iter)->getPositionAtStep(Params.startstep));72 } else if (Norm1 < MYEPSILON) {73 Sprinter = Params.PermutationMap[Walker->getNr()]; // find first target point74 trajectory1 = Sprinter->getPositionAtStep(Params.endstep) - (*iter)->getPositionAtStep(Params.startstep);75 trajectory2 *= trajectory1.ScalarProduct(trajectory2); // trajectory2 is scaled to unity, hence we don't need to divide by anything76 trajectory1 -= trajectory2; // project the part in norm direction away77 tmp = trajectory1.Norm(); // remaining norm is distance78 } else if (Norm2 < MYEPSILON) {79 Sprinter = Params.PermutationMap[(*iter)->getNr()]; // find second target point80 trajectory2 = Sprinter->getPositionAtStep(Params.endstep) - Walker->getPositionAtStep(Params.startstep); // copy second offset81 trajectory1 *= trajectory2.ScalarProduct(trajectory1); // trajectory1 is scaled to unity, hence we don't need to divide by anything82 trajectory2 -= trajectory1; // project the part in norm direction away83 tmp = trajectory2.Norm(); // remaining norm is distance84 } else if ((fabs(trajectory1.ScalarProduct(trajectory2)/Norm1/Norm2) - 1.) < MYEPSILON) { // check whether they're linear dependent85 // Log() << Verbose(3) << "Both trajectories of " << *Walker << " and " << *Runner << " are linear dependent: ";86 // Log() << Verbose(0) << trajectory1;87 // Log() << Verbose(0) << " and ";88 // Log() << Verbose(0) << trajectory2;89 tmp = Walker->getPositionAtStep(Params.startstep).distance((*iter)->getPositionAtStep(Params.startstep));90 // Log() << Verbose(0) << " with distance " << tmp << "." << endl;91 } else { // determine distance by finding minimum distance92 // Log() << Verbose(3) << "Both trajectories of " << *Walker << " and " << *(*iter) << " are linear independent ";93 // Log() << Verbose(0) << endl;94 // Log() << Verbose(0) << "First Trajectory: ";95 // Log() << Verbose(0) << trajectory1 << endl;96 // Log() << Verbose(0) << "Second Trajectory: ";97 // Log() << Verbose(0) << trajectory2 << endl;98 // determine normal vector for both99 normal = Plane(trajectory1, trajectory2,0).getNormal();100 // print all vectors for debugging101 // Log() << Verbose(0) << "Normal vector in between: ";102 // Log() << Verbose(0) << normal << endl;103 // setup matrix104 for (int i=NDIM;i--;) {105 gsl_matrix_set(A, 0, i, trajectory1[i]);106 gsl_matrix_set(A, 1, i, trajectory2[i]);107 gsl_matrix_set(A, 2, i, normal[i]);108 gsl_vector_set(x,i, (Walker->getPositionAtStep(Params.startstep)[i] - (*iter)->getPositionAtStep(Params.startstep)[i]));109 }110 // solve the linear system by Householder transformations111 gsl_linalg_HH_svx(A, x);112 // distance from last component113 tmp = gsl_vector_get(x,2);114 // Log() << Verbose(0) << " with distance " << tmp << "." << endl;115 // test whether we really have the intersection (by checking on c_1 and c_2)116 trajectory1.Scale(gsl_vector_get(x,0));117 trajectory2.Scale(gsl_vector_get(x,1));118 normal.Scale(gsl_vector_get(x,2));119 TestVector = (*iter)->getPositionAtStep(Params.startstep) + trajectory2 + normal120 - (Walker->getPositionAtStep(Params.startstep) + trajectory1);121 if (TestVector.Norm() < MYEPSILON) {122 // Log() << Verbose(2) << "Test: ok.\tDistance of " << tmp << " is correct." << endl;123 } else {124 // Log() << Verbose(2) << "Test: failed.\tIntersection is off by ";125 // Log() << Verbose(0) << TestVector;126 // Log() << Verbose(0) << "." << endl;127 }128 }129 // add up130 tmp *= Params.IsAngstroem ? 1. : 1./AtomicLengthToAngstroem;131 if (fabs(tmp) > MYEPSILON) {132 result += Params.PenaltyConstants[1] * 1./tmp;133 //Log() << Verbose(4) << "Adding " << 1./tmp*constants[1] << "." << endl;134 }135 }136 return result;137 };138 139 /** Penalizes atoms heading to same target.140 * \param *Walker atom to check against others141 * \param *mol molecule with other atoms142 * \param &Params constrained potential parameters143 * \return \a penalty times the number of equal targets144 */145 double PenalizeEqualTargets(atom *Walker, molecule *mol, struct EvaluatePotential &Params)146 {147 double result = 0.;148 for (molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) {149 if ((Params.PermutationMap[Walker->getNr()] == Params.PermutationMap[(*iter)->getNr()]) && (Walker->getNr() < (*iter)->getNr())) {150 // atom *Sprinter = PermutationMap[Walker->getNr()];151 // Log() << Verbose(0) << *Walker << " and " << *(*iter) << " are heading to the same target at ";152 // Log() << Verbose(0) << Sprinter->getPosition(endstep);153 // Log() << Verbose(0) << ", penalting." << endl;154 result += Params.PenaltyConstants[2];155 //Log() << Verbose(4) << "Adding " << constants[2] << "." << endl;156 }157 }158 return result;159 };160 161 /** Evaluates the potential energy used for constrained molecular dynamics.162 * \f$V_i^{con} = c^{bond} \cdot | r_{P(i)} - R_i | + sum_{i \neq j} C^{min} \cdot \frac{1}{C_{ij}} + C^{inj} \Bigl (1 - \theta \bigl (\prod_{i \neq j} (P(i) - P(j)) \bigr ) \Bigr )\f$163 * where the first term points to the target in minimum distance, the second is a penalty for trajectories lying too close to each other (\f$C_{ij}\f$ is minimum distance between164 * trajectories i and j) and the third term is a penalty for two atoms trying to each the same target point.165 * Note that for the second term we have to solve the following linear system:166 * \f$-c_1 \cdot n_1 + c_2 \cdot n_2 + C \cdot n_3 = - p_2 + p_1\f$, where \f$c_1\f$, \f$c_2\f$ and \f$C\f$ are constants,167 * offset vector \f$p_1\f$ in direction \f$n_1\f$, offset vector \f$p_2\f$ in direction \f$n_2\f$,168 * \f$n_3\f$ is the normal vector to both directions. \f$C\f$ would be the minimum distance between the two lines.169 * \sa molecule::MinimiseConstrainedPotential(), molecule::VerletForceIntegration()170 * \param *out output stream for debugging171 * \param &Params constrained potential parameters172 * \return potential energy173 * \note This routine is scaling quadratically which is not optimal.174 * \todo There's a bit double counting going on for the first time, bu nothing to worry really about.175 */176 double molecule::ConstrainedPotential(struct EvaluatePotential &Params)177 {178 double tmp = 0.;179 double result = 0.;180 // go through every atom181 atom *Runner = NULL;182 for (molecule::const_iterator iter = begin(); iter != end(); ++iter) {183 // first term: distance to target184 Runner = Params.PermutationMap[(*iter)->getNr()]; // find target point185 tmp = ((*iter)->getPositionAtStep(Params.startstep).distance(Runner->getPositionAtStep(Params.endstep)));186 tmp *= Params.IsAngstroem ? 1. : 1./AtomicLengthToAngstroem;187 result += Params.PenaltyConstants[0] * tmp;188 //Log() << Verbose(4) << "Adding " << tmp*constants[0] << "." << endl;189 190 // second term: sum of distances to other trajectories191 result += SumDistanceOfTrajectories((*iter), this, Params);192 193 // third term: penalty for equal targets194 result += PenalizeEqualTargets((*iter), this, Params);195 }196 197 return result;198 };199 200 /** print the current permutation map.201 * \param *out output stream for debugging202 * \param &Params constrained potential parameters203 * \param AtomCount number of atoms204 */205 void PrintPermutationMap(int AtomCount, struct EvaluatePotential &Params)206 {207 stringstream zeile1, zeile2;208 int *DoubleList = new int[AtomCount];209 for(int i=0;i<AtomCount;i++)210 DoubleList[i] = 0;211 int doubles = 0;212 zeile1 << "PermutationMap: ";213 zeile2 << " ";214 for (int i=0;i<AtomCount;i++) {215 Params.DoubleList[Params.PermutationMap[i]->getNr()]++;216 zeile1 << i << " ";217 zeile2 << Params.PermutationMap[i]->getNr() << " ";218 }219 for (int i=0;i<AtomCount;i++)220 if (Params.DoubleList[i] > 1)221 doubles++;222 if (doubles >0)223 DoLog(2) && (Log() << Verbose(2) << "Found " << doubles << " Doubles." << endl);224 delete[](DoubleList);225 // Log() << Verbose(2) << zeile1.str() << endl << zeile2.str() << endl;226 };227 228 /** \f$O(N^2)\f$ operation of calculation distance between each atom pair and putting into DistanceList.229 * \param *mol molecule to scan distances in230 * \param &Params constrained potential parameters231 */232 void FillDistanceList(molecule *mol, struct EvaluatePotential &Params)233 {234 for (int i=mol->getAtomCount(); i--;) {235 Params.DistanceList[i] = new DistanceMap; // is the distance sorted target list per atom236 Params.DistanceList[i]->clear();237 }238 239 for (molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) {240 for (molecule::const_iterator runner = mol->begin(); runner != mol->end(); ++runner) {241 Params.DistanceList[(*iter)->getNr()]->insert( DistancePair((*iter)->getPositionAtStep(Params.startstep).distance((*runner)->getPositionAtStep(Params.endstep)), (*runner)) );242 }243 }244 };245 246 /** initialize lists.247 * \param *out output stream for debugging248 * \param *mol molecule to scan distances in249 * \param &Params constrained potential parameters250 */251 void CreateInitialLists(molecule *mol, struct EvaluatePotential &Params)252 {253 for (molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) {254 Params.StepList[(*iter)->getNr()] = Params.DistanceList[(*iter)->getNr()]->begin(); // stores the step to the next iterator that could be a possible next target255 Params.PermutationMap[(*iter)->getNr()] = Params.DistanceList[(*iter)->getNr()]->begin()->second; // always pick target with the smallest distance256 Params.DoubleList[Params.DistanceList[(*iter)->getNr()]->begin()->second->getNr()]++; // increase this target's source count (>1? not injective)257 Params.DistanceIterators[(*iter)->getNr()] = Params.DistanceList[(*iter)->getNr()]->begin(); // and remember which one we picked258 DoLog(2) && (Log() << Verbose(2) << **iter << " starts with distance " << Params.DistanceList[(*iter)->getNr()]->begin()->first << "." << endl);259 }260 };261 262 /** Try the next nearest neighbour in order to make the permutation map injective.263 * \param *out output stream for debugging264 * \param *mol molecule265 * \param *Walker atom to change its target266 * \param &OldPotential old value of constraint potential to see if we do better with new target267 * \param &Params constrained potential parameters268 */269 double TryNextNearestNeighbourForInjectivePermutation(molecule *mol, atom *Walker, double &OldPotential, struct EvaluatePotential &Params)270 {271 double Potential = 0;272 DistanceMap::iterator NewBase = Params.DistanceIterators[Walker->getNr()]; // store old base273 do {274 NewBase++; // take next further distance in distance to targets list that's a target of no one275 } while ((Params.DoubleList[NewBase->second->getNr()] != 0) && (NewBase != Params.DistanceList[Walker->getNr()]->end()));276 if (NewBase != Params.DistanceList[Walker->getNr()]->end()) {277 Params.PermutationMap[Walker->getNr()] = NewBase->second;278 Potential = fabs(mol->ConstrainedPotential(Params));279 if (Potential > OldPotential) { // undo280 Params.PermutationMap[Walker->getNr()] = Params.DistanceIterators[Walker->getNr()]->second;281 } else { // do282 Params.DoubleList[Params.DistanceIterators[Walker->getNr()]->second->getNr()]--; // decrease the old entry in the doubles list283 Params.DoubleList[NewBase->second->getNr()]++; // increase the old entry in the doubles list284 Params.DistanceIterators[Walker->getNr()] = NewBase;285 OldPotential = Potential;286 DoLog(3) && (Log() << Verbose(3) << "Found a new permutation, new potential is " << OldPotential << "." << endl);287 }288 }289 return Potential;290 };291 292 /** Permutes \a **&PermutationMap until the penalty is below constants[2].293 * \param *out output stream for debugging294 * \param *mol molecule to scan distances in295 * \param &Params constrained potential parameters296 */297 void MakeInjectivePermutation(molecule *mol, struct EvaluatePotential &Params)298 {299 molecule::const_iterator iter = mol->begin();300 DistanceMap::iterator NewBase;301 double Potential = fabs(mol->ConstrainedPotential(Params));302 303 if (mol->empty()) {304 eLog() << Verbose(1) << "Molecule is empty." << endl;305 return;306 }307 while ((Potential) > Params.PenaltyConstants[2]) {308 PrintPermutationMap(mol->getAtomCount(), Params);309 iter++;310 if (iter == mol->end()) // round-robin at the end311 iter = mol->begin();312 if (Params.DoubleList[Params.DistanceIterators[(*iter)->getNr()]->second->getNr()] <= 1) // no need to make those injective that aren't313 continue;314 // now, try finding a new one315 Potential = TryNextNearestNeighbourForInjectivePermutation(mol, (*iter), Potential, Params);316 }317 for (int i=mol->getAtomCount(); i--;) // now each single entry in the DoubleList should be <=1318 if (Params.DoubleList[i] > 1) {319 DoeLog(0) && (eLog()<< Verbose(0) << "Failed to create an injective PermutationMap!" << endl);320 performCriticalExit();321 }322 DoLog(1) && (Log() << Verbose(1) << "done." << endl);323 };324 325 /** Minimises the extra potential for constrained molecular dynamics and gives forces and the constrained potential energy.326 * We do the following:327 * -# Generate a distance list from all source to all target points328 * -# Sort this per source point329 * -# Take for each source point the target point with minimum distance, use this as initial permutation330 * -# check whether molecule::ConstrainedPotential() is greater than injective penalty331 * -# If so, we go through each source point, stepping down in the sorted target point distance list and re-checking potential.332 * -# Next, we only apply transformations that keep the injectivity of the permutations list.333 * -# Hence, for one source point we step down the ladder and seek the corresponding owner of this new target334 * point and try to change it for one with lesser distance, or for the next one with greater distance, but only335 * if this decreases the conditional potential.336 * -# finished.337 * -# Then, we calculate the forces by taking the spatial derivative, where we scale the potential to such a degree,338 * that the total force is always pointing in direction of the constraint force (ensuring that we move in the339 * right direction).340 * -# Finally, we calculate the potential energy and return.341 * \param *out output stream for debugging342 * \param **PermutationMap on return: mapping between the atom label of the initial and the final configuration343 * \param startstep current MD step giving initial position between which and \a endstep we perform the constrained MD (as further steps are always concatenated)344 * \param endstep step giving final position in constrained MD345 * \param IsAngstroem whether coordinates are in angstroem (true) or bohrradius (false)346 * \sa molecule::VerletForceIntegration()347 * \return potential energy (and allocated **PermutationMap (array of molecule::AtomCount ^2)348 * \todo The constrained potential's constants are set to fixed values right now, but they should scale based on checks of the system in order349 * to ensure they're properties (e.g. constants[2] always greater than the energy of the system).350 * \bug this all is not O(N log N) but O(N^2)351 */352 double molecule::MinimiseConstrainedPotential(atom **&PermutationMap, int startstep, int endstep, bool IsAngstroem)353 {354 double Potential, OldPotential, OlderPotential;355 struct EvaluatePotential Params;356 Params.PermutationMap = new atom *[getAtomCount()];357 Params.DistanceList = new DistanceMap *[getAtomCount()];358 Params.DistanceIterators = new DistanceMap::iterator[getAtomCount()];359 Params.DoubleList = new int[getAtomCount()];360 Params.StepList = new DistanceMap::iterator[getAtomCount()];361 int round;362 atom *Sprinter = NULL;363 DistanceMap::iterator Rider, Strider;364 365 // set to zero366 for (int i=0;i<getAtomCount();i++) {367 Params.PermutationMap[i] = NULL;368 Params.DoubleList[i] = 0;369 }370 371 /// Minimise the potential372 // set Lagrange multiplier constants373 Params.PenaltyConstants[0] = 10.;374 Params.PenaltyConstants[1] = 1.;375 Params.PenaltyConstants[2] = 1e+7; // just a huge penalty376 // generate the distance list377 DoLog(1) && (Log() << Verbose(1) << "Allocating, initializting and filling the distance list ... " << endl);378 FillDistanceList(this, Params);379 380 // create the initial PermutationMap (source -> target)381 CreateInitialLists(this, Params);382 383 // make the PermutationMap injective by checking whether we have a non-zero constants[2] term in it384 DoLog(1) && (Log() << Verbose(1) << "Making the PermutationMap injective ... " << endl);385 MakeInjectivePermutation(this, Params);386 delete[](Params.DoubleList);387 388 // argument minimise the constrained potential in this injective PermutationMap389 DoLog(1) && (Log() << Verbose(1) << "Argument minimising the PermutationMap." << endl);390 OldPotential = 1e+10;391 round = 0;392 do {393 DoLog(2) && (Log() << Verbose(2) << "Starting round " << ++round << ", at current potential " << OldPotential << " ... " << endl);394 OlderPotential = OldPotential;395 molecule::const_iterator iter;396 do {397 iter = begin();398 for (; iter != end(); ++iter) {399 PrintPermutationMap(getAtomCount(), Params);400 Sprinter = Params.DistanceIterators[(*iter)->getNr()]->second; // store initial partner401 Strider = Params.DistanceIterators[(*iter)->getNr()]; //remember old iterator402 Params.DistanceIterators[(*iter)->getNr()] = Params.StepList[(*iter)->getNr()];403 if (Params.DistanceIterators[(*iter)->getNr()] == Params.DistanceList[(*iter)->getNr()]->end()) {// stop, before we run through the list and still on404 Params.DistanceIterators[(*iter)->getNr()] == Params.DistanceList[(*iter)->getNr()]->begin();405 break;406 }407 //Log() << Verbose(2) << "Current Walker: " << *(*iter) << " with old/next candidate " << *Sprinter << "/" << *DistanceIterators[(*iter)->getNr()]->second << "." << endl;408 // find source of the new target409 molecule::const_iterator runner = begin();410 for (; runner != end(); ++runner) { // find the source whose toes we might be stepping on (Walker's new target should be in use by another already)411 if (Params.PermutationMap[(*runner)->getNr()] == Params.DistanceIterators[(*iter)->getNr()]->second) {412 //Log() << Verbose(2) << "Found the corresponding owner " << *(*runner) << " to " << *PermutationMap[(*runner)->getNr()] << "." << endl;413 break;414 }415 }416 if (runner != end()) { // we found the other source417 // then look in its distance list for Sprinter418 Rider = Params.DistanceList[(*runner)->getNr()]->begin();419 for (; Rider != Params.DistanceList[(*runner)->getNr()]->end(); Rider++)420 if (Rider->second == Sprinter)421 break;422 if (Rider != Params.DistanceList[(*runner)->getNr()]->end()) { // if we have found one423 //Log() << Verbose(2) << "Current Other: " << *(*runner) << " with old/next candidate " << *PermutationMap[(*runner)->getNr()] << "/" << *Rider->second << "." << endl;424 // exchange both425 Params.PermutationMap[(*iter)->getNr()] = Params.DistanceIterators[(*iter)->getNr()]->second; // put next farther distance into PermutationMap426 Params.PermutationMap[(*runner)->getNr()] = Sprinter; // and hand the old target to its respective owner427 PrintPermutationMap(getAtomCount(), Params);428 // calculate the new potential429 //Log() << Verbose(2) << "Checking new potential ..." << endl;430 Potential = ConstrainedPotential(Params);431 if (Potential > OldPotential) { // we made everything worse! Undo ...432 //Log() << Verbose(3) << "Nay, made the potential worse: " << Potential << " vs. " << OldPotential << "!" << endl;433 //Log() << Verbose(3) << "Setting " << *(*runner) << "'s source to " << *Params.DistanceIterators[(*runner)->getNr()]->second << "." << endl;434 // Undo for Runner (note, we haven't moved the iteration yet, we may use this)435 Params.PermutationMap[(*runner)->getNr()] = Params.DistanceIterators[(*runner)->getNr()]->second;436 // Undo for Walker437 Params.DistanceIterators[(*iter)->getNr()] = Strider; // take next farther distance target438 //Log() << Verbose(3) << "Setting " << *(*iter) << "'s source to " << *Params.DistanceIterators[(*iter)->getNr()]->second << "." << endl;439 Params.PermutationMap[(*iter)->getNr()] = Params.DistanceIterators[(*iter)->getNr()]->second;440 } else {441 Params.DistanceIterators[(*runner)->getNr()] = Rider; // if successful also move the pointer in the iterator list442 DoLog(3) && (Log() << Verbose(3) << "Found a better permutation, new potential is " << Potential << " vs." << OldPotential << "." << endl);443 OldPotential = Potential;444 }445 if (Potential > Params.PenaltyConstants[2]) {446 DoeLog(1) && (eLog()<< Verbose(1) << "The two-step permutation procedure did not maintain injectivity!" << endl);447 exit(255);448 }449 //Log() << Verbose(0) << endl;450 } else {451 DoeLog(1) && (eLog()<< Verbose(1) << **runner << " was not the owner of " << *Sprinter << "!" << endl);452 exit(255);453 }454 } else {455 Params.PermutationMap[(*iter)->getNr()] = Params.DistanceIterators[(*iter)->getNr()]->second; // new target has no source!456 }457 Params.StepList[(*iter)->getNr()]++; // take next farther distance target458 }459 } while (++iter != end());460 } while ((OlderPotential - OldPotential) > 1e-3);461 DoLog(1) && (Log() << Verbose(1) << "done." << endl);462 463 464 /// free memory and return with evaluated potential465 for (int i=getAtomCount(); i--;)466 Params.DistanceList[i]->clear();467 delete[](Params.DistanceList);468 delete[](Params.DistanceIterators);469 return ConstrainedPotential(Params);470 };471 472 473 /** Evaluates the (distance-related part) of the constrained potential for the constrained forces.474 * \param *out output stream for debugging475 * \param startstep current MD step giving initial position between which and \a endstep we perform the constrained MD (as further steps are always concatenated)476 * \param endstep step giving final position in constrained MD477 * \param **PermutationMap mapping between the atom label of the initial and the final configuration478 * \param *Force ForceMatrix containing force vectors from the external energy functional minimisation.479 * \todo the constant for the constrained potential distance part is hard-coded independently of the hard-coded value in MinimiseConstrainedPotential()480 */481 void molecule::EvaluateConstrainedForces(int startstep, int endstep, atom **PermutationMap, ForceMatrix *Force)482 {483 double constant = 10.;484 485 /// evaluate forces (only the distance to target dependent part) with the final PermutationMap486 DoLog(1) && (Log() << Verbose(1) << "Calculating forces and adding onto ForceMatrix ... " << endl);487 BOOST_FOREACH(atom *_atom, atoms) {488 atom *Sprinter = PermutationMap[_atom->getNr()];489 // set forces490 for (int i=NDIM;i++;)491 Force->Matrix[0][_atom->getNr()][5+i] += 2.*constant*sqrt(_atom->getPositionAtStep(startstep).distance(Sprinter->getPositionAtStep(endstep)));492 }493 DoLog(1) && (Log() << Verbose(1) << "done." << endl);494 };495 40 496 41 /** Performs a linear interpolation between two desired atomic configurations with a given number of steps. … … 514 59 atom **PermutationMap = NULL; 515 60 atom *Sprinter = NULL; 516 if (!MapByIdentity) 517 MinimiseConstrainedPotential(PermutationMap, startstep, endstep, configuration.GetIsAngstroem()); 518 else { 61 if (!MapByIdentity) { 62 MinimiseConstrainedPotential Minimiser(atoms); 63 Minimiser(PermutationMap, startstep, endstep, configuration.GetIsAngstroem()); 64 } else { 519 65 // TODO: construction of enumeration goes here 520 66 PermutationMap = new atom *[getAtomCount()]; … … 610 156 // calculate forces and potential 611 157 atom **PermutationMap = NULL; 612 ConstrainedPotentialEnergy = MinimiseConstrainedPotential(PermutationMap,configuration.DoConstrainedMD, 0, configuration.GetIsAngstroem()); 613 EvaluateConstrainedForces(configuration.DoConstrainedMD, 0, PermutationMap, &Force); 158 MinimiseConstrainedPotential Minimiser(atoms); 159 //double ConstrainedPotentialEnergy = 160 Minimiser(PermutationMap, configuration.DoConstrainedMD, 0, configuration.GetIsAngstroem()); 161 Minimiser.EvaluateConstrainedForces(&Force); 614 162 delete[](PermutationMap); 615 163 }
Note:
See TracChangeset
for help on using the changeset viewer.