Changeset 85bac0


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:
c30cda
Parents:
a1fe77
git-author:
Frederik Heber <heber@…> (09/09/08 15:29:58)
git-committer:
Frederik Heber <heber@…> (09/11/08 13:28:25)
Message:

Implemented molecule::LinearInterpolationBetweenConfiguration().

command line option "-L" with start and end step performs a linear interpolation between two atomic configurations. So far the mapping from initial atom labels to final labels is not yet finished, it is injective, but not yet minimal.

Location:
src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/builder.cpp

    ra1fe77 r85bac0  
    820820            cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl;
    821821            cout << "\t-P <file>\tParse given forces file and append as an MD step to config file via Verlet." << endl;
     822            cout << "\t-L <step0> <step1> <prefix>\tStore a linear interpolation between two configurations <step0> and <step1> into single config files with prefix <prefix> and as Trajectories into the current config file." << endl;
    822823            cout << "\t-r\t\tConvert file from an old pcp syntax." << endl;
    823824            cout << "\t-t x1 x2 x3\tTranslate all atoms by this vector (x1,x2,x3)." << endl;
     
    989990              argptr+=1;
    990991              break;
     992            case 'L':
     993              ExitFlag = 1;
     994              SaveFlag = true;
     995              cout << Verbose(1) << "Linear interpolation between configuration " << argv[argptr] << " and " << argv[argptr+1] << "." << endl;
     996              if (!mol->LinearInterpolationBetweenConfiguration((ofstream *)&cout, atoi(argv[argptr]), atoi(argv[argptr+1]), argv[argptr+2], configuration))
     997                cout << Verbose(2) << "Could not store " << argv[argptr+2] << " files." << endl;
     998              else
     999                cout << Verbose(2) << "Steps created and " << argv[argptr+2] << " files stored." << endl;
     1000              argptr+=3;
     1001              break;
    9911002            case 'P':
    9921003              ExitFlag = 1;
  • src/moleculelist.cpp

    ra1fe77 r85bac0  
    378378 * \param *configuration standard configuration to attach atoms in fragment molecule to.
    379379 * \param *SortIndex Index to map from the BFS labeling to the sequence how of Ion_Type in the config
     380 * \param DoPeriodic true - call ScanForPeriodicCorrection, false - don't
     381 * \param DoCentering true - call molecule::CenterEdge(), false - don't
    380382 * \return true - success (each file was written), false - something went wrong.
    381383 */
    382 bool MoleculeListClass::OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex)
     384bool MoleculeListClass::OutputConfigForListOfFragments(ofstream *out, const char *fragmentprefix, config *configuration, int *SortIndex, bool DoPeriodic, bool DoCentering)
    383385{
    384386  ofstream outputFragment;
     
    404406
    405407    // correct periodic
    406     ListOfMolecules[i]->ScanForPeriodicCorrection(out);
     408    if (DoPeriodic)
     409      ListOfMolecules[i]->ScanForPeriodicCorrection(out);
    407410
    408411    // output xyz file
    409412    FragmentNumber = FixedDigitNumber(NumberOfMolecules, FragmentCounter++);
    410     sprintf(FragmentName, "%s/%s%s.conf.xyz", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
     413    sprintf(FragmentName, "%s/%s%s.conf.xyz", configuration->configpath, fragmentprefix, FragmentNumber);
    411414    outputFragment.open(FragmentName, ios::out);
    412     *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter-1 << " as XYZ ...";
     415    *out << Verbose(2) << "Saving " << fragmentprefix << " No. " << FragmentNumber << "/" << FragmentCounter-1 << " as XYZ ...";
    413416    if ((intermediateResult = ListOfMolecules[i]->OutputXYZ(&outputFragment)))
    414417      *out << " done." << endl;
     
    429432   
    430433    // center on edge
    431     ListOfMolecules[i]->CenterEdge(out, &BoxDimension);
    432     ListOfMolecules[i]->SetBoxDimension(&BoxDimension);  // update Box of atoms by boundary
    433     int j = -1;
    434     for (int k=0;k<NDIM;k++) {
    435       j += k+1;
    436       BoxDimension.x[k] = 2.5* (configuration->GetIsAngstroem() ? 1. : 1./AtomicLengthToAngstroem);
    437       ListOfMolecules[i]->cell_size[j] += BoxDimension.x[k]*2.;
    438     }
    439     ListOfMolecules[i]->Translate(&BoxDimension);
     434    if (DoCentering) {
     435      ListOfMolecules[i]->CenterEdge(out, &BoxDimension);
     436      ListOfMolecules[i]->SetBoxDimension(&BoxDimension);  // update Box of atoms by boundary
     437      int j = -1;
     438      for (int k=0;k<NDIM;k++) {
     439        j += k+1;
     440        BoxDimension.x[k] = 2.5* (configuration->GetIsAngstroem() ? 1. : 1./AtomicLengthToAngstroem);
     441        ListOfMolecules[i]->cell_size[j] += BoxDimension.x[k]*2.;
     442      }
     443      ListOfMolecules[i]->Translate(&BoxDimension);
     444    }
    440445
    441446    // also calculate necessary orbitals
     
    445450    // change path in config
    446451    //strcpy(PathBackup, configuration->configpath);
    447     sprintf(FragmentName, "%s/%s%s/", PathBackup, FRAGMENTPREFIX, FragmentNumber);
     452    sprintf(FragmentName, "%s/%s%s/", PathBackup, fragmentprefix, FragmentNumber);
    448453    configuration->SetDefaultPath(FragmentName);
    449454   
    450455    // and save as config
    451     sprintf(FragmentName, "%s/%s%s.conf", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
     456    sprintf(FragmentName, "%s/%s%s.conf", configuration->configpath, fragmentprefix, FragmentNumber);
    452457    outputFragment.open(FragmentName, ios::out);
    453     *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter-1 << " as config ...";
     458    *out << Verbose(2) << "Saving " << fragmentprefix << " No. " << FragmentNumber << "/" << FragmentCounter-1 << " as config ...";
    454459    if ((intermediateResult = configuration->Save(&outputFragment, ListOfMolecules[i]->elemente, ListOfMolecules[i])))
    455460      *out << " done." << endl;
     
    465470
    466471    // and save as mpqc input file
    467     sprintf(FragmentName, "%s/%s%s.in", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
     472    sprintf(FragmentName, "%s/%s%s.in", configuration->configpath, fragmentprefix, FragmentNumber);
    468473    outputFragment.open(FragmentName, ios::out);
    469     *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter-1 << " as mpqc input ...";
     474    *out << Verbose(2) << "Saving " << fragmentprefix << " No. " << FragmentNumber << "/" << FragmentCounter-1 << " as mpqc input ...";
    470475    if ((intermediateResult = configuration->SaveMPQC(&outputFragment, ListOfMolecules[i])))
    471476      *out << " done." << endl;
  • src/molecules.cpp

    ra1fe77 r85bac0  
    10081008
    10091009/** Evaluates the potential energy used for constrained molecular dynamics.
    1010  * \f$V_i^{con} = c^{bond} \cdot | r_{P(i)} - R_i | + sum_{i \neq j} C^{min} \cdot \tfrac{1}{C_{ij}} + C^{inj} \Bigl (1 - \theta \bigl (\prod_{i \neq j} (P(i) - P(j)) \bigr ) \Bigr )\f$
     1010 * \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$
    10111011 *     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}$ is minimum distance between
    10121012 *     trajectories i and j) and the third term is a penalty for two atoms trying to each the same target point.
     
    10241024 * \return potential energy
    10251025 * \note This routine is scaling quadratically which is not optimal.
     1026 * \todo There's a bit double counting going on for the first time, bu nothing to worry really about.
    10261027 */
    10271028double molecule::ConstrainedPotential(ofstream *out, atom **PermutationMap, int startstep, int endstep, double *constants, bool IsAngstroem)
    10281029{
    1029   double result = 0., tmp;
     1030  double result = 0., tmp, Norm1, Norm2;
    10301031  atom *Walker = NULL, *Runner = NULL, *Sprinter = NULL;
    10311032  Vector trajectory1, trajectory2, normal, TestVector;
     
    10421043    tmp *= IsAngstroem ? 1. : 1./AtomicLengthToAngstroem;
    10431044    result += constants[0] * tmp;
     1045    //*out << Verbose(4) << "Adding " << tmp*constants[0] << "." << endl;
    10441046   
    10451047    // second term: sum of distances to other trajectories
     
    10471049    while (Runner->next != end) {
    10481050      Runner = Runner->next;
     1051      if (Runner == Walker) // hence, we only go up to the Walker, not beyond (similar to i=0; i<j; i++)
     1052        break;
    10491053      // determine normalized trajectories direction vector (n1, n2)
    1050       Sprinter = PermutationMap[Walker->nr];   // find target point
     1054      Sprinter = PermutationMap[Walker->nr];   // find first target point
    10511055      trajectory1.CopyVector(&Trajectories[Sprinter].R.at(endstep));
    10521056      trajectory1.SubtractVector(&Trajectories[Walker].R.at(startstep));
    10531057      trajectory1.Normalize();
    1054       Sprinter = PermutationMap[Runner->nr];   // find target point
     1058      Norm1 = trajectory1.Norm();
     1059      Sprinter = PermutationMap[Runner->nr];   // find second target point
    10551060      trajectory2.CopyVector(&Trajectories[Sprinter].R.at(endstep));
    10561061      trajectory2.SubtractVector(&Trajectories[Runner].R.at(startstep));
    10571062      trajectory2.Normalize();
    1058       // check whether they're linear dependent
    1059       if (fabs(trajectory1.ScalarProduct(&trajectory2)/trajectory1.Norm()/trajectory2.Norm() - 1.) < MYEPSILON) {
    1060         *out << "Both trajectories of " << *Walker << " and " << *Runner << " are linear dependent: ";
    1061         *out << trajectory1;
    1062         *out << " and ";
    1063         *out << trajectory2 << endl;
     1063      Norm2 = trajectory1.Norm();
     1064      // check whether either is zero()
     1065      if ((Norm1 < MYEPSILON) && (Norm2 < MYEPSILON)) {
    10641066        tmp = Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Runner].R.at(startstep));
     1067      } else if (Norm1 < MYEPSILON) {
     1068        Sprinter = PermutationMap[Walker->nr];   // find first target point
     1069        trajectory1.CopyVector(&Trajectories[Sprinter].R.at(endstep));  // copy first offset
     1070        trajectory1.SubtractVector(&Trajectories[Runner].R.at(startstep));  // subtract second offset
     1071        trajectory2.Scale( trajectory1.ScalarProduct(&trajectory2) ); // trajectory2 is scaled to unity, hence we don't need to divide by anything
     1072        trajectory1.SubtractVector(&trajectory2);   // project the part in norm direction away
     1073        tmp = trajectory1.Norm();  // remaining norm is distance
     1074      } else if (Norm2 < MYEPSILON) {
     1075        Sprinter = PermutationMap[Runner->nr];   // find second target point
     1076        trajectory2.CopyVector(&Trajectories[Sprinter].R.at(endstep));  // copy second offset
     1077        trajectory2.SubtractVector(&Trajectories[Walker].R.at(startstep));  // subtract first offset
     1078        trajectory1.Scale( trajectory2.ScalarProduct(&trajectory1) ); // trajectory1 is scaled to unity, hence we don't need to divide by anything
     1079        trajectory2.SubtractVector(&trajectory1);   // project the part in norm direction away
     1080        tmp = trajectory2.Norm();  // remaining norm is distance
     1081      } else if ((fabs(trajectory1.ScalarProduct(&trajectory2)/Norm1/Norm2) - 1.) < MYEPSILON) { // check whether they're linear dependent
     1082//        *out << Verbose(3) << "Both trajectories of " << *Walker << " and " << *Runner << " are linear dependent: ";
     1083//        *out << trajectory1;
     1084//        *out << " and ";
     1085//        *out << trajectory2;
     1086        tmp = Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Runner].R.at(startstep));
     1087//        *out << " with distance " << tmp << "." << endl;
    10651088      } else { // determine distance by finding minimum distance
    1066         *out << "Both trajectories of " << *Walker << " and " << *Runner << " are linear independent." << endl;
     1089//        *out << Verbose(3) << "Both trajectories of " << *Walker << " and " << *Runner << " are linear independent ";
     1090//        *out << endl;
     1091//        *out << "First Trajectory: ";
     1092//        *out << trajectory1 << endl;
     1093//        *out << "Second Trajectory: ";
     1094//        *out << trajectory2 << endl;
    10671095        // determine normal vector for both
    10681096        normal.MakeNormalVector(&trajectory1, &trajectory2);
     1097        // print all vectors for debugging
     1098//        *out << "Normal vector in between: ";
     1099//        *out << normal << endl;
    10691100        // setup matrix
    10701101        for (int i=NDIM;i--;) {
     
    10771108        gsl_linalg_HH_svx(A, x);
    10781109        // distance from last component
    1079         tmp = gsl_vector_get(x,2);   
     1110        tmp = gsl_vector_get(x,2);
     1111//        *out << " with distance " << tmp << "." << endl;
    10801112        // test whether we really have the intersection (by checking on c_1 and c_2)
    10811113        TestVector.CopyVector(&Trajectories[Runner].R.at(startstep));
     
    10881120        TestVector.SubtractVector(&trajectory1);
    10891121        if (TestVector.Norm() < MYEPSILON) {
    1090           *out << "Test: ok.\tDistance of " << tmp << " is correct." << endl; 
     1122//          *out << Verbose(2) << "Test: ok.\tDistance of " << tmp << " is correct." << endl; 
    10911123        } else {
    1092           *out << "Test: failed.\tIntersection is off by ";
    1093           *out << TestVector;
    1094           *out << "." << endl; 
     1124//          *out << Verbose(2) << "Test: failed.\tIntersection is off by ";
     1125//          *out << TestVector;
     1126//          *out << "." << endl; 
    10951127        }
    10961128      }
    10971129      // add up
    10981130      tmp *= IsAngstroem ? 1. : 1./AtomicLengthToAngstroem;
    1099       result += constants[1] * 1./tmp;
     1131      if (fabs(tmp) > MYEPSILON) {
     1132        result += constants[1] * 1./tmp;
     1133        //*out << Verbose(4) << "Adding " << 1./tmp*constants[1] << "." << endl;
     1134      }
    11001135    }
    11011136     
     
    11061141      if ((PermutationMap[Walker->nr] == PermutationMap[Runner->nr]) && (Walker->nr < Runner->nr)) {
    11071142        Sprinter = PermutationMap[Walker->nr];
    1108         *out << *Walker << " and " << *Runner << " are heading to the same target at ";
    1109         *out << Trajectories[Sprinter].R.at(endstep);
    1110         *out << ", penalting." << endl;
     1143//        *out << *Walker << " and " << *Runner << " are heading to the same target at ";
     1144//        *out << Trajectories[Sprinter].R.at(endstep);
     1145//        *out << ", penalting." << endl;
    11111146        result += constants[2];
     1147        //*out << Verbose(4) << "Adding " << constants[2] << "." << endl;
    11121148      }
    11131149    }
     
    11231159  zeile2 << "                ";
    11241160  for (int i=0;i<Nr;i++) {
    1125     zeile1 << i << "\t";
    1126     zeile2 << PermutationMap[i]->nr << "\t";
    1127   }
    1128   *out << zeile1 << endl << zeile2 << endl;
     1161    zeile1 << i << " ";
     1162    zeile2 << PermutationMap[i]->nr << " ";
     1163  }
     1164//  *out << zeile1.str() << endl << zeile2.str() << endl;
    11291165};
    11301166
     
    11371173 *     -# If so, we go through each source point, stepping down in the sorted target point distance list and re-checking potential.
    11381174 *  -# 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
     1175 *  -# Hence, for one source point we step down the ladder and seek the corresponding owner of this new target
    11401176 *     point and try to change it for one with lesser distance, or for the next one with greater distance, but only
    11411177 *     if this decreases the conditional potential.
     
    11461182 *  -# Finally, we calculate the potential energy and return.
    11471183 * \param *out output stream for debugging
    1148  * \param *Force ForceMatrix containing force vectors from the external energy functional minimisation.
     1184 * \param **PermutationMap on return: mapping between the atom label of the initial and the final configuration
    11491185 * \param startstep current MD step giving initial position between which and \a endstep we perform the constrained MD (as further steps are always concatenated)
    11501186 * \param endstep step giving final position in constrained MD
    11511187 * \param IsAngstroem whether coordinates are in angstroem (true) or bohrradius (false)
    11521188 * \sa molecule::VerletForceIntegration()
    1153  * \return potential energy
    1154  */
    1155 double molecule::MinimiseConstrainedPotential(ofstream *out, ForceMatrix *Force, int startstep, int endstep, bool IsAngstroem)
     1189 * \return potential energy (and allocated **PermutationMap (array of molecule::AtomCount ^2)
     1190 * \todo The constrained potential's constants are set to fixed values right now, but they should scale based on checks of the system in order
     1191 *       to ensure they're properties (e.g. constants[2] always greater than the energy of the system).
     1192 * \bug this all is not O(N log N) but O(N^2)
     1193 */
     1194double molecule::MinimiseConstrainedPotential(ofstream *out, atom **&PermutationMap, int startstep, int endstep, bool IsAngstroem)
    11561195{
    11571196  double Potential, OldPotential;
    1158   atom **PermutationMap = (atom **) Malloc(AtomCount*sizeof(atom *), "molecule::MinimiseConstrainedPotential: *PermutationMap");
     1197  PermutationMap = (atom **) Malloc(AtomCount*sizeof(atom *), "molecule::MinimiseConstrainedPotential: **PermutationMap");
    11591198  DistanceMap **DistanceList = (DistanceMap **) Malloc(AtomCount*sizeof(DistanceMap *), "molecule::MinimiseConstrainedPotential: **DistanceList");
    1160   DistanceMap::iterator *DistanceIterators = (DistanceMap::iterator *) Malloc(AtomCount*sizeof(DistanceMap::iterator), "molecule::MinimiseConstrainedPotential: *DistanceIterators");
     1199  DistanceMap::iterator *DistanceIterators = (DistanceMap::iterator *) Malloc(AtomCount*sizeof(DistanceMap::iterator), "molecule::MinimiseConstrainedPotential: *DistanceIterators");
     1200  int *DoubleList = (int *) Malloc(AtomCount*sizeof(int), "molecule::MinimiseConstrainedPotential: *DoubleList");
    11611201  double constants[3];
    11621202  atom *Walker = NULL, *Runner = NULL, *Sprinter = NULL;
    1163 
     1203  DistanceMap::iterator Rider;
     1204 
    11641205  /// Minimise the potential
    1165   // set constants (TODO)
     1206  // set Lagrange multiplier constants
    11661207  constants[0] = 10.;
    11671208  constants[1] = 1.;
    11681209  constants[2] = 1e+7;    // just a huge penalty
    11691210  // generate the distance list
    1170   *out << Verbose(1) << "Generating the distance list ... " << endl;
     1211  *out << Verbose(1) << "Creating the distance list ... " << endl;
    11711212  for (int i=AtomCount; i--;) {
    1172     DistanceList[i] = new DistanceMap;
     1213    DoubleList[i] = 0;  // store's for how many atoms in startstep this atom is a target in endstep
     1214    DistanceList[i] = new DistanceMap;    // is the distance sorted target list per atom
    11731215    DistanceList[i]->clear();
    11741216  }
     1217  *out << Verbose(1) << "Filling the distance list ... " << endl;
    11751218  Walker = start;
    1176   while (Walker->next != NULL) {
     1219  while (Walker->next != end) {
    11771220    Walker = Walker->next;
    11781221    Runner = start;
    1179     while(Runner->next != NULL) {
     1222    while(Runner->next != end) {
    11801223      Runner = Runner->next;
    11811224      DistanceList[Walker->nr]->insert( DistancePair(Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Runner].R.at(endstep)), Runner) );
    11821225    }
    11831226  }
    1184   // create the initial PermutationMap
     1227  // create the initial PermutationMap (source -> target)
    11851228  Walker = start;
    1186   while (Walker->next != NULL) {
     1229  while (Walker->next != end) {
    11871230    Walker = Walker->next;
    1188     PermutationMap[Walker->nr] = DistanceList[Walker->nr]->begin()->second;
    1189     DistanceIterators[Walker->nr] = DistanceList[Walker->nr]->begin();
     1231    PermutationMap[Walker->nr] = DistanceList[Walker->nr]->begin()->second;   // always pick target with the smallest distance
     1232    DoubleList[DistanceList[Walker->nr]->begin()->second->nr]++;            // increase this target's source count (>1? not injective)
     1233    DistanceIterators[Walker->nr] = DistanceList[Walker->nr]->begin();    // and remember which one we picked
    11901234    *out << *Walker << " starts with distance " << DistanceList[Walker->nr]->begin()->first << "." << endl;
    11911235  }
    1192   // make the PermutationMap injective
     1236  *out << Verbose(1) << "done." << endl;
     1237  // make the PermutationMap injective by checking whether we have a non-zero constants[2] term in it
    11931238  *out << Verbose(1) << "Making the PermutationMap injective ... " << endl;
    11941239  Walker = start;
    1195   while ((OldPotential = fabs(ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem)) > constants[2])) {
     1240  DistanceMap::iterator NewBase;
     1241  OldPotential = fabs(ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem));
     1242  while ((OldPotential) > constants[2]) {
    11961243    PrintPermutationMap(out, PermutationMap, AtomCount);
    11971244    Walker = Walker->next;
    11981245    if (Walker == end) // round-robin at the end
    11991246      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   }
     1247    if (DoubleList[DistanceIterators[Walker->nr]->second->nr] <= 1)  // no need to make those injective that aren't
     1248      continue;
     1249    // now, try finding a new one
     1250    NewBase = DistanceIterators[Walker->nr];  // store old base
     1251    do {
     1252      NewBase++;  // take next further distance in distance to targets list that's a target of no one
     1253    } while ((DoubleList[NewBase->second->nr] != 0) && (NewBase != DistanceList[Walker->nr]->end()));
     1254    if (NewBase != DistanceList[Walker->nr]->end()) {
     1255      DoubleList[DistanceIterators[Walker->nr]->second->nr]--;  // decrease the old entry in the doubles list
     1256      DoubleList[NewBase->second->nr]++;    // increase the old entry in the doubles list
     1257      PermutationMap[Walker->nr] = NewBase->second;
     1258      Potential = fabs(ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem));
     1259      if (Potential > OldPotential) { // undo
     1260        DoubleList[NewBase->second->nr]--;
     1261        DistanceIterators[Walker->nr] = NewBase;
     1262        PermutationMap[Walker->nr] = DistanceIterators[Walker->nr]->second;
     1263        DoubleList[DistanceIterators[Walker->nr]->second->nr]++;
     1264      } else {
     1265        OldPotential = Potential;
     1266        *out << Verbose(3) << "Found a new permutation, new potential is " << OldPotential << "." << endl;
     1267      }
     1268    }
     1269  }
     1270  for (int i=AtomCount; i--;) // now each single entry in the DoubleList should be <=1
     1271    if (DoubleList[i] > 1) {
     1272      cerr << "Failed to create an injective PermutationMap!" << endl;
     1273      exit(1);
     1274    }
     1275  *out << Verbose(1) << "done." << endl;
     1276  Free((void **)&DoubleList, "molecule::MinimiseConstrainedPotential: *DoubleList");
    12031277  // argument minimise the constrained potential in this injective PermutationMap
    1204   *out << Verbose(1) << "Argument minimising the PermutationMap ... " << endl;
     1278  *out << Verbose(1) << "Argument minimising the PermutationMap, at current potential " << OldPotential << " ... " << endl;
    12051279  do {
    1206     PrintPermutationMap(out, PermutationMap, AtomCount);
    12071280    Walker = start;
    12081281    while (Walker->next != end) { // pick one
    12091282      Walker = Walker->next;
     1283      PrintPermutationMap(out, PermutationMap, AtomCount);
    12101284      Sprinter = DistanceIterators[Walker->nr]->second;   // store initial partner
    12111285      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
     1286      if (DistanceIterators[Walker->nr] == DistanceList[Walker->nr]->end()) // stop, before we run through the list and still on
     1287        break;
     1288      *out << Verbose(2) << "Current Walker: " << *Walker << " with old/next candidate " << *Sprinter << "/" << *DistanceIterators[Walker->nr]->second << "." << endl;
     1289      Runner = start->next;
     1290      while(Runner != end) { // find the other one whose toes we might be stepping on (this target should be used by another already)
     1291        if (PermutationMap[Runner->nr] == DistanceIterators[Walker->nr]->second) {
     1292          *out << Verbose(2) << "Found the corresponding owner " << *Runner << " to " << *DistanceIterators[Walker->nr]->second << "." << endl;
     1293          break;
     1294        }
    12151295        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
     1296      }
     1297      if (Runner != end) { // we found one a tripel
    12201298        // then look in distance list for Sprinter
    1221         DistanceMap::iterator Rider = DistanceList[Walker->nr]->begin();
    1222         for (; Rider != DistanceList[Walker->nr]->end(); Rider++)
     1299        Rider = DistanceList[Runner->nr]->begin();
     1300        for (; Rider != DistanceList[Runner->nr]->end(); Rider++)
    12231301          if (Rider->second == Sprinter)
    12241302            break;
    1225         if (Rider != DistanceList[Walker->nr]->end()) { // if we have found one
     1303        if (Rider != DistanceList[Runner->nr]->end()) { // if we have found one
     1304          *out << Verbose(2) << "Current Other: " << *Runner << " with old/next candidate " << *PermutationMap[Runner->nr] << "/" << *Rider->second << "." << endl;
    12261305          // exchange the second also
    1227           PermutationMap[Runner->nr] = Rider->second;
     1306          PermutationMap[Walker->nr] = DistanceIterators[Walker->nr]->second; // put next farther distance into PermutationMap
     1307          PermutationMap[Runner->nr] = Sprinter;  // and hand the old target to its respective owner
    12281308          // calculate the new potential
     1309          PrintPermutationMap(out, PermutationMap, AtomCount);
     1310          *out << Verbose(2) << "Checking new potential ..." << endl;
    12291311          Potential = ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem);
    12301312          if (Potential > OldPotential) { // we made everything worse! Undo ...
     1313            *out << Verbose(3) << "Nay, made the potential worse: " << Potential << " vs. " << OldPotential << "!" << endl;
    12311314            // Undo for Walker
    12321315            DistanceIterators[Walker->nr]--;  // take next farther distance target
     
    12341317            // Undo for Runner (note, we haven't moved the iteration yet, we may use this)
    12351318            PermutationMap[Runner->nr] = DistanceIterators[Runner->nr]->second;
     1319            Potential = OldPotential;
    12361320          } else {
    12371321            DistanceIterators[Runner->nr] = Rider;  // if successful also move the pointer in the iterator list
     1322            *out << Verbose(3) << "Found a better permutation, new potential is " << Potential << " vs." << OldPotential << "." << endl;
    12381323            OldPotential = Potential;
    1239             *out << "Found a better permutation, new potential is " << OldPotential << "." << endl;
    12401324            break;
    12411325          }
    1242           if (Potential > constants[2])
     1326          if (Potential > constants[2]) {
    12431327            cerr << "ERROR: The two-step permutation procedure did not maintain injectivity!" << endl;
     1328            exit(255);
     1329          }
     1330          *out << endl;
    12441331        }
    12451332      } else {
    1246         DistanceIterators[Walker->nr]--;  // take next farther distance target
    1247         PermutationMap[Walker->nr] = DistanceIterators[Walker->nr]->second;
     1333        DistanceIterators[Walker->nr]--;  // take old distance target
    12481334      }
    12491335    }
    12501336  } while (Walker->next != end);
    1251 
     1337  *out << Verbose(1) << "done." << endl;
     1338
     1339 
     1340  /// free memory and return with evaluated potential
     1341  for (int i=AtomCount; i--;)
     1342    DistanceList[i]->clear();
     1343  Free((void **)&DistanceList, "molecule::MinimiseConstrainedPotential: **DistanceList");
     1344  Free((void **)&DistanceIterators, "molecule::MinimiseConstrainedPotential: *DistanceIterators");
     1345  return ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem);
     1346};
     1347
     1348/** Evaluates the (distance-related part) of the constrained potential for the constrained forces.
     1349 * \param *out output stream for debugging
     1350 * \param startstep current MD step giving initial position between which and \a endstep we perform the constrained MD (as further steps are always concatenated)
     1351 * \param endstep step giving final position in constrained MD
     1352 * \param **PermutationMap mapping between the atom label of the initial and the final configuration
     1353 * \param *Force ForceMatrix containing force vectors from the external energy functional minimisation.
     1354 * \todo the constant for the constrained potential distance part is hard-coded independently of the hard-coded value in MinimiseConstrainedPotential()
     1355 */
     1356void molecule::EvaluateConstrainedForces(ofstream *out, int startstep, int endstep, atom **PermutationMap, ForceMatrix *Force)
     1357{
     1358  double constant = 10.;
     1359  atom *Walker = NULL, *Sprinter = NULL;
     1360 
    12521361  /// evaluate forces (only the distance to target dependent part) with the final PermutationMap
    12531362  *out << Verbose(1) << "Calculating forces and adding onto ForceMatrix ... " << endl;
     
    12581367    // set forces
    12591368    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)));
     1369      Force->Matrix[0][Walker->nr][5+i] += 2.*constant*sqrt(Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Sprinter].R.at(endstep)));
    12611370  } 
    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");
     1371  *out << Verbose(1) << "done." << endl;
     1372};
     1373
     1374/** Performs a linear interpolation between two desired atomic configurations with a given number of steps.
     1375 * Note, step number is config::MaxOuterStep
     1376 * \param *out output stream for debugging
     1377 * \param startstep stating initial configuration in molecule::Trajectories
     1378 * \param endstep stating final configuration in molecule::Trajectories
     1379 * \param &config configuration structure
     1380 * \return true - success in writing step files, false - error writing files or only one step in molecule::Trajectories
     1381 */
     1382bool molecule::LinearInterpolationBetweenConfiguration(ofstream *out, int startstep, int endstep, const char *prefix, config &configuration)
     1383{
     1384  bool status = true;
     1385  int MaxSteps = configuration.MaxOuterStep;
     1386  MoleculeListClass *MoleculePerStep = new MoleculeListClass(MaxSteps+1, AtomCount);
     1387  // Get the Permutation Map by MinimiseConstrainedPotential
     1388  atom **PermutationMap = NULL;
     1389  atom *Walker = NULL, *Sprinter = NULL;
     1390  MinimiseConstrainedPotential(out, PermutationMap, startstep, endstep, configuration.GetIsAngstroem());
     1391
     1392  // check whether we have sufficient space in Trajectories for each atom
     1393  Walker = start;
     1394  while (Walker->next != end) {
     1395    Walker = Walker->next;
     1396    if (Trajectories[Walker].R.size() <= (unsigned int)(MaxSteps)) {
     1397      //cout << "Increasing size for trajectory array of " << keyword << " to " << (MaxSteps+1) << "." << endl;
     1398      Trajectories[Walker].R.resize(MaxSteps+1);
     1399      Trajectories[Walker].U.resize(MaxSteps+1);
     1400      Trajectories[Walker].F.resize(MaxSteps+1);
     1401    }
     1402  }
     1403  // push endstep to last one
     1404  Walker = start;
     1405  while (Walker->next != end) { // remove the endstep (is now the very last one)
     1406    Walker = Walker->next;
     1407    for (int n=NDIM;n--;) {
     1408      Trajectories[Walker].R.at(MaxSteps).x[n] = Trajectories[Walker].R.at(endstep).x[n];
     1409      Trajectories[Walker].U.at(MaxSteps).x[n] = Trajectories[Walker].U.at(endstep).x[n];
     1410      Trajectories[Walker].F.at(MaxSteps).x[n] = Trajectories[Walker].F.at(endstep).x[n];
     1411    }
     1412  }
     1413  endstep = MaxSteps;
     1414 
     1415  // go through all steps and add the molecular configuration to the list and to the Trajectories of \a this molecule
     1416  *out << Verbose(1) << "Filling intermediate " << MaxSteps << " steps with MDSteps of " << MDSteps << "." << endl;
     1417  for (int step = 0; step <= MaxSteps; step++) {
     1418    MoleculePerStep->ListOfMolecules[step] = new molecule(elemente);
     1419    Walker = start;
     1420    while (Walker->next != end) {
     1421      Walker = Walker->next;
     1422      // add to molecule list
     1423      Sprinter = MoleculePerStep->ListOfMolecules[step]->AddCopyAtom(Walker);
     1424      for (int n=NDIM;n--;) {
     1425        Sprinter->x.x[n] = Trajectories[Walker].R.at(startstep).x[n] + (Trajectories[PermutationMap[Walker->nr]].R.at(endstep).x[n] - Trajectories[Walker].R.at(startstep).x[n])*((double)step/(double)MaxSteps);
     1426        // add to Trajectories
     1427        //*out << Verbose(3) << step << ">=" << MDSteps-1 << endl;
     1428        //if (step >= MDSteps-1) {
     1429          Trajectories[Walker].R.at(step).x[n] = Trajectories[Walker].R.at(startstep).x[n] + (Trajectories[PermutationMap[Walker->nr]].R.at(endstep).x[n] - Trajectories[Walker].R.at(startstep).x[n])*((double)step/(double)MaxSteps);
     1430          Trajectories[Walker].U.at(step).x[n] = 0.;
     1431          Trajectories[Walker].F.at(step).x[n] = 0.;
     1432        //}
     1433      }
     1434    }
     1435  }
     1436  MDSteps = MaxSteps+1;   // otherwise new Trajectories' points aren't stored on save&exit
     1437 
     1438  // store the list to single step files
     1439  int *SortIndex = (int *) Malloc(AtomCount*sizeof(int), "molecule::LinearInterpolationBetweenConfiguration: *SortIndex");
     1440  for (int i=AtomCount; i--; )
     1441    SortIndex[i] = i;
     1442  status = MoleculePerStep->OutputConfigForListOfFragments(out, "ConstrainedStep", &configuration, SortIndex, false, false);
     1443 
     1444  // free and return
    12681445  Free((void **)&PermutationMap, "molecule::MinimiseConstrainedPotential: *PermutationMap");
    1269   return ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem);
     1446  delete(MoleculePerStep);
     1447  return status;
    12701448};
    12711449
     
    12801458 * \param DoConstrained whether we perform a constrained (>0, target step in molecule::trajectories) or unconstrained (0) molecular dynamics, \sa molecule::MinimiseConstrainedPotential()
    12811459 * \return true - file found and parsed, false - file not found or imparsable
     1460 * \todo This is not yet checked if it is correctly working with DoConstrained set to true.
    12821461 */
    12831462bool molecule::VerletForceIntegration(ofstream *out, char *file, double delta_t, bool IsAngstroem, int DoConstrained)
     
    13211500    if (DoConstrained) {
    13221501      // calculate forces and potential
    1323       ConstrainedPotentialEnergy = MinimiseConstrainedPotential(out, &Force, DoConstrained, 0, IsAngstroem);
     1502      atom **PermutationMap = NULL;
     1503      ConstrainedPotentialEnergy = MinimiseConstrainedPotential(out, PermutationMap, DoConstrained, 0, IsAngstroem);
     1504      EvaluateConstrainedForces(out, DoConstrained, 0, PermutationMap, &Force);
     1505      Free((void **)&PermutationMap, "molecule::MinimiseConstrainedPotential: *PermutationMap");
    13241506    }
    13251507   
     
    32923474     
    32933475      *out << Verbose(1) << "Writing " << BondFragments->NumberOfMolecules << " possible bond fragmentation configs" << endl;
    3294       if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex))
     3476      if (BondFragments->OutputConfigForListOfFragments(out, FRAGMENTPREFIX, configuration, SortIndex, true, true))
    32953477        *out << Verbose(1) << "All configs written." << endl;
    32963478      else
  • src/molecules.hpp

    ra1fe77 r85bac0  
    262262        bool VerletForceIntegration(ofstream *out, char *file, double delta_t, bool IsAngstroem, int DoConstrained);
    263263        double ConstrainedPotential(ofstream *out, atom **permutation, int start, int end, double *constants, bool IsAngstroem);
    264         double MinimiseConstrainedPotential(ofstream *out, ForceMatrix *Force, int startstep, int endstep, bool IsAngstroem);
     264        double MinimiseConstrainedPotential(ofstream *out, atom **&permutation, int startstep, int endstep, bool IsAngstroem);
     265        void EvaluateConstrainedForces(ofstream *out, int startstep, int endstep, atom **PermutationMap, ForceMatrix *Force);
     266        bool LinearInterpolationBetweenConfiguration(ofstream *out, int startstep, int endstep, const char *prefix, config &configuration);
    265267       
    266268  bool CheckBounds(const Vector *x) const;
     
    340342  bool AddHydrogenCorrection(ofstream *out, char *path);
    341343  bool StoreForcesFile(ofstream *out, char *path, int *SortIndex);
    342   bool OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex);
     344  bool OutputConfigForListOfFragments(ofstream *out, const char *fragmentprefix, config *configuration, int *SortIndex, bool DoPeriodic, bool DoCentering);
    343345  void Output(ofstream *out);
    344346 
     
    389391    double Deltat;
    390392    int DoConstrainedMD;
     393    int MaxOuterStep;
    391394   
    392395    private:
     
    410413    int Seed;
    411414   
    412     int MaxOuterStep;
    413415    int OutVisStep;
    414416    int OutSrcStep;
Note: See TracChangeset for help on using the changeset viewer.