Changeset a1fe77 for src/molecules.cpp


Ignore:
Timestamp:
Sep 11, 2008, 1:28:25 PM (16 years ago)
Author:
Frederik Heber <heber@…>
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:
85bac0
Parents:
6e9353
git-author:
Frederik Heber <heber@…> (09/05/08 16:56:31)
git-committer:
Frederik Heber <heber@…> (09/11/08 13:28:25)
Message:

Basic implementation of Constrained MD is done, missing testing.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/molecules.cpp

    r6e9353 ra1fe77  
    10171017 * \sa molecule::MinimiseConstrainedPotential(), molecule::VerletForceIntegration()
    10181018 * \param *out output stream for debugging
    1019  * \param *permutation gives target index for each atom, array of size molecule::AtomCount (this is "x" in \f$V^{con}(x)\f$)
     1019 * \param *PermutationMap gives target ptr for each atom, array of size molecule::AtomCount (this is "x" in \f$V^{con}(x)\f$)
    10201020 * \param startstep start configuration (MDStep in molecule::trajectories)
    10211021 * \param endstep end configuration (MDStep in molecule::trajectories)
     
    10251025 * \note This routine is scaling quadratically which is not optimal.
    10261026 */
    1027 double molecule::ConstrainedPotential(ofstream *out, int *permutation, int startstep, int endstep, double *constants, bool IsAngstroem)
     1027double molecule::ConstrainedPotential(ofstream *out, atom **PermutationMap, int startstep, int endstep, double *constants, bool IsAngstroem)
    10281028{
    10291029  double result = 0., tmp;
     
    10381038    Walker = Walker->next;
    10391039    // first term: distance to target
    1040     Runner = FindAtom(permutation[Walker->nr]);   // find target point
    1041     result += constants[0] * (Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Runner].R.at(endstep)));
     1040    Runner = PermutationMap[Walker->nr];   // find target point
     1041    tmp = (Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Runner].R.at(endstep)));
     1042    tmp *= IsAngstroem ? 1. : 1./AtomicLengthToAngstroem;
     1043    result += constants[0] * tmp;
    10421044   
    10431045    // second term: sum of distances to other trajectories
     
    10461048      Runner = Runner->next;
    10471049      // determine normalized trajectories direction vector (n1, n2)
    1048       Sprinter = FindAtom(permutation[Walker->nr]);   // find target point
     1050      Sprinter = PermutationMap[Walker->nr];   // find target point
    10491051      trajectory1.CopyVector(&Trajectories[Sprinter].R.at(endstep));
    10501052      trajectory1.SubtractVector(&Trajectories[Walker].R.at(startstep));
    10511053      trajectory1.Normalize();
    1052       Sprinter = FindAtom(permutation[Runner->nr]);   // find target point
     1054      Sprinter = PermutationMap[Runner->nr];   // find target point
    10531055      trajectory2.CopyVector(&Trajectories[Sprinter].R.at(endstep));
    10541056      trajectory2.SubtractVector(&Trajectories[Runner].R.at(startstep));
     
    10881090          *out << "Test: ok.\tDistance of " << tmp << " is correct." << endl; 
    10891091        } else {
    1090           *out << "Test: failed.\tDifference in intersection is ";
     1092          *out << "Test: failed.\tIntersection is off by ";
    10911093          *out << TestVector;
    10921094          *out << "." << endl; 
     
    10941096      }
    10951097      // add up
     1098      tmp *= IsAngstroem ? 1. : 1./AtomicLengthToAngstroem;
    10961099      result += constants[1] * 1./tmp;
    10971100    }
     
    11011104    while (Runner->next != end) {
    11021105      Runner = Runner->next;
    1103       if ((permutation[Walker->nr] == permutation[Runner->nr]) && (Walker->nr < Runner->nr)) {
    1104         Sprinter = FindAtom(permutation[Walker->nr]);
     1106      if ((PermutationMap[Walker->nr] == PermutationMap[Runner->nr]) && (Walker->nr < Runner->nr)) {
     1107        Sprinter = PermutationMap[Walker->nr];
    11051108        *out << *Walker << " and " << *Runner << " are heading to the same target at ";
    11061109        *out << Trajectories[Sprinter].R.at(endstep);
     
    11141117};
    11151118
     1119void PrintPermutationMap(ofstream *out, atom **PermutationMap, int Nr)
     1120{
     1121  stringstream zeile1, zeile2;
     1122  zeile1 << "PermutationMap: ";
     1123  zeile2 << "                ";
     1124  for (int i=0;i<Nr;i++) {
     1125    zeile1 << i << "\t";
     1126    zeile2 << PermutationMap[i]->nr << "\t";
     1127  }
     1128  *out << zeile1 << endl << zeile2 << endl;
     1129};
     1130
    11161131/** Minimises the extra potential for constrained molecular dynamics and gives forces and the constrained potential energy.
    11171132 * We do the following:
    1118  *  -# First, we minimise the potential, see molecule::ConstrainedPotential()
     1133 *  -# Generate a distance list from all source to all target points
     1134 *  -# Sort this per source point
     1135 *  -# Take for each source point the target point with minimum distance, use this as initial permutation
     1136 *  -# check whether molecule::ConstrainedPotential() is greater than injective penalty
     1137 *     -# If so, we go through each source point, stepping down in the sorted target point distance list and re-checking potential.
     1138 *  -# Next, we only apply transformations that keep the injectivity of the permutations list.
     1139 *  -# Hence, we for one source point we step down the ladder and seek the corresponding owner of this new target
     1140 *     point and try to change it for one with lesser distance, or for the next one with greater distance, but only
     1141 *     if this decreases the conditional potential.
     1142 *  -# finished.
    11191143 *  -# Then, we calculate the forces by taking the spatial derivative, where we scale the potential to such a degree,
    11201144 *     that the total force is always pointing in direction of the constraint force (ensuring that we move in the
     
    11231147 * \param *out output stream for debugging
    11241148 * \param *Force ForceMatrix containing force vectors from the external energy functional minimisation.
    1125  * \param targetstep target step between which and the predecessor we perform the constrained MD
     1149 * \param startstep current MD step giving initial position between which and \a endstep we perform the constrained MD (as further steps are always concatenated)
     1150 * \param endstep step giving final position in constrained MD
     1151 * \param IsAngstroem whether coordinates are in angstroem (true) or bohrradius (false)
    11261152 * \sa molecule::VerletForceIntegration()
    11271153 * \return potential energy
    11281154 */
    1129 double molecule::MinimiseConstrainedPotential(ofstream *out, ForceMatrix *Force, int targetstep)
    1130 {
    1131   double potential = 0.;
    1132   // Minimise the potential
    1133  
    1134   // evaluate forces
    1135  
    1136   // evaluate potential and return
    1137   return potential;
     1155double molecule::MinimiseConstrainedPotential(ofstream *out, ForceMatrix *Force, int startstep, int endstep, bool IsAngstroem)
     1156{
     1157  double Potential, OldPotential;
     1158  atom **PermutationMap = (atom **) Malloc(AtomCount*sizeof(atom *), "molecule::MinimiseConstrainedPotential: *PermutationMap");
     1159  DistanceMap **DistanceList = (DistanceMap **) Malloc(AtomCount*sizeof(DistanceMap *), "molecule::MinimiseConstrainedPotential: **DistanceList");
     1160  DistanceMap::iterator *DistanceIterators = (DistanceMap::iterator *) Malloc(AtomCount*sizeof(DistanceMap::iterator), "molecule::MinimiseConstrainedPotential: *DistanceIterators");
     1161  double constants[3];
     1162  atom *Walker = NULL, *Runner = NULL, *Sprinter = NULL;
     1163
     1164  /// Minimise the potential
     1165  // set constants (TODO)
     1166  constants[0] = 10.;
     1167  constants[1] = 1.;
     1168  constants[2] = 1e+7;    // just a huge penalty
     1169  // generate the distance list
     1170  *out << Verbose(1) << "Generating the distance list ... " << endl;
     1171  for (int i=AtomCount; i--;) {
     1172    DistanceList[i] = new DistanceMap;
     1173    DistanceList[i]->clear();
     1174  }
     1175  Walker = start;
     1176  while (Walker->next != NULL) {
     1177    Walker = Walker->next;
     1178    Runner = start;
     1179    while(Runner->next != NULL) {
     1180      Runner = Runner->next;
     1181      DistanceList[Walker->nr]->insert( DistancePair(Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Runner].R.at(endstep)), Runner) );
     1182    }
     1183  }
     1184  // create the initial PermutationMap
     1185  Walker = start;
     1186  while (Walker->next != NULL) {
     1187    Walker = Walker->next;
     1188    PermutationMap[Walker->nr] = DistanceList[Walker->nr]->begin()->second;
     1189    DistanceIterators[Walker->nr] = DistanceList[Walker->nr]->begin();
     1190    *out << *Walker << " starts with distance " << DistanceList[Walker->nr]->begin()->first << "." << endl;
     1191  }
     1192  // make the PermutationMap injective
     1193  *out << Verbose(1) << "Making the PermutationMap injective ... " << endl;
     1194  Walker = start;
     1195  while ((OldPotential = fabs(ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem)) > constants[2])) {
     1196    PrintPermutationMap(out, PermutationMap, AtomCount);
     1197    Walker = Walker->next;
     1198    if (Walker == end) // round-robin at the end
     1199      Walker = start->next;
     1200    DistanceIterators[Walker->nr]++;  // take next further distance in distance to targets list
     1201    PermutationMap[Walker->nr] = DistanceIterators[Walker->nr]->second;
     1202  }
     1203  // argument minimise the constrained potential in this injective PermutationMap
     1204  *out << Verbose(1) << "Argument minimising the PermutationMap ... " << endl;
     1205  do {
     1206    PrintPermutationMap(out, PermutationMap, AtomCount);
     1207    Walker = start;
     1208    while (Walker->next != end) { // pick one
     1209      Walker = Walker->next;
     1210      Sprinter = DistanceIterators[Walker->nr]->second;   // store initial partner
     1211      DistanceIterators[Walker->nr]++;  // take next farther distance target
     1212      PermutationMap[Walker->nr] = DistanceIterators[Walker->nr]->second;
     1213      Runner = start;
     1214      while(Runner->next != end) { // find the other whose toes were stepping on (this target should be used by another already
     1215        Runner = Runner->next;
     1216        if (PermutationMap[Runner->nr] == DistanceIterators[Walker->nr]->second)
     1217          break;
     1218      }
     1219      if (Runner->next != end) { // we found one a tripel
     1220        // then look in distance list for Sprinter
     1221        DistanceMap::iterator Rider = DistanceList[Walker->nr]->begin();
     1222        for (; Rider != DistanceList[Walker->nr]->end(); Rider++)
     1223          if (Rider->second == Sprinter)
     1224            break;
     1225        if (Rider != DistanceList[Walker->nr]->end()) { // if we have found one
     1226          // exchange the second also
     1227          PermutationMap[Runner->nr] = Rider->second;
     1228          // calculate the new potential
     1229          Potential = ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem);
     1230          if (Potential > OldPotential) { // we made everything worse! Undo ...
     1231            // Undo for Walker
     1232            DistanceIterators[Walker->nr]--;  // take next farther distance target
     1233            PermutationMap[Walker->nr] = Sprinter;
     1234            // Undo for Runner (note, we haven't moved the iteration yet, we may use this)
     1235            PermutationMap[Runner->nr] = DistanceIterators[Runner->nr]->second;
     1236          } else {
     1237            DistanceIterators[Runner->nr] = Rider;  // if successful also move the pointer in the iterator list
     1238            OldPotential = Potential;
     1239            *out << "Found a better permutation, new potential is " << OldPotential << "." << endl;
     1240            break;
     1241          }
     1242          if (Potential > constants[2])
     1243            cerr << "ERROR: The two-step permutation procedure did not maintain injectivity!" << endl;
     1244        }
     1245      } else {
     1246        DistanceIterators[Walker->nr]--;  // take next farther distance target
     1247        PermutationMap[Walker->nr] = DistanceIterators[Walker->nr]->second;
     1248      }
     1249    }
     1250  } while (Walker->next != end);
     1251
     1252  /// evaluate forces (only the distance to target dependent part) with the final PermutationMap
     1253  *out << Verbose(1) << "Calculating forces and adding onto ForceMatrix ... " << endl;
     1254  Walker = start;
     1255  while (Walker->next != NULL) {
     1256    Walker = Walker->next;
     1257    Sprinter = PermutationMap[Walker->nr];
     1258    // set forces
     1259    for (int i=NDIM;i++;)
     1260      Force->Matrix[0][Walker->nr][5+i] += 2.*constants[0]*sqrt(Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Sprinter].R.at(endstep)));
     1261  } 
     1262 
     1263  /// evaluate potential, free memory and return
     1264  for (int i=AtomCount; i--;)
     1265    DistanceList[i]->clear();
     1266  Free((void **)&DistanceList, "molecule::MinimiseConstrainedPotential: **DistanceList");
     1267  Free((void **)&DistanceIterators, "molecule::MinimiseConstrainedPotential: *DistanceIterators");
     1268  Free((void **)&PermutationMap, "molecule::MinimiseConstrainedPotential: *PermutationMap");
     1269  return ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem);
    11381270};
    11391271
     
    11881320    // solve a constrained potential if we are meant to
    11891321    if (DoConstrained) {
    1190       ConstrainedPotentialEnergy = MinimiseConstrainedPotential(out, &Force, DoConstrained);
     1322      // calculate forces and potential
     1323      ConstrainedPotentialEnergy = MinimiseConstrainedPotential(out, &Force, DoConstrained, 0, IsAngstroem);
    11911324    }
    11921325   
Note: See TracChangeset for help on using the changeset viewer.