Changeset 6e9353 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:
a1fe77
Parents:
18913c
git-author:
Frederik Heber <heber@…> (09/05/08 08:22:51)
git-committer:
Frederik Heber <heber@…> (09/11/08 13:28:25)
Message:

Constrained Molecular Dynamics: two new functions molecule::ConstrainedPotential(), molecule::MinimiseConstrainedPotential()

Constrained Molecular Dynamics scaffold implemented (so far it does nothing):

  • config::DoConstrainedMD contains the target step (i.e. config::DoConstrainedMD = 2 will do a constraint motion from step 1 to step 2), 0 means no constrained motion, is parsed in config::load(), def

ault is 0

ajectory distance, equal target (last two are pure penalties). Implemented, not tested.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/molecules.cpp

    r18913c r6e9353  
    10071007};
    10081008
     1009/** 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$
     1011 *     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
     1012 *     trajectories i and j) and the third term is a penalty for two atoms trying to each the same target point.
     1013 * Note that for the second term we have to solve the following linear system:
     1014 * \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,
     1015 * offset vector \f$p_1\f$ in direction \f$n_1\f$, offset vector \f$p_2\f$ in direction \f$n_2\f$,
     1016 * \f$n_3\f$ is the normal vector to both directions. \f$C\f$ would be the minimum distance between the two lines.
     1017 * \sa molecule::MinimiseConstrainedPotential(), molecule::VerletForceIntegration()
     1018 * \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$)
     1020 * \param startstep start configuration (MDStep in molecule::trajectories)
     1021 * \param endstep end configuration (MDStep in molecule::trajectories)
     1022 * \param *constants constant in front of each term
     1023 * \param IsAngstroem whether coordinates are in angstroem (true) or bohrradius (false)
     1024 * \return potential energy
     1025 * \note This routine is scaling quadratically which is not optimal.
     1026 */
     1027double molecule::ConstrainedPotential(ofstream *out, int *permutation, int startstep, int endstep, double *constants, bool IsAngstroem)
     1028{
     1029  double result = 0., tmp;
     1030  atom *Walker = NULL, *Runner = NULL, *Sprinter = NULL;
     1031  Vector trajectory1, trajectory2, normal, TestVector;
     1032  gsl_matrix *A = gsl_matrix_alloc(NDIM,NDIM);
     1033  gsl_vector *x = gsl_vector_alloc(NDIM);
     1034
     1035  // go through every atom
     1036  Walker = start;
     1037  while (Walker->next != end) {
     1038    Walker = Walker->next;
     1039    // 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)));
     1042   
     1043    // second term: sum of distances to other trajectories
     1044    Runner = start;
     1045    while (Runner->next != end) {
     1046      Runner = Runner->next;
     1047      // determine normalized trajectories direction vector (n1, n2)
     1048      Sprinter = FindAtom(permutation[Walker->nr]);   // find target point
     1049      trajectory1.CopyVector(&Trajectories[Sprinter].R.at(endstep));
     1050      trajectory1.SubtractVector(&Trajectories[Walker].R.at(startstep));
     1051      trajectory1.Normalize();
     1052      Sprinter = FindAtom(permutation[Runner->nr]);   // find target point
     1053      trajectory2.CopyVector(&Trajectories[Sprinter].R.at(endstep));
     1054      trajectory2.SubtractVector(&Trajectories[Runner].R.at(startstep));
     1055      trajectory2.Normalize();
     1056      // check whether they're linear dependent
     1057      if (fabs(trajectory1.ScalarProduct(&trajectory2)/trajectory1.Norm()/trajectory2.Norm() - 1.) < MYEPSILON) {
     1058        *out << "Both trajectories of " << *Walker << " and " << *Runner << " are linear dependent: ";
     1059        *out << trajectory1;
     1060        *out << " and ";
     1061        *out << trajectory2 << endl;
     1062        tmp = Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Runner].R.at(startstep));
     1063      } else { // determine distance by finding minimum distance
     1064        *out << "Both trajectories of " << *Walker << " and " << *Runner << " are linear independent." << endl;
     1065        // determine normal vector for both
     1066        normal.MakeNormalVector(&trajectory1, &trajectory2);
     1067        // setup matrix
     1068        for (int i=NDIM;i--;) {
     1069          gsl_matrix_set(A, 0, i, trajectory1.x[i]);
     1070          gsl_matrix_set(A, 1, i, trajectory2.x[i]);
     1071          gsl_matrix_set(A, 2, i, normal.x[i]);
     1072          gsl_vector_set(x,i, (Trajectories[Walker].R.at(startstep).x[i] - Trajectories[Runner].R.at(startstep).x[i]));
     1073        }
     1074        // solve the linear system by Householder transformations
     1075        gsl_linalg_HH_svx(A, x);
     1076        // distance from last component
     1077        tmp = gsl_vector_get(x,2);   
     1078        // test whether we really have the intersection (by checking on c_1 and c_2)
     1079        TestVector.CopyVector(&Trajectories[Runner].R.at(startstep));
     1080        trajectory2.Scale(gsl_vector_get(x,1));
     1081        TestVector.AddVector(&trajectory2);
     1082        normal.Scale(gsl_vector_get(x,2));
     1083        TestVector.AddVector(&normal);
     1084        TestVector.SubtractVector(&Trajectories[Walker].R.at(startstep));
     1085        trajectory1.Scale(gsl_vector_get(x,0));
     1086        TestVector.SubtractVector(&trajectory1);
     1087        if (TestVector.Norm() < MYEPSILON) {
     1088          *out << "Test: ok.\tDistance of " << tmp << " is correct." << endl; 
     1089        } else {
     1090          *out << "Test: failed.\tDifference in intersection is ";
     1091          *out << TestVector;
     1092          *out << "." << endl; 
     1093        }
     1094      }
     1095      // add up
     1096      result += constants[1] * 1./tmp;
     1097    }
     1098     
     1099    // third term: penalty for equal targets
     1100    Runner = start;
     1101    while (Runner->next != end) {
     1102      Runner = Runner->next;
     1103      if ((permutation[Walker->nr] == permutation[Runner->nr]) && (Walker->nr < Runner->nr)) {
     1104        Sprinter = FindAtom(permutation[Walker->nr]);
     1105        *out << *Walker << " and " << *Runner << " are heading to the same target at ";
     1106        *out << Trajectories[Sprinter].R.at(endstep);
     1107        *out << ", penalting." << endl;
     1108        result += constants[2];
     1109      }
     1110    }
     1111  }
     1112 
     1113  return result;
     1114};
     1115
     1116/** Minimises the extra potential for constrained molecular dynamics and gives forces and the constrained potential energy.
     1117 * We do the following:
     1118 *  -# First, we minimise the potential, see molecule::ConstrainedPotential()
     1119 *  -# Then, we calculate the forces by taking the spatial derivative, where we scale the potential to such a degree,
     1120 *     that the total force is always pointing in direction of the constraint force (ensuring that we move in the
     1121 *     right direction).
     1122 *  -# Finally, we calculate the potential energy and return.
     1123 * \param *out output stream for debugging
     1124 * \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
     1126 * \sa molecule::VerletForceIntegration()
     1127 * \return potential energy
     1128 */
     1129double 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;
     1138};
     1139
    10091140/** Parses nuclear forces from file and performs Verlet integration.
    10101141 * Note that we assume the parsed forces to be in atomic units (hence, if coordinates are in angstroem, we
    10111142 * have to transform them).
    10121143 * This adds a new MD step to the config file.
     1144 * \param *out output stream for debugging
    10131145 * \param *file filename
    10141146 * \param delta_t time step width in atomic units
    10151147 * \param IsAngstroem whether coordinates are in angstroem (true) or bohrradius (false)
     1148 * \param DoConstrained whether we perform a constrained (>0, target step in molecule::trajectories) or unconstrained (0) molecular dynamics, \sa molecule::MinimiseConstrainedPotential()
    10161149 * \return true - file found and parsed, false - file not found or imparsable
    10171150 */
    1018 bool molecule::VerletForceIntegration(char *file, double delta_t, bool IsAngstroem)
     1151bool molecule::VerletForceIntegration(ofstream *out, char *file, double delta_t, bool IsAngstroem, int DoConstrained)
    10191152{
    10201153  element *runner = elemente->start;
     
    10241157  string token;
    10251158  stringstream item;
    1026   double a, IonMass, Vector[NDIM];
     1159  double a, IonMass, Vector[NDIM], ConstrainedPotentialEnergy;
    10271160  ForceMatrix Force;
    10281161
     
    10531186        Force.Matrix[0][i][d+5] -= Vector[d]/(double)AtomCount;
    10541187      }
     1188    // solve a constrained potential if we are meant to
     1189    if (DoConstrained) {
     1190      ConstrainedPotentialEnergy = MinimiseConstrainedPotential(out, &Force, DoConstrained);
     1191    }
     1192   
    10551193    // and perform Verlet integration for each atom with position, velocity and force vector
    10561194    runner = elemente->start;
     
    10671205            // check size of vectors
    10681206            if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) {
    1069               //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl;
     1207              //out << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl;
    10701208              Trajectories[walker].R.resize(MDSteps+10);
    10711209              Trajectories[walker].U.resize(MDSteps+10);
     
    10851223              Trajectories[walker].U.at(MDSteps).x[d] += a * (Trajectories[walker].F.at(MDSteps).x[d]+Trajectories[walker].F.at(MDSteps-1).x[d]);
    10861224            }
    1087 //            cout << "Integrated position&velocity of step " << (MDSteps) << ": (";
     1225//            out << "Integrated position&velocity of step " << (MDSteps) << ": (";
    10881226//            for (int d=0;d<NDIM;d++)
    1089 //              cout << Trajectories[walker].R.at(MDSteps).x[d] << " ";          // next step
    1090 //            cout << ")\t(";
     1227//              out << Trajectories[walker].R.at(MDSteps).x[d] << " ";          // next step
     1228//            out << ")\t(";
    10911229//            for (int d=0;d<NDIM;d++)
    10921230//              cout << Trajectories[walker].U.at(MDSteps).x[d] << " ";          // next step
    1093 //            cout << ")" << endl;
     1231//            out << ")" << endl;
    10941232            // next atom
    10951233            AtomNo++;
Note: See TracChangeset for help on using the changeset viewer.